ty.rs 186.5 KB
Newer Older
V
Virgile Andreani 已提交
1
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
#![allow(non_camel_case_types)]
12

13
use back::svh::Svh;
E
Eduard Burtescu 已提交
14
use driver::session::Session;
K
Keegan McAllister 已提交
15
use lint;
16
use metadata::csearch;
17
use middle::const_eval;
18
use middle::def;
19
use middle::dependency_format;
20
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
21
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
22
use middle::mem_categorization as mc;
23
use middle::resolve;
24
use middle::resolve_lifetime;
A
Aaron Turon 已提交
25
use middle::stability;
26
use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
27
use middle::traits;
28 29
use middle::ty;
use middle::typeck;
30
use middle::ty_fold::{mod, TypeFoldable,TypeFolder};
31
use middle;
32 33
use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
use util::ppaux::{trait_store_to_string, ty_to_string};
34
use util::ppaux::{Repr, UserString};
35
use util::common::{indenter, memoized, memoized_with_key};
36
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet, FnvHashMap};
37

38
use std::cell::{Cell, RefCell};
39
use std::cmp;
40
use std::fmt::{mod, Show};
41
use std::hash::{Hash, sip, Writer};
A
Alex Crichton 已提交
42
use std::mem;
43
use std::ops;
H
Huon Wilson 已提交
44
use std::rc::Rc;
45
use std::collections::{HashMap, HashSet};
46
use std::collections::hash_map::{Occupied, Vacant};
47
use arena::TypedArena;
E
Eduard Burtescu 已提交
48
use syntax::abi;
49 50 51 52
use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
use syntax::ast::{Visibility};
J
Jakub Bukaj 已提交
53
use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod};
54
use syntax::attr::{mod, AttrMetaMethods};
55
use syntax::codemap::Span;
56
use syntax::parse::token::{mod, InternedString};
57
use syntax::{ast, ast_map};
58
use std::collections::enum_set::{EnumSet, CLike};
59

60 61
pub type Disr = u64;

62
pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
63

64
// Data types
65

66
#[deriving(PartialEq, Eq, Hash)]
67
pub struct field {
68
    pub name: ast::Name,
69
    pub mt: mt
70
}
71

L
Luqman Aden 已提交
72
#[deriving(Clone, Show)]
73
pub enum ImplOrTraitItemContainer {
74 75
    TraitContainer(ast::DefId),
    ImplContainer(ast::DefId),
76 77
}

78 79 80 81 82 83 84 85 86 87 88 89
impl ImplOrTraitItemContainer {
    pub fn id(&self) -> ast::DefId {
        match *self {
            TraitContainer(id) => id,
            ImplContainer(id) => id,
        }
    }
}

#[deriving(Clone)]
pub enum ImplOrTraitItem {
    MethodTraitItem(Rc<Method>),
90
    TypeTraitItem(Rc<AssociatedType>),
91 92 93 94 95 96
}

impl ImplOrTraitItem {
    fn id(&self) -> ImplOrTraitItemId {
        match *self {
            MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
97 98 99
            TypeTraitItem(ref associated_type) => {
                TypeTraitItemId(associated_type.def_id)
            }
100 101 102 103 104 105
        }
    }

    pub fn def_id(&self) -> ast::DefId {
        match *self {
            MethodTraitItem(ref method) => method.def_id,
106
            TypeTraitItem(ref associated_type) => associated_type.def_id,
107 108 109
        }
    }

110
    pub fn name(&self) -> ast::Name {
111
        match *self {
112 113
            MethodTraitItem(ref method) => method.name,
            TypeTraitItem(ref associated_type) => associated_type.name,
114 115 116 117 118 119
        }
    }

    pub fn container(&self) -> ImplOrTraitItemContainer {
        match *self {
            MethodTraitItem(ref method) => method.container,
120
            TypeTraitItem(ref associated_type) => associated_type.container,
121 122
        }
    }
123 124 125 126 127 128 129

    pub fn as_opt_method(&self) -> Option<Rc<Method>> {
        match *self {
            MethodTraitItem(ref m) => Some((*m).clone()),
            TypeTraitItem(_) => None
        }
    }
130 131 132 133 134
}

#[deriving(Clone)]
pub enum ImplOrTraitItemId {
    MethodTraitItemId(ast::DefId),
135
    TypeTraitItemId(ast::DefId),
136 137 138 139 140 141
}

impl ImplOrTraitItemId {
    pub fn def_id(&self) -> ast::DefId {
        match *self {
            MethodTraitItemId(def_id) => def_id,
142
            TypeTraitItemId(def_id) => def_id,
143 144 145 146
        }
    }
}

L
Luqman Aden 已提交
147
#[deriving(Clone, Show)]
148
pub struct Method {
149
    pub name: ast::Name,
150 151
    pub generics: ty::Generics,
    pub fty: BareFnTy,
152
    pub explicit_self: ExplicitSelfCategory,
153 154
    pub vis: ast::Visibility,
    pub def_id: ast::DefId,
155
    pub container: ImplOrTraitItemContainer,
156 157

    // If this method is provided, we need to know where it came from
158
    pub provided_source: Option<ast::DefId>
159
}
160

161
impl Method {
162
    pub fn new(name: ast::Name,
163 164
               generics: ty::Generics,
               fty: BareFnTy,
165
               explicit_self: ExplicitSelfCategory,
166
               vis: ast::Visibility,
167
               def_id: ast::DefId,
168
               container: ImplOrTraitItemContainer,
169
               provided_source: Option<ast::DefId>)
170
               -> Method {
171
       Method {
172
            name: name,
173 174 175 176
            generics: generics,
            fty: fty,
            explicit_self: explicit_self,
            vis: vis,
177
            def_id: def_id,
178
            container: container,
179
            provided_source: provided_source
180 181
        }
    }
182

183
    pub fn container_id(&self) -> ast::DefId {
184 185 186 187 188
        match self.container {
            TraitContainer(id) => id,
            ImplContainer(id) => id,
        }
    }
189 190
}

191 192
#[deriving(Clone)]
pub struct AssociatedType {
193
    pub name: ast::Name,
194 195 196 197 198
    pub vis: ast::Visibility,
    pub def_id: ast::DefId,
    pub container: ImplOrTraitItemContainer,
}

B
Ben Gamari 已提交
199
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
200
pub struct mt {
201 202
    pub ty: t,
    pub mutbl: ast::Mutability,
203
}
204

205
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
206
pub enum TraitStore {
207
    /// Box<Trait>
208 209 210
    UniqTraitStore,
    /// &Trait and &mut Trait
    RegionTraitStore(Region, ast::Mutability),
211 212
}

B
Ben Gamari 已提交
213
#[deriving(Clone, Show)]
214
pub struct field_ty {
215 216 217
    pub name: Name,
    pub id: DefId,
    pub vis: ast::Visibility,
218
    pub origin: ast::DefId,  // The DefId of the struct in which the field is declared.
219
}
T
Tim Chevalier 已提交
220

221 222
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
223
#[deriving(PartialEq, Eq, Hash)]
224
pub struct creader_cache_key {
225 226 227
    pub cnum: CrateNum,
    pub pos: uint,
    pub len: uint
228
}
229

230
pub type creader_cache = RefCell<HashMap<creader_cache_key, t>>;
231

232
pub struct intern_key {
233
    sty: *const sty,
234
}
235

236
// NB: Do not replace this with #[deriving(PartialEq)]. The automatically-derived
237 238
// implementation will not recurse through sty and you will get stack
// exhaustion.
239
impl cmp::PartialEq for intern_key {
240
    fn eq(&self, other: &intern_key) -> bool {
241
        unsafe {
242
            *self.sty == *other.sty
243
        }
244
    }
245
    fn ne(&self, other: &intern_key) -> bool {
246 247
        !self.eq(other)
    }
248
}
249

250
impl Eq for intern_key {}
D
Daniel Micay 已提交
251

252 253 254
impl<W:Writer> Hash<W> for intern_key {
    fn hash(&self, s: &mut W) {
        unsafe { (*self.sty).hash(s) }
255 256
    }
}
257

258
pub enum ast_ty_to_ty_cache_entry {
259
    atttce_unresolved,  /* not resolved yet */
260
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
261 262
}

263
#[deriving(Clone, PartialEq, Decodable, Encodable)]
264
pub struct ItemVariances {
265 266
    pub types: VecPerParamSpace<Variance>,
    pub regions: VecPerParamSpace<Variance>,
267
}
268

269
#[deriving(Clone, PartialEq, Decodable, Encodable, Show)]
270
pub enum Variance {
271 272 273 274
    Covariant,      // T<A> <: T<B> iff A <: B -- e.g., function return type
    Invariant,      // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
    Contravariant,  // T<A> <: T<B> iff B <: A -- e.g., function param type
    Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
275
}
276

L
Luqman Aden 已提交
277
#[deriving(Clone, Show)]
278
pub enum AutoAdjustment {
279 280
    AdjustAddEnv(ty::TraitStore),
    AdjustDerefRef(AutoDerefRef)
281 282
}

L
Luqman Aden 已提交
283
#[deriving(Clone, PartialEq, Show)]
N
Nick Cameron 已提交
284 285 286 287 288 289
pub enum UnsizeKind {
    // [T, ..n] -> [T], the uint field is n.
    UnsizeLength(uint),
    // An unsize coercion applied to the tail field of a struct.
    // The uint is the index of the type parameter which is unsized.
    UnsizeStruct(Box<UnsizeKind>, uint),
290
    UnsizeVtable(TyTrait, /* the self type of the trait */ ty::t)
N
Nick Cameron 已提交
291 292
}

L
Luqman Aden 已提交
293
#[deriving(Clone, Show)]
294
pub struct AutoDerefRef {
295 296
    pub autoderefs: uint,
    pub autoref: Option<AutoRef>
297
}
298

L
Luqman Aden 已提交
299
#[deriving(Clone, PartialEq, Show)]
N
Niko Matsakis 已提交
300
pub enum AutoRef {
301
    /// Convert from T to &T
N
Nick Cameron 已提交
302 303
    /// The third field allows us to wrap other AutoRef adjustments.
    AutoPtr(Region, ast::Mutability, Option<Box<AutoRef>>),
304

N
Nick Cameron 已提交
305 306
    /// Convert [T, ..n] to [T] (or similar, depending on the kind)
    AutoUnsize(UnsizeKind),
307

N
Nick Cameron 已提交
308 309 310
    /// Convert Box<[T, ..n]> to Box<[T]> or something similar in a Box.
    /// With DST and Box a library type, this should be replaced by UnsizeStruct.
    AutoUnsizeUniq(UnsizeKind),
311

N
Niko Matsakis 已提交
312
    /// Convert from T to *T
N
Nick Cameron 已提交
313
    /// Value to thin pointer
314 315
    /// The second field allows us to wrap other AutoRef adjustments.
    AutoUnsafe(ast::Mutability, Option<Box<AutoRef>>),
N
Nick Cameron 已提交
316 317
}

N
Nick Cameron 已提交
318 319 320 321 322
// Ugly little helper function. The first bool in the returned tuple is true if
// there is an 'unsize to trait object' adjustment at the bottom of the
// adjustment. If that is surrounded by an AutoPtr, then we also return the
// region of the AutoPtr (in the third argument). The second bool is true if the
// adjustment is unique.
N
Nick Cameron 已提交
323
fn autoref_object_region(autoref: &AutoRef) -> (bool, bool, Option<Region>) {
N
Nick Cameron 已提交
324
    fn unsize_kind_is_object(k: &UnsizeKind) -> bool {
N
Nick Cameron 已提交
325
        match k {
N
Nick Cameron 已提交
326 327 328
            &UnsizeVtable(..) => true,
            &UnsizeStruct(box ref k, _) => unsize_kind_is_object(k),
            _ => false
N
Nick Cameron 已提交
329 330 331 332
        }
    }

    match autoref {
N
Nick Cameron 已提交
333 334
        &AutoUnsize(ref k) => (unsize_kind_is_object(k), false, None),
        &AutoUnsizeUniq(ref k) => (unsize_kind_is_object(k), true, None),
N
Nick Cameron 已提交
335 336 337 338 339 340 341 342
        &AutoPtr(adj_r, _, Some(box ref autoref)) => {
            let (b, u, r) = autoref_object_region(autoref);
            if r.is_some() || u {
                (b, u, r)
            } else {
                (b, u, Some(adj_r))
            }
        }
343
        &AutoUnsafe(_, Some(box ref autoref)) => autoref_object_region(autoref),
N
Nick Cameron 已提交
344 345 346 347 348 349 350 351
        _ => (false, false, None)
    }
}

// If the adjustment introduces a borrowed reference to a trait object, then
// returns the region of the borrowed reference.
pub fn adjusted_object_region(adj: &AutoAdjustment) -> Option<Region> {
    match adj {
352
        &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
N
Nick Cameron 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366
            let (b, _, r) = autoref_object_region(autoref);
            if b {
                r
            } else {
                None
            }
        }
        _ => None
    }
}

// Returns true if there is a trait cast at the bottom of the adjustment.
pub fn adjust_is_object(adj: &AutoAdjustment) -> bool {
    match adj {
367
        &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
N
Nick Cameron 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380
            let (b, _, _) = autoref_object_region(autoref);
            b
        }
        _ => false
    }
}

// If possible, returns the type expected from the given adjustment. This is not
// possible if the adjustment depends on the type of the adjusted expression.
pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
    fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
        match autoref {
            &AutoUnsize(ref k) => match k {
381
                &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
N
Nick Cameron 已提交
382 383 384 385 386
                    Some(mk_trait(cx, def_id, substs.clone(), bounds))
                }
                _ => None
            },
            &AutoUnsizeUniq(ref k) => match k {
387
                &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
N
Nick Cameron 已提交
388 389 390 391 392 393 394 395 396 397
                    Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
                }
                _ => None
            },
            &AutoPtr(r, m, Some(box ref autoref)) => {
                match type_of_autoref(cx, autoref) {
                    Some(t) => Some(mk_rptr(cx, r, mt {mutbl: m, ty: t})),
                    None => None
                }
            }
398 399 400 401 402 403
            &AutoUnsafe(m, Some(box ref autoref)) => {
                match type_of_autoref(cx, autoref) {
                    Some(t) => Some(mk_ptr(cx, mt {mutbl: m, ty: t})),
                    None => None
                }
            }
N
Nick Cameron 已提交
404 405 406
            _ => None
        }
    }
407

N
Nick Cameron 已提交
408
    match adj {
409
        &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
N
Nick Cameron 已提交
410 411 412 413
            type_of_autoref(cx, autoref)
        }
        _ => None
    }
414 415
}

N
Nick Cameron 已提交
416 417


418 419 420 421 422 423 424 425 426
/// A restriction that certain types must be the same size. The use of
/// `transmute` gives rise to these restrictions.
pub struct TransmuteRestriction {
    /// The span from whence the restriction comes.
    pub span: Span,
    /// The type being transmuted from.
    pub from: t,
    /// The type being transmuted to.
    pub to: t,
N
Nick Cameron 已提交
427 428
    /// NodeIf of the transmute intrinsic.
    pub id: ast::NodeId,
429 430
}

431 432 433
/// The data structure to keep track of all the information that typechecker
/// generates so that so that it can be reused and doesn't have to be redone
/// later on.
434 435 436 437
pub struct ctxt<'tcx> {
    /// The arena that types are allocated from.
    type_arena: &'tcx TypedArena<t_box_>,

438 439
    /// Specifically use a speedy hash algorithm for this hash map, it's used
    /// quite often.
440
    interner: RefCell<FnvHashMap<intern_key, &'tcx t_box_>>,
441 442 443
    pub next_id: Cell<uint>,
    pub sess: Session,
    pub def_map: resolve::DefMap,
444

445
    pub named_region_map: resolve_lifetime::NamedRegionMap,
446

447
    pub region_maps: middle::region::RegionMaps,
448

449 450 451
    /// Stores the types for various nodes in the AST.  Note that this table
    /// is not guaranteed to be populated until after typeck.  See
    /// typeck::check::fn_ctxt for details.
452
    pub node_types: node_type_table,
453

454 455
    /// Stores the type parameters which were substituted to obtain the type
    /// of this node.  This only applies to nodes that refer to entities
J
Joseph Crail 已提交
456
    /// parameterized by type parameters, such as generic fns, types, or
457
    /// other items.
458
    pub item_substs: RefCell<NodeMap<ItemSubsts>>,
459

460 461
    /// Maps from a trait item to the trait item "descriptor"
    pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem>>,
462

463 464
    /// Maps from a trait def-id to a list of the def-ids of its trait items
    pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
465

466 467
    /// A cache for the trait_items() routine
    pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem>>>>,
468

E
Eduard Burtescu 已提交
469
    pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
470

E
Eduard Burtescu 已提交
471 472
    pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
    pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
473

474 475 476 477
    /// Maps from node-id of a trait object cast (like `foo as
    /// Box<Trait>`) to the trait reference.
    pub object_cast_map: typeck::ObjectCastMap,

478
    pub map: ast_map::Map<'tcx>,
479
    pub intrinsic_defs: RefCell<DefIdMap<t>>,
480
    pub freevars: RefCell<FreevarMap>,
481 482
    pub tcache: type_cache,
    pub rcache: creader_cache,
483
    pub short_names_cache: RefCell<HashMap<t, String>>,
484 485 486
    pub needs_unwind_cleanup_cache: RefCell<HashMap<t, bool>>,
    pub tc_cache: RefCell<HashMap<uint, TypeContents>>,
    pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry>>,
E
Eduard Burtescu 已提交
487
    pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo>>>>>,
488
    pub ty_param_defs: RefCell<NodeMap<TypeParameterDef>>,
489
    pub adjustments: RefCell<NodeMap<AutoAdjustment>>,
490
    pub normalized_cache: RefCell<HashMap<t, t>>,
E
Eduard Burtescu 已提交
491
    pub lang_items: middle::lang_items::LanguageItems,
492
    /// A mapping of fake provided method def_ids to the default implementation
493
    pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
E
Eduard Burtescu 已提交
494
    pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
495

496 497
    /// Maps from def-id of a type or region parameter to its
    /// (inferred) variance.
E
Eduard Burtescu 已提交
498
    pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
499

500 501 502
    /// True if the variance has been computed yet; false otherwise.
    pub variance_computed: Cell<bool>,

503 504 505 506
    /// A mapping from the def ID of an enum or struct type to the def ID
    /// of the method that implements its destructor. If the type is not
    /// present in this map, it does not have a destructor. This map is
    /// populated during the coherence phase of typechecking.
507
    pub destructor_for_type: RefCell<DefIdMap<ast::DefId>>,
508

509
    /// A method will be in this list if and only if it is a destructor.
510
    pub destructors: RefCell<DefIdSet>,
511

512
    /// Maps a trait onto a list of impls of that trait.
E
Eduard Burtescu 已提交
513
    pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
514

515 516 517
    /// Maps a DefId of a type to a list of its inherent impls.
    /// Contains implementations of methods that are inherent to a type.
    /// Methods in these implementations don't need to be exported.
518
    pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>,
519

520
    /// Maps a DefId of an impl to a list of its items.
521 522 523
    /// Note that this contains all of the impls that we know about,
    /// including ones in other crates. It's not clear that this is the best
    /// way to do it.
524
    pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
525

526 527
    /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
    /// present in this set can be warned about.
528
    pub used_unsafe: RefCell<NodeSet>,
529

530 531 532
    /// Set of nodes which mark locals as mutable which end up getting used at
    /// some point. Local variable definitions not in this set can be warned
    /// about.
533
    pub used_mut_nodes: RefCell<NodeSet>,
534

535 536
    /// The set of external nominal types whose implementations have been read.
    /// This is used for lazy resolution of methods.
537
    pub populated_external_types: RefCell<DefIdSet>,
538

539 540
    /// The set of external traits whose implementations have been read. This
    /// is used for lazy resolution of traits.
541
    pub populated_external_traits: RefCell<DefIdSet>,
A
Alex Crichton 已提交
542

543
    /// Borrows
544
    pub upvar_borrow_map: RefCell<UpvarBorrowMap>,
545

546 547
    /// These two caches are used by const_eval when decoding external statics
    /// and variants that are found.
548 549
    pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
    pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
550 551

    pub method_map: typeck::MethodMap,
552 553

    pub dependency_formats: RefCell<dependency_format::Dependencies>,
554

555 556
    /// Records the type of each unboxed closure. The def ID is the ID of the
    /// expression defining the unboxed closure.
557
    pub unboxed_closures: RefCell<DefIdMap<UnboxedClosure>>,
558

559
    pub node_lint_levels: RefCell<HashMap<(ast::NodeId, lint::LintId),
560
                                          lint::LevelSource>>,
561 562 563 564 565

    /// The types that must be asserted to be the same size for `transmute`
    /// to be valid. We gather up these restrictions in the intrinsicck pass
    /// and check them in trans.
    pub transmute_restrictions: RefCell<Vec<TransmuteRestriction>>,
A
Aaron Turon 已提交
566 567 568

    /// Maps any item's def-id to its stability index.
    pub stability: RefCell<stability::Index>,
569 570 571

    /// Maps closures to their capture clauses.
    pub capture_modes: RefCell<CaptureModeMap>,
572 573 574 575 576 577 578

    /// Maps def IDs to true if and only if they're associated types.
    pub associated_types: RefCell<DefIdMap<bool>>,

    /// Maps def IDs of traits to information about their associated types.
    pub trait_associated_types:
        RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
579 580 581 582

    /// Caches the results of trait selection. This cache is used
    /// for things that do not have to do with the parameters in scope.
    pub selection_cache: traits::SelectionCache,
583 584 585

    /// Caches the representation hints for struct definitions.
    pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
586
}
587

588 589 590 591
// Flags that we track on types. These flags are propagated upwards
// through the type during type construction, so that we can quickly
// check whether the type has various kinds of types in it without
// recursing over the type itself.
592 593 594 595 596 597 598 599 600 601 602
bitflags! {
    flags TypeFlags: u32 {
        const NO_TYPE_FLAGS = 0b0,
        const HAS_PARAMS    = 0b1,
        const HAS_SELF      = 0b10,
        const HAS_TY_INFER  = 0b100,
        const HAS_RE_INFER  = 0b1000,
        const HAS_REGIONS   = 0b10000,
        const HAS_TY_ERR    = 0b100000,
        const NEEDS_SUBST   = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
    }
603 604
}

605
pub type t_box = &'static t_box_;
606

B
Ben Gamari 已提交
607
#[deriving(Show)]
608
pub struct t_box_ {
609 610
    pub sty: sty,
    pub id: uint,
611 612 613 614 615 616 617
    pub flags: TypeFlags,
}

impl fmt::Show for TypeFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.bits)
    }
618
}
619

620 621 622 623 624 625
// To reduce refcounting cost, we're representing types as unsafe pointers
// throughout the compiler. These are simply casted t_box values. Use ty::get
// to cast them back to a box. (Without the cast, compiler performance suffers
// ~15%.) This does mean that a t value relies on the ctxt to keep its box
// alive, and using ty::get is unsafe when the ctxt is no longer alive.
enum t_opaque {}
626

627
#[allow(raw_pointer_deriving)]
628
#[deriving(Clone, PartialEq, Eq, Hash)]
629
pub struct t { inner: *const t_opaque }
630 631 632

impl fmt::Show for t {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
633
        write!(f, "{}", get(*self))
634 635 636
    }
}

637
pub fn get(t: t) -> t_box {
638
    unsafe {
A
Alex Crichton 已提交
639
        let t2: t_box = mem::transmute(t);
640
        t2
641
    }
642 643
}

644 645
fn tbox_has_flag(tb: t_box, flag: TypeFlags) -> bool {
    tb.flags.intersects(flag)
646
}
647
pub fn type_has_params(t: t) -> bool {
648
    tbox_has_flag(get(t), HAS_PARAMS)
P
Patrick Walton 已提交
649
}
650 651
pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), HAS_SELF) }
pub fn type_has_ty_infer(t: t) -> bool { tbox_has_flag(get(t), HAS_TY_INFER) }
652
pub fn type_needs_infer(t: t) -> bool {
653
    tbox_has_flag(get(t), HAS_TY_INFER | HAS_RE_INFER)
654
}
655
pub fn type_id(t: t) -> uint { get(t).id }
656

B
Ben Gamari 已提交
657
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
658
pub struct BareFnTy {
659
    pub fn_style: ast::FnStyle,
660 661
    pub abi: abi::Abi,
    pub sig: FnSig,
662 663
}

B
Ben Gamari 已提交
664
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
665
pub struct ClosureTy {
666
    pub fn_style: ast::FnStyle,
667
    pub onceness: ast::Onceness,
668
    pub store: TraitStore,
669
    pub bounds: ExistentialBounds,
670
    pub sig: FnSig,
671
    pub abi: abi::Abi,
672 673
}

J
Jakub Bukaj 已提交
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum FnOutput {
    FnConverging(ty::t),
    FnDiverging
}

impl FnOutput {
    pub fn unwrap(&self) -> ty::t {
        match *self {
            ty::FnConverging(ref t) => *t,
            ty::FnDiverging => unreachable!()
        }
    }
}

689 690 691 692
/**
 * Signature of a function type, which I have arbitrarily
 * decided to use to refer to the input/output types.
 *
693 694 695 696
 * - `binder_id` is the node id where this fn type appeared;
 *   it is used to identify all the bound regions appearing
 *   in the input/output types that are bound by this fn type
 *   (vs some enclosing or enclosed fn type)
697
 * - `inputs` is the list of arguments and their modes.
698 699 700
 * - `output` is the return type.
 * - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
 */
701
#[deriving(Clone, PartialEq, Eq, Hash)]
702
pub struct FnSig {
703 704
    pub binder_id: ast::NodeId,
    pub inputs: Vec<t>,
J
Jakub Bukaj 已提交
705
    pub output: FnOutput,
706
    pub variadic: bool
707 708
}

B
Ben Gamari 已提交
709
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
710 711
pub struct ParamTy {
    pub space: subst::ParamSpace,
712 713
    pub idx: uint,
    pub def_id: DefId
714
}
715

716
/// Representation of regions:
717
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
718
pub enum Region {
719 720 721
    // Region bound in a type or fn declaration which will be
    // substituted 'early' -- that is, at the same time when type
    // parameters are substituted.
722 723 724 725
    ReEarlyBound(/* param id */ ast::NodeId,
                 subst::ParamSpace,
                 /*index*/ uint,
                 ast::Name),
726

727 728 729 730
    // Region bound in a function scope, which will be substituted when the
    // function is called. The first argument must be the `binder_id` of
    // some enclosing function signature.
    ReLateBound(/* binder_id */ ast::NodeId, BoundRegion),
731 732 733 734

    /// When checking a function body, the types of all arguments and so forth
    /// that refer to bound region parameters are modified to refer to free
    /// region parameters.
735
    ReFree(FreeRegion),
736 737

    /// A concrete region naming some expression within the current function.
738
    ReScope(NodeId),
739

N
Niko Matsakis 已提交
740
    /// Static data that has an "infinite" lifetime. Top in the region lattice.
741
    ReStatic,
742 743

    /// A region variable.  Should not exist after typeck.
744
    ReInfer(InferRegion),
N
Niko Matsakis 已提交
745 746

    /// Empty lifetime is for data that is never accessed.
747
    /// Bottom in the region lattice. We treat ReEmpty somewhat
N
Niko Matsakis 已提交
748 749 750
    /// specially; at least right now, we do not generate instances of
    /// it during the GLB computations, but rather
    /// generate an error instead. This is to improve error messages.
751
    /// The only way to get an instance of ReEmpty is to have a region
N
Niko Matsakis 已提交
752
    /// variable with no constraints.
753
    ReEmpty,
N
Niko Matsakis 已提交
754 755
}

756 757 758 759 760
/**
 * Upvars do not get their own node-id. Instead, we use the pair of
 * the original var id (that is, the root variable that is referenced
 * by the upvar) and the id of the closure expression.
 */
L
Luqman Aden 已提交
761
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
762
pub struct UpvarId {
763 764
    pub var_id: ast::NodeId,
    pub closure_expr_id: ast::NodeId,
765 766
}

767
#[deriving(Clone, PartialEq, Eq, Hash, Show, Encodable, Decodable)]
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
pub enum BorrowKind {
    /// Data must be immutable and is aliasable.
    ImmBorrow,

    /// Data must be immutable but not aliasable.  This kind of borrow
    /// cannot currently be expressed by the user and is used only in
    /// implicit closure bindings. It is needed when you the closure
    /// is borrowing or mutating a mutable referent, e.g.:
    ///
    ///    let x: &mut int = ...;
    ///    let y = || *x += 5;
    ///
    /// If we were to try to translate this closure into a more explicit
    /// form, we'd encounter an error with the code as written:
    ///
    ///    struct Env { x: & &mut int }
    ///    let x: &mut int = ...;
    ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
    ///
    /// This is then illegal because you cannot mutate a `&mut` found
    /// in an aliasable location. To solve, you'd have to translate with
    /// an `&mut` borrow:
    ///
    ///    struct Env { x: & &mut int }
    ///    let x: &mut int = ...;
    ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
    ///
    /// Now the assignment to `**env.x` is legal, but creating a
    /// mutable pointer to `x` is not because `x` is not mutable. We
    /// could fix this by declaring `x` as `let mut x`. This is ok in
    /// user code, if awkward, but extra weird for closures, since the
    /// borrow is hidden.
    ///
    /// So we introduce a "unique imm" borrow -- the referent is
    /// immutable, but not aliasable. This solves the problem. For
    /// simplicity, we don't give users the way to express this
    /// borrow, it's just used when translating closures.
    UniqueImmBorrow,

    /// Data is mutable and not aliasable.
    MutBorrow
}

/**
 * Information describing the borrowing of an upvar. This is computed
 * during `typeck`, specifically by `regionck`. The general idea is
 * that the compiler analyses treat closures like:
 *
 *     let closure: &'e fn() = || {
 *        x = 1;   // upvar x is assigned to
 *        use(y);  // upvar y is read
 *        foo(&z); // upvar z is borrowed immutably
 *     };
 *
 * as if they were "desugared" to something loosely like:
 *
 *     struct Vars<'x,'y,'z> { x: &'x mut int,
 *                             y: &'y const int,
 *                             z: &'z int }
 *     let closure: &'e fn() = {
 *         fn f(env: &Vars) {
 *             *env.x = 1;
 *             use(*env.y);
 *             foo(env.z);
 *         }
 *         let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
 *                                                       y: &'y const y,
 *                                                       z: &'z z };
 *         (env, f)
 *     };
 *
 * This is basically what happens at runtime. The closure is basically
 * an existentially quantified version of the `(env, f)` pair.
 *
 * This data structure indicates the region and mutability of a single
 * one of the `x...z` borrows.
 *
 * It may not be obvious why each borrowed variable gets its own
 * lifetime (in the desugared version of the example, these are indicated
 * by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
 * Each such lifetime must encompass the lifetime `'e` of the closure itself,
 * but need not be identical to it. The reason that this makes sense:
 *
 * - Callers are only permitted to invoke the closure, and hence to
 *   use the pointers, within the lifetime `'e`, so clearly `'e` must
 *   be a sublifetime of `'x...'z`.
 * - The closure creator knows which upvars were borrowed by the closure
 *   and thus `x...z` will be reserved for `'x...'z` respectively.
858
 * - Through mutation, the borrowed upvars can actually escape
859 860 861
 *   the closure, so sometimes it is necessary for them to be larger
 *   than the closure lifetime itself.
 */
L
Luqman Aden 已提交
862
#[deriving(PartialEq, Clone, Encodable, Decodable, Show)]
863
pub struct UpvarBorrow {
864 865
    pub kind: BorrowKind,
    pub region: ty::Region,
866 867 868 869
}

pub type UpvarBorrowMap = HashMap<UpvarId, UpvarBorrow>;

870 871
impl Region {
    pub fn is_bound(&self) -> bool {
872
        match self {
A
Alex Crichton 已提交
873 874
            &ty::ReEarlyBound(..) => true,
            &ty::ReLateBound(..) => true,
875 876 877 878 879
            _ => false
        }
    }
}

880
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
881
pub struct FreeRegion {
882 883
    pub scope_id: NodeId,
    pub bound_region: BoundRegion
884 885
}

886
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
887
pub enum BoundRegion {
888
    /// An anonymous region parameter for a given fn (&T)
889
    BrAnon(uint),
890

891
    /// Named region parameters for functions (a in &'a T)
892 893 894
    ///
    /// The def-id is needed to distinguish free regions in
    /// the event of shadowing.
895
    BrNamed(ast::DefId, ast::Name),
896

897
    /// Fresh bound identifiers created during GLB computations.
898
    BrFresh(uint),
899 900 901 902

    // Anonymous region for the implicit env pointer parameter
    // to a closure
    BrEnv
903 904
}

905
mod primitives {
906
    use super::t_box_;
907 908 909 910 911 912 913 914

    use syntax::ast;

    macro_rules! def_prim_ty(
        ($name:ident, $sty:expr, $id:expr) => (
            pub static $name: t_box_ = t_box_ {
                sty: $sty,
                id: $id,
915
                flags: super::NO_TYPE_FLAGS,
916 917 918 919 920 921
            };
        )
    )

    def_prim_ty!(TY_NIL,    super::ty_nil,                  0)
    def_prim_ty!(TY_BOOL,   super::ty_bool,                 1)
922
    def_prim_ty!(TY_CHAR,   super::ty_char,                 2)
923 924 925 926 927 928 929 930 931 932 933 934
    def_prim_ty!(TY_INT,    super::ty_int(ast::TyI),        3)
    def_prim_ty!(TY_I8,     super::ty_int(ast::TyI8),       4)
    def_prim_ty!(TY_I16,    super::ty_int(ast::TyI16),      5)
    def_prim_ty!(TY_I32,    super::ty_int(ast::TyI32),      6)
    def_prim_ty!(TY_I64,    super::ty_int(ast::TyI64),      7)
    def_prim_ty!(TY_UINT,   super::ty_uint(ast::TyU),       8)
    def_prim_ty!(TY_U8,     super::ty_uint(ast::TyU8),      9)
    def_prim_ty!(TY_U16,    super::ty_uint(ast::TyU16),     10)
    def_prim_ty!(TY_U32,    super::ty_uint(ast::TyU32),     11)
    def_prim_ty!(TY_U64,    super::ty_uint(ast::TyU64),     12)
    def_prim_ty!(TY_F32,    super::ty_float(ast::TyF32),    14)
    def_prim_ty!(TY_F64,    super::ty_float(ast::TyF64),    15)
935 936 937 938

    pub static TY_ERR: t_box_ = t_box_ {
        sty: super::ty_err,
        id: 17,
939
        flags: super::HAS_TY_ERR,
940 941
    };

942
    pub const LAST_PRIMITIVE_ID: uint = 18;
943 944
}

945
// NB: If you change this, you'll probably want to change the corresponding
946
// AST structure in libsyntax/ast.rs as well.
B
Ben Gamari 已提交
947
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
948
pub enum sty {
P
Patrick Walton 已提交
949 950
    ty_nil,
    ty_bool,
951
    ty_char,
952 953 954
    ty_int(ast::IntTy),
    ty_uint(ast::UintTy),
    ty_float(ast::FloatTy),
955 956 957
    /// Substs here, possibly against intuition, *may* contain `ty_param`s.
    /// That is, even after substitution it is possible that there are type
    /// variables. This happens when the `ty_enum` corresponds to an enum
958
    /// definition and not a concrete use of it. To get the correct `ty_enum`
959 960 961
    /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
    /// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
    /// well.`
962
    ty_enum(DefId, Substs),
963
    ty_uniq(t),
964
    ty_str,
N
Nick Cameron 已提交
965
    ty_vec(t, Option<uint>), // Second field is length.
P
Patrick Walton 已提交
966
    ty_ptr(mt),
967
    ty_rptr(Region, mt),
968
    ty_bare_fn(BareFnTy),
969 970
    ty_closure(Box<ClosureTy>),
    ty_trait(Box<TyTrait>),
971
    ty_struct(DefId, Substs),
972
    ty_unboxed_closure(DefId, Region, Substs),
973
    ty_tup(Vec<t>),
P
Patrick Walton 已提交
974

975
    ty_param(ParamTy), // type parameter
N
Nick Cameron 已提交
976 977 978 979 980 981
    ty_open(t),  // A deref'ed fat pointer, i.e., a dynamically sized value
                 // and its size. Only ever used in trans. It is not necessary
                 // earlier since we don't need to distinguish a DST with its
                 // size (e.g., in a deref) vs a DST with the size elsewhere (
                 // e.g., in a field).

982
    ty_infer(InferTy), // something used only during inference/typeck
983 984 985
    ty_err, // Also only used during inference/typeck, to represent
            // the type of an erroneous expression (helps cut down
            // on non-useful type error messages)
986 987
}

B
Ben Gamari 已提交
988
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
989
pub struct TyTrait {
990
    pub def_id: DefId,
991
    pub substs: Substs,
992
    pub bounds: ExistentialBounds
993 994
}

B
Ben Gamari 已提交
995
#[deriving(PartialEq, Eq, Hash, Show)]
996
pub struct TraitRef {
997
    pub def_id: DefId,
998
    pub substs: Substs,
999 1000
}

1001
#[deriving(Clone, PartialEq)]
1002
pub enum IntVarValue {
1003 1004
    IntType(ast::IntTy),
    UintType(ast::UintTy),
1005 1006
}

1007
#[deriving(Clone, Show)]
1008
pub enum terr_vstore_kind {
1009 1010 1011 1012
    terr_vec,
    terr_str,
    terr_fn,
    terr_trait
1013 1014
}

1015
#[deriving(Clone, Show)]
1016
pub struct expected_found<T> {
1017 1018
    pub expected: T,
    pub found: T
1019 1020
}

1021
// Data structures used in type unification
1022
#[deriving(Clone, Show)]
1023
pub enum type_err {
P
Patrick Walton 已提交
1024
    terr_mismatch,
1025
    terr_fn_style_mismatch(expected_found<FnStyle>),
1026
    terr_onceness_mismatch(expected_found<Onceness>),
1027
    terr_abi_mismatch(expected_found<abi::Abi>),
1028
    terr_mutability,
1029
    terr_sigil_mismatch(expected_found<TraitStore>),
P
Patrick Walton 已提交
1030
    terr_box_mutability,
M
Marijn Haverbeke 已提交
1031
    terr_ptr_mutability,
1032
    terr_ref_mutability,
P
Patrick Walton 已提交
1033
    terr_vec_mutability,
1034
    terr_tuple_size(expected_found<uint>),
1035
    terr_fixed_array_size(expected_found<uint>),
1036
    terr_ty_param_size(expected_found<uint>),
P
Patrick Walton 已提交
1037
    terr_arg_count,
1038 1039 1040
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
1041 1042
    terr_regions_insufficiently_polymorphic(BoundRegion, Region),
    terr_regions_overly_polymorphic(BoundRegion, Region),
1043
    terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
1044
    terr_sorts(expected_found<t>),
1045
    terr_integer_as_char,
1046
    terr_int_mismatch(expected_found<IntVarValue>),
1047
    terr_float_mismatch(expected_found<ast::FloatTy>),
1048
    terr_traits(expected_found<ast::DefId>),
1049
    terr_builtin_bounds(expected_found<BuiltinBounds>),
1050 1051
    terr_variadic_mismatch(expected_found<bool>),
    terr_cyclic_ty,
J
Jakub Bukaj 已提交
1052
    terr_convergence_mismatch(expected_found<bool>)
1053 1054
}

1055 1056 1057
/// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
/// as well as the existential type parameter in an object type.
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
1058
pub struct ParamBounds {
1059
    pub region_bounds: Vec<ty::Region>,
1060
    pub builtin_bounds: BuiltinBounds,
E
Eduard Burtescu 已提交
1061
    pub trait_bounds: Vec<Rc<TraitRef>>
E
Eduard Burtescu 已提交
1062
}
1063

1064 1065 1066
/// Bounds suitable for an existentially quantified type parameter
/// such as those that appear in object types or closure types. The
/// major difference between this case and `ParamBounds` is that
1067 1068
/// general purpose trait bounds are omitted and there must be
/// *exactly one* region.
1069 1070 1071 1072 1073 1074
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
pub struct ExistentialBounds {
    pub region_bound: ty::Region,
    pub builtin_bounds: BuiltinBounds
}

1075 1076
pub type BuiltinBounds = EnumSet<BuiltinBound>;

1077
#[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
1078
#[repr(uint)]
1079
pub enum BuiltinBound {
1080
    BoundSend,
1081
    BoundSized,
F
Flavio Percoco 已提交
1082
    BoundCopy,
A
Alex Crichton 已提交
1083
    BoundSync,
1084 1085
}

K
Kevin Butler 已提交
1086
pub fn empty_builtin_bounds() -> BuiltinBounds {
1087 1088 1089
    EnumSet::empty()
}

K
Kevin Butler 已提交
1090
pub fn all_builtin_bounds() -> BuiltinBounds {
1091
    let mut set = EnumSet::empty();
1092
    set.add(BoundSend);
1093
    set.add(BoundSized);
A
Alex Crichton 已提交
1094
    set.add(BoundSync);
1095 1096 1097
    set
}

1098 1099 1100 1101 1102 1103 1104 1105 1106
pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
    /*!
     * An existential bound that does not implement any traits.
     */

    ty::ExistentialBounds { region_bound: r,
                            builtin_bounds: empty_builtin_bounds() }
}

1107
impl CLike for BuiltinBound {
1108
    fn to_uint(&self) -> uint {
1109 1110
        *self as uint
    }
1111
    fn from_uint(v: uint) -> BuiltinBound {
A
Alex Crichton 已提交
1112
        unsafe { mem::transmute(v) }
1113
    }
1114 1115
}

1116
#[deriving(Clone, PartialEq, Eq, Hash)]
1117 1118 1119
pub struct TyVid {
    pub index: uint
}
1120

1121
#[deriving(Clone, PartialEq, Eq, Hash)]
1122 1123 1124
pub struct IntVid {
    pub index: uint
}
1125

1126
#[deriving(Clone, PartialEq, Eq, Hash)]
1127 1128 1129
pub struct FloatVid {
    pub index: uint
}
1130

1131
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
1132
pub struct RegionVid {
1133
    pub index: uint
1134
}
N
Niko Matsakis 已提交
1135

1136
#[deriving(Clone, PartialEq, Eq, Hash)]
1137
pub enum InferTy {
1138
    TyVar(TyVid),
1139
    IntVar(IntVid),
1140 1141 1142 1143 1144 1145 1146
    FloatVar(FloatVid),
    SkolemizedTy(uint),

    // FIXME -- once integral fallback is impl'd, we should remove
    // this type. It's only needed to prevent spurious errors for
    // integers whose type winds up never being constrained.
    SkolemizedIntTy(uint),
1147 1148
}

1149
#[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
1150
pub enum InferRegion {
1151
    ReVar(RegionVid),
1152
    ReSkolemized(uint, BoundRegion)
1153 1154
}

1155
impl cmp::PartialEq for InferRegion {
1156
    fn eq(&self, other: &InferRegion) -> bool {
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
1167
    fn ne(&self, other: &InferRegion) -> bool {
1168 1169
        !((*self) == (*other))
    }
1170 1171
}

1172
impl fmt::Show for TyVid {
1173
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
1174
        write!(f, "<generic #{}>", self.index)
1175
    }
N
Niko Matsakis 已提交
1176 1177
}

1178
impl fmt::Show for IntVid {
1179
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1180
        write!(f, "<generic integer #{}>", self.index)
1181
    }
1182 1183
}

1184
impl fmt::Show for FloatVid {
1185
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1186
        write!(f, "<generic float #{}>", self.index)
1187
    }
1188 1189
}

1190 1191
impl fmt::Show for RegionVid {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1192
        write!(f, "'<generic lifetime #{}>", self.index)
1193
    }
1194
}
1195

1196 1197
impl fmt::Show for FnSig {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1198
        // grr, without tcx not much we can do.
A
Alex Crichton 已提交
1199
        write!(f, "(...)")
1200 1201 1202
    }
}

1203 1204
impl fmt::Show for InferTy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1205
        match *self {
1206 1207 1208
            TyVar(ref v) => v.fmt(f),
            IntVar(ref v) => v.fmt(f),
            FloatVar(ref v) => v.fmt(f),
1209 1210
            SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
            SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
1211
        }
N
Niko Matsakis 已提交
1212 1213 1214
    }
}

1215 1216
impl fmt::Show for IntVarValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1217
        match *self {
1218 1219
            IntType(ref v) => v.fmt(f),
            UintType(ref v) => v.fmt(f),
1220
        }
1221 1222
    }
}
1223

B
Ben Gamari 已提交
1224
#[deriving(Clone, Show)]
1225
pub struct TypeParameterDef {
1226
    pub name: ast::Name,
1227
    pub def_id: ast::DefId,
1228 1229
    pub space: subst::ParamSpace,
    pub index: uint,
1230
    pub associated_with: Option<ast::DefId>,
1231 1232
    pub bounds: ParamBounds,
    pub default: Option<ty::t>,
1233 1234
}

B
Ben Gamari 已提交
1235
#[deriving(Encodable, Decodable, Clone, Show)]
1236
pub struct RegionParameterDef {
1237 1238
    pub name: ast::Name,
    pub def_id: ast::DefId,
1239 1240
    pub space: subst::ParamSpace,
    pub index: uint,
1241
    pub bounds: Vec<ty::Region>,
1242 1243
}

1244 1245
/// Information about the type/lifetime parameters associated with an
/// item or method. Analogous to ast::Generics.
B
Ben Gamari 已提交
1246
#[deriving(Clone, Show)]
1247
pub struct Generics {
1248 1249
    pub types: VecPerParamSpace<TypeParameterDef>,
    pub regions: VecPerParamSpace<RegionParameterDef>,
1250 1251
}

1252
impl Generics {
1253 1254 1255
    pub fn empty() -> Generics {
        Generics { types: VecPerParamSpace::empty(),
                   regions: VecPerParamSpace::empty() }
H
Huon Wilson 已提交
1256
    }
1257 1258

    pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
1259
        !self.types.is_empty_in(space)
1260
    }
1261 1262 1263 1264

    pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
        !self.regions.is_empty_in(space)
    }
1265 1266
}

1267
impl TraitRef {
1268 1269 1270 1271
    pub fn new(def_id: ast::DefId, substs: Substs) -> TraitRef {
        TraitRef { def_id: def_id, substs: substs }
    }

1272 1273 1274
    pub fn self_ty(&self) -> ty::t {
        self.substs.self_ty().unwrap()
    }
N
Niko Matsakis 已提交
1275 1276 1277 1278 1279 1280 1281 1282

    pub fn input_types(&self) -> &[ty::t] {
        // Select only the "input types" from a trait-reference. For
        // now this is all the types that appear in the
        // trait-reference, but it should eventually exclude
        // associated types.
        self.substs.types.as_slice()
    }
1283 1284
}

1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
/// When type checking, we use the `ParameterEnvironment` to track
/// details about the type/lifetime parameters that are in scope.
/// It primarily stores the bounds information.
///
/// Note: This information might seem to be redundant with the data in
/// `tcx.ty_param_defs`, but it is not. That table contains the
/// parameter definitions from an "outside" perspective, but this
/// struct will contain the bounds for a parameter as seen from inside
/// the function body. Currently the only real distinction is that
/// bound lifetime parameters are replaced with free ones, but in the
/// future I hope to refine the representation of types so as to make
/// more distinctions clearer.
pub struct ParameterEnvironment {
    /// A substitution that can be applied to move from
    /// the "outer" view of a type or method to the "inner" view.
    /// In general, this means converting from bound parameters to
    /// free parameters. Since we currently represent bound/free type
1302
    /// parameters in the same way, this only has an effect on regions.
1303
    pub free_substs: Substs,
1304

1305 1306
    /// Bounds on the various type parameters
    pub bounds: VecPerParamSpace<ParamBounds>,
1307 1308 1309 1310 1311 1312

    /// Each type parameter has an implicit region bound that
    /// indicates it must outlive at least the function body (the user
    /// may specify stronger requirements). This field indicates the
    /// region of the callee.
    pub implicit_region_bound: ty::Region,
1313 1314 1315 1316 1317 1318 1319 1320

    /// Obligations that the caller must satisfy. This is basically
    /// the set of bounds on the in-scope type parameters, translated
    /// into Obligations.
    ///
    /// Note: This effectively *duplicates* the `bounds` array for
    /// now.
    pub caller_obligations: VecPerParamSpace<traits::Obligation>,
1321 1322 1323 1324

    /// Caches the results of trait selection. This cache is used
    /// for things that have to do with the parameters in scope.
    pub selection_cache: traits::SelectionCache,
1325 1326
}

1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
impl ParameterEnvironment {
    pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
        match cx.map.find(id) {
            Some(ast_map::NodeImplItem(ref impl_item)) => {
                match **impl_item {
                    ast::MethodImplItem(ref method) => {
                        let method_def_id = ast_util::local_def(id);
                        match ty::impl_or_trait_item(cx, method_def_id) {
                            MethodTraitItem(ref method_ty) => {
                                let method_generics = &method_ty.generics;
                                construct_parameter_environment(
                                    cx,
1339
                                    method.span,
1340 1341 1342
                                    method_generics,
                                    method.pe_body().id)
                            }
1343 1344 1345 1346 1347 1348
                            TypeTraitItem(_) => {
                                cx.sess
                                  .bug("ParameterEnvironment::from_item(): \
                                        can't create a parameter environment \
                                        for type trait items")
                            }
1349 1350
                        }
                    }
1351 1352 1353 1354 1355
                    ast::TypeImplItem(_) => {
                        cx.sess.bug("ParameterEnvironment::from_item(): \
                                     can't create a parameter environment \
                                     for type impl items")
                    }
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373
                }
            }
            Some(ast_map::NodeTraitItem(trait_method)) => {
                match *trait_method {
                    ast::RequiredMethod(ref required) => {
                        cx.sess.span_bug(required.span,
                                         "ParameterEnvironment::from_item():
                                          can't create a parameter \
                                          environment for required trait \
                                          methods")
                    }
                    ast::ProvidedMethod(ref method) => {
                        let method_def_id = ast_util::local_def(id);
                        match ty::impl_or_trait_item(cx, method_def_id) {
                            MethodTraitItem(ref method_ty) => {
                                let method_generics = &method_ty.generics;
                                construct_parameter_environment(
                                    cx,
1374
                                    method.span,
1375 1376 1377
                                    method_generics,
                                    method.pe_body().id)
                            }
1378 1379 1380 1381 1382 1383
                            TypeTraitItem(_) => {
                                cx.sess
                                  .bug("ParameterEnvironment::from_item(): \
                                        can't create a parameter environment \
                                        for type trait items")
                            }
1384 1385
                        }
                    }
1386 1387 1388 1389 1390
                    ast::TypeTraitItem(_) => {
                        cx.sess.bug("ParameterEnvironment::from_item(): \
                                     can't create a parameter environment \
                                     for type trait items")
                    }
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
                }
            }
            Some(ast_map::NodeItem(item)) => {
                match item.node {
                    ast::ItemFn(_, _, _, _, ref body) => {
                        // We assume this is a function.
                        let fn_def_id = ast_util::local_def(id);
                        let fn_pty = ty::lookup_item_type(cx, fn_def_id);

                        construct_parameter_environment(cx,
1401
                                                        item.span,
1402 1403 1404 1405 1406 1407
                                                        &fn_pty.generics,
                                                        body.id)
                    }
                    ast::ItemEnum(..) |
                    ast::ItemStruct(..) |
                    ast::ItemImpl(..) |
1408
                    ast::ItemConst(..) |
1409 1410 1411
                    ast::ItemStatic(..) => {
                        let def_id = ast_util::local_def(id);
                        let pty = ty::lookup_item_type(cx, def_id);
1412 1413
                        construct_parameter_environment(cx, item.span,
                                                        &pty.generics, id)
1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
                    }
                    _ => {
                        cx.sess.span_bug(item.span,
                                         "ParameterEnvironment::from_item():
                                          can't create a parameter \
                                          environment for this kind of item")
                    }
                }
            }
            _ => {
                cx.sess.bug(format!("ParameterEnvironment::from_item(): \
                                     `{}` is not an item",
                                    cx.map.node_to_string(id)).as_slice())
            }
        }
    }
}

1432 1433
/// A polytype.
///
1434 1435 1436
/// - `generics`: the set of type parameters and their bounds
/// - `ty`: the base types, which may reference the parameters defined
///   in `generics`
B
Ben Gamari 已提交
1437
#[deriving(Clone, Show)]
1438
pub struct Polytype {
1439 1440
    pub generics: Generics,
    pub ty: t
1441
}
1442

1443
/// As `Polytype` but for a trait ref.
1444
pub struct TraitDef {
1445 1446 1447 1448 1449
    /// Generic type definitions. Note that `Self` is listed in here
    /// as having a single bound, the trait itself (e.g., in the trait
    /// `Eq`, there is a single bound `Self : Eq`). This is so that
    /// default methods get to assume that the `Self` parameters
    /// implements the trait.
1450
    pub generics: Generics,
1451 1452

    /// The "supertrait" bounds.
1453
    pub bounds: ParamBounds,
E
Eduard Burtescu 已提交
1454
    pub trait_ref: Rc<ty::TraitRef>,
1455 1456
}

1457 1458 1459 1460
/// Records the substitutions used to translate the polytype for an
/// item into the monotype of an item reference.
#[deriving(Clone)]
pub struct ItemSubsts {
1461
    pub substs: Substs,
1462 1463
}

1464
pub type type_cache = RefCell<DefIdMap<Polytype>>;
1465

1466
pub type node_type_table = RefCell<HashMap<uint,t>>;
1467

1468
/// Records information about each unboxed closure.
1469
#[deriving(Clone)]
1470 1471 1472 1473 1474 1475 1476
pub struct UnboxedClosure {
    /// The type of the unboxed closure.
    pub closure_type: ClosureTy,
    /// The kind of unboxed closure this is.
    pub kind: UnboxedClosureKind,
}

L
Luqman Aden 已提交
1477
#[deriving(Clone, PartialEq, Eq, Show)]
1478 1479 1480 1481 1482 1483
pub enum UnboxedClosureKind {
    FnUnboxedClosureKind,
    FnMutUnboxedClosureKind,
    FnOnceUnboxedClosureKind,
}

1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
impl UnboxedClosureKind {
    pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
        let result = match *self {
            FnUnboxedClosureKind => cx.lang_items.require(FnTraitLangItem),
            FnMutUnboxedClosureKind => {
                cx.lang_items.require(FnMutTraitLangItem)
            }
            FnOnceUnboxedClosureKind => {
                cx.lang_items.require(FnOnceTraitLangItem)
            }
        };
        match result {
            Ok(trait_did) => trait_did,
            Err(err) => cx.sess.fatal(err.as_slice()),
        }
    }
}

1502 1503 1504 1505
pub fn mk_ctxt<'tcx>(s: Session,
                     type_arena: &'tcx TypedArena<t_box_>,
                     dm: resolve::DefMap,
                     named_region_map: resolve_lifetime::NamedRegionMap,
1506
                     map: ast_map::Map<'tcx>,
1507 1508
                     freevars: RefCell<FreevarMap>,
                     capture_modes: RefCell<CaptureModeMap>,
1509 1510 1511
                     region_maps: middle::region::RegionMaps,
                     lang_items: middle::lang_items::LanguageItems,
                     stability: stability::Index) -> ctxt<'tcx> {
E
Eduard Burtescu 已提交
1512
    ctxt {
1513 1514
        type_arena: type_arena,
        interner: RefCell::new(FnvHashMap::new()),
1515
        named_region_map: named_region_map,
1516
        item_variance_map: RefCell::new(DefIdMap::new()),
1517
        variance_computed: Cell::new(false),
1518
        next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
1519 1520
        sess: s,
        def_map: dm,
1521
        region_maps: region_maps,
1522
        node_types: RefCell::new(HashMap::new()),
1523
        item_substs: RefCell::new(NodeMap::new()),
1524 1525
        trait_refs: RefCell::new(NodeMap::new()),
        trait_defs: RefCell::new(DefIdMap::new()),
1526
        object_cast_map: RefCell::new(NodeMap::new()),
1527
        map: map,
1528
        intrinsic_defs: RefCell::new(DefIdMap::new()),
1529
        freevars: freevars,
1530
        tcache: RefCell::new(DefIdMap::new()),
1531
        rcache: RefCell::new(HashMap::new()),
1532
        short_names_cache: RefCell::new(HashMap::new()),
1533
        needs_unwind_cleanup_cache: RefCell::new(HashMap::new()),
1534
        tc_cache: RefCell::new(HashMap::new()),
1535 1536
        ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
        enum_var_cache: RefCell::new(DefIdMap::new()),
1537 1538 1539
        impl_or_trait_items: RefCell::new(DefIdMap::new()),
        trait_item_def_ids: RefCell::new(DefIdMap::new()),
        trait_items_cache: RefCell::new(DefIdMap::new()),
1540 1541 1542
        impl_trait_cache: RefCell::new(DefIdMap::new()),
        ty_param_defs: RefCell::new(NodeMap::new()),
        adjustments: RefCell::new(NodeMap::new()),
1543
        normalized_cache: RefCell::new(HashMap::new()),
L
Luqman Aden 已提交
1544
        lang_items: lang_items,
1545
        provided_method_sources: RefCell::new(DefIdMap::new()),
1546
        struct_fields: RefCell::new(DefIdMap::new()),
1547 1548 1549 1550
        destructor_for_type: RefCell::new(DefIdMap::new()),
        destructors: RefCell::new(DefIdSet::new()),
        trait_impls: RefCell::new(DefIdMap::new()),
        inherent_impls: RefCell::new(DefIdMap::new()),
1551
        impl_items: RefCell::new(DefIdMap::new()),
1552 1553 1554 1555
        used_unsafe: RefCell::new(NodeSet::new()),
        used_mut_nodes: RefCell::new(NodeSet::new()),
        populated_external_types: RefCell::new(DefIdSet::new()),
        populated_external_traits: RefCell::new(DefIdSet::new()),
1556
        upvar_borrow_map: RefCell::new(HashMap::new()),
1557 1558
        extern_const_statics: RefCell::new(DefIdMap::new()),
        extern_const_variants: RefCell::new(DefIdMap::new()),
1559
        method_map: RefCell::new(FnvHashMap::new()),
1560
        dependency_formats: RefCell::new(HashMap::new()),
1561
        unboxed_closures: RefCell::new(DefIdMap::new()),
1562
        node_lint_levels: RefCell::new(HashMap::new()),
1563
        transmute_restrictions: RefCell::new(Vec::new()),
1564
        stability: RefCell::new(stability),
1565
        capture_modes: capture_modes,
1566 1567
        associated_types: RefCell::new(DefIdMap::new()),
        trait_associated_types: RefCell::new(DefIdMap::new()),
1568
        selection_cache: traits::SelectionCache::new(),
1569
        repr_hint_cache: RefCell::new(DefIdMap::new()),
1570
   }
1571
}
1572

1573
// Type constructors
1574 1575 1576

// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for t above).
E
Eduard Burtescu 已提交
1577
pub fn mk_t(cx: &ctxt, st: sty) -> t {
1578 1579
    // Check for primitive types.
    match st {
T
Tim Chevalier 已提交
1580 1581 1582 1583 1584 1585
        ty_nil => return mk_nil(),
        ty_err => return mk_err(),
        ty_bool => return mk_bool(),
        ty_int(i) => return mk_mach_int(i),
        ty_uint(u) => return mk_mach_uint(u),
        ty_float(f) => return mk_mach_float(f),
1586
        ty_char => return mk_char(),
1587 1588 1589
        _ => {}
    };

C
Corey Richardson 已提交
1590
    let key = intern_key { sty: &st };
1591

1592
    match cx.interner.borrow().find(&key) {
A
Alex Crichton 已提交
1593
        Some(t) => unsafe { return mem::transmute(&t.sty); },
1594
        _ => ()
1595
    }
1596

1597 1598
    let mut flags = NO_TYPE_FLAGS;
    fn rflags(r: Region) -> TypeFlags {
1599
        HAS_REGIONS | {
1600
            match r {
1601
              ty::ReInfer(_) => HAS_RE_INFER,
1602
              _ => NO_TYPE_FLAGS,
1603
            }
N
Niko Matsakis 已提交
1604 1605
        }
    }
1606 1607
    fn sflags(substs: &Substs) -> TypeFlags {
        let mut f = NO_TYPE_FLAGS;
1608 1609
        let mut i = substs.types.iter();
        for tt in i {
1610
            f = f | get(*tt).flags;
1611
        }
1612
        match substs.regions {
1613 1614
            subst::ErasedRegions => {}
            subst::NonerasedRegions(ref regions) => {
D
Daniel Micay 已提交
1615
                for r in regions.iter() {
1616
                    f = f | rflags(*r)
1617 1618 1619
                }
            }
        }
B
Brian Anderson 已提交
1620
        return f;
N
Niko Matsakis 已提交
1621
    }
1622
    fn flags_for_bounds(bounds: &ExistentialBounds) -> TypeFlags {
1623 1624
        rflags(bounds.region_bound)
    }
1625
    match &st {
1626
      &ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
1627
      &ty_str => {}
T
Tim Chevalier 已提交
1628 1629
      // You might think that we could just return ty_err for
      // any type containing ty_err as a component, and get
1630
      // rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
T
Tim Chevalier 已提交
1631 1632 1633 1634
      // the exception of function types that return bot).
      // But doing so caused sporadic memory corruption, and
      // neither I (tjc) nor nmatsakis could figure out why,
      // so we're doing it this way.
1635
      &ty_err => flags = flags | HAS_TY_ERR,
1636 1637
      &ty_param(ref p) => {
          if p.space == subst::SelfSpace {
1638
              flags = flags | HAS_SELF;
1639
          } else {
1640
              flags = flags | HAS_PARAMS;
1641 1642
          }
      }
1643 1644 1645 1646
      &ty_unboxed_closure(_, ref region, ref substs) => {
          flags = flags | rflags(*region);
          flags = flags | sflags(substs);
      }
1647
      &ty_infer(_) => flags = flags | HAS_TY_INFER,
1648
      &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
1649
          flags = flags | sflags(substs);
1650
      }
1651
      &ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
1652 1653
          flags = flags | sflags(substs);
          flags = flags | flags_for_bounds(bounds);
1654
      }
E
Eduard Burtescu 已提交
1655
      &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
1656
        flags = flags | get(tt).flags
1657
      }
N
Nick Cameron 已提交
1658
      &ty_ptr(ref m) => {
1659
        flags = flags | get(m.ty).flags;
1660
      }
1661
      &ty_rptr(r, ref m) => {
1662 1663
        flags = flags | rflags(r);
        flags = flags | get(m.ty).flags;
M
Marijn Haverbeke 已提交
1664
      }
1665
      &ty_tup(ref ts) => for tt in ts.iter() { flags = flags | get(*tt).flags; },
1666
      &ty_bare_fn(ref f) => {
1667
        for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
J
Jakub Bukaj 已提交
1668 1669 1670
        if let ty::FnConverging(output) = f.sig.output {
            flags = flags | get(output).flags;
        }
1671 1672
      }
      &ty_closure(ref f) => {
1673 1674
        match f.store {
            RegionTraitStore(r, _) => {
1675
                flags = flags | rflags(r);
1676 1677 1678
            }
            _ => {}
        }
1679
        for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
J
Jakub Bukaj 已提交
1680 1681 1682
        if let ty::FnConverging(output) = f.sig.output {
            flags = flags | get(output).flags;
        }
1683
        flags = flags | flags_for_bounds(&f.bounds);
M
Marijn Haverbeke 已提交
1684
      }
1685
    }
1686

1687
    let t = cx.type_arena.alloc(t_box_ {
1688
        sty: st,
1689
        id: cx.next_id.get(),
1690
        flags: flags,
1691
    });
1692

1693
    let sty_ptr = &t.sty as *const sty;
1694

1695
    let key = intern_key {
1696
        sty: sty_ptr,
1697
    };
1698

1699
    cx.interner.borrow_mut().insert(key, t);
1700

1701
    cx.next_id.set(cx.next_id.get() + 1);
1702 1703

    unsafe {
1704
        mem::transmute::<*const sty, t>(sty_ptr)
1705
    }
1706 1707
}

1708
#[inline]
T
Tim Chevalier 已提交
1709
pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1710
    unsafe {
A
Alex Crichton 已提交
1711
        mem::transmute::<&'static t_box_, t>(primitive)
1712 1713
    }
}
P
Patrick Walton 已提交
1714

1715
#[inline]
T
Tim Chevalier 已提交
1716
pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
1717

1718
#[inline]
T
Tim Chevalier 已提交
1719
pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
1720

1721
#[inline]
T
Tim Chevalier 已提交
1722
pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
1723

1724
#[inline]
T
Tim Chevalier 已提交
1725
pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) }
1726

1727
#[inline]
T
Tim Chevalier 已提交
1728
pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) }
1729

1730
#[inline]
T
Tim Chevalier 已提交
1731
pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) }
1732

1733
#[inline]
T
Tim Chevalier 已提交
1734
pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) }
1735

1736
#[inline]
T
Tim Chevalier 已提交
1737
pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) }
1738

1739
#[inline]
T
Tim Chevalier 已提交
1740
pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
1741

1742
#[inline]
T
Tim Chevalier 已提交
1743
pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
1744

1745
#[inline]
T
Tim Chevalier 已提交
1746
pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
1747

1748
#[inline]
T
Tim Chevalier 已提交
1749
pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) }
1750

1751
#[inline]
T
Tim Chevalier 已提交
1752
pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) }
1753

1754
#[inline]
T
Tim Chevalier 已提交
1755
pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) }
1756

1757
#[inline]
T
Tim Chevalier 已提交
1758
pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
1759

1760
pub fn mk_mach_int(tm: ast::IntTy) -> t {
1761
    match tm {
1762 1763 1764 1765 1766
        ast::TyI    => mk_int(),
        ast::TyI8   => mk_i8(),
        ast::TyI16  => mk_i16(),
        ast::TyI32  => mk_i32(),
        ast::TyI64  => mk_i64(),
1767 1768
    }
}
1769

1770
pub fn mk_mach_uint(tm: ast::UintTy) -> t {
1771
    match tm {
1772 1773 1774 1775 1776
        ast::TyU    => mk_uint(),
        ast::TyU8   => mk_u8(),
        ast::TyU16  => mk_u16(),
        ast::TyU32  => mk_u32(),
        ast::TyU64  => mk_u64(),
1777 1778
    }
}
1779

1780
pub fn mk_mach_float(tm: ast::FloatTy) -> t {
1781
    match tm {
1782 1783
        ast::TyF32  => mk_f32(),
        ast::TyF64  => mk_f64(),
1784
    }
1785
}
1786

1787
#[inline]
T
Tim Chevalier 已提交
1788
pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
1789

1790 1791
pub fn mk_str(cx: &ctxt) -> t {
    mk_t(cx, ty_str)
1792 1793 1794 1795 1796
}

pub fn mk_str_slice(cx: &ctxt, r: Region, m: ast::Mutability) -> t {
    mk_rptr(cx, r,
            mt {
1797
                ty: mk_t(cx, ty_str),
1798 1799
                mutbl: m
            })
1800 1801
}

1802
pub fn mk_enum(cx: &ctxt, did: ast::DefId, substs: Substs) -> t {
N
Niko Matsakis 已提交
1803
    // take a copy of substs so that we own the vectors inside
1804
    mk_t(cx, ty_enum(did, substs))
1805
}
1806

E
Eduard Burtescu 已提交
1807
pub fn mk_uniq(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
1808

E
Eduard Burtescu 已提交
1809
pub fn mk_ptr(cx: &ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1810

E
Eduard Burtescu 已提交
1811
pub fn mk_rptr(cx: &ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1812

E
Eduard Burtescu 已提交
1813
pub fn mk_mut_rptr(cx: &ctxt, r: Region, ty: t) -> t {
1814
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
1815
}
E
Eduard Burtescu 已提交
1816
pub fn mk_imm_rptr(cx: &ctxt, r: Region, ty: t) -> t {
1817
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
1818 1819
}

E
Eduard Burtescu 已提交
1820
pub fn mk_mut_ptr(cx: &ctxt, ty: t) -> t {
1821
    mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
1822
}
1823

E
Eduard Burtescu 已提交
1824
pub fn mk_imm_ptr(cx: &ctxt, ty: t) -> t {
1825
    mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
1826 1827
}

E
Eduard Burtescu 已提交
1828
pub fn mk_nil_ptr(cx: &ctxt) -> t {
1829
    mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
1830 1831
}

N
Nick Cameron 已提交
1832 1833
pub fn mk_vec(cx: &ctxt, t: t, sz: Option<uint>) -> t {
    mk_t(cx, ty_vec(t, sz))
1834 1835 1836 1837 1838
}

pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
    mk_rptr(cx, r,
            mt {
N
Nick Cameron 已提交
1839
                ty: mk_vec(cx, tm.ty, None),
1840 1841
                mutbl: tm.mutbl
            })
1842 1843
}

E
Eduard Burtescu 已提交
1844
pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
1845

E
Eduard Burtescu 已提交
1846
pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
1847
    mk_t(cx, ty_closure(box fty))
1848 1849
}

E
Eduard Burtescu 已提交
1850
pub fn mk_bare_fn(cx: &ctxt, fty: BareFnTy) -> t {
1851 1852 1853
    mk_t(cx, ty_bare_fn(fty))
}

E
Eduard Burtescu 已提交
1854
pub fn mk_ctor_fn(cx: &ctxt,
1855 1856 1857
                  binder_id: ast::NodeId,
                  input_tys: &[ty::t],
                  output: ty::t) -> t {
1858
    let input_args = input_tys.iter().map(|t| *t).collect();
1859 1860
    mk_bare_fn(cx,
               BareFnTy {
1861
                   fn_style: ast::NormalFn,
1862
                   abi: abi::Rust,
1863
                   sig: FnSig {
1864
                    binder_id: binder_id,
1865
                    inputs: input_args,
J
Jakub Bukaj 已提交
1866
                    output: ty::FnConverging(output),
1867
                    variadic: false
1868 1869
                   }
                })
1870 1871
}

1872

E
Eduard Burtescu 已提交
1873
pub fn mk_trait(cx: &ctxt,
1874
                did: ast::DefId,
1875
                substs: Substs,
1876 1877
                bounds: ExistentialBounds)
                -> t {
N
Niko Matsakis 已提交
1878
    // take a copy of substs so that we own the vectors inside
1879
    let inner = box TyTrait {
1880 1881 1882 1883 1884
        def_id: did,
        substs: substs,
        bounds: bounds
    };
    mk_t(cx, ty_trait(inner))
1885 1886
}

1887
pub fn mk_struct(cx: &ctxt, struct_id: ast::DefId, substs: Substs) -> t {
N
Niko Matsakis 已提交
1888
    // take a copy of substs so that we own the vectors inside
1889
    mk_t(cx, ty_struct(struct_id, substs))
T
Tim Chevalier 已提交
1890 1891
}

1892
pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId, region: Region, substs: Substs)
1893
                          -> t {
1894
    mk_t(cx, ty_unboxed_closure(closure_id, region, substs))
1895 1896
}

E
Eduard Burtescu 已提交
1897
pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1898

E
Eduard Burtescu 已提交
1899
pub fn mk_int_var(cx: &ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
1900

E
Eduard Burtescu 已提交
1901
pub fn mk_float_var(cx: &ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
1902

E
Eduard Burtescu 已提交
1903
pub fn mk_infer(cx: &ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1904

1905 1906 1907 1908 1909 1910 1911
pub fn mk_param(cx: &ctxt, space: subst::ParamSpace, n: uint, k: DefId) -> t {
    mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
}

pub fn mk_self_type(cx: &ctxt, did: ast::DefId) -> t {
    mk_param(cx, subst::SelfSpace, 0, did)
}
M
Marijn Haverbeke 已提交
1912

1913 1914
pub fn mk_param_from_def(cx: &ctxt, def: &TypeParameterDef) -> t {
    mk_param(cx, def.space, def.index, def.def_id)
1915
}
1916

N
Nick Cameron 已提交
1917 1918
pub fn mk_open(cx: &ctxt, t: t) -> t { mk_t(cx, ty_open(t)) }

1919
pub fn walk_ty(ty: t, f: |t|) {
B
Brian Anderson 已提交
1920
    maybe_walk_ty(ty, |t| { f(t); true });
1921 1922
}

1923
pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
1924 1925 1926
    if !f(ty) {
        return;
    }
1927
    match get(ty).sty {
J
Jakub Bukaj 已提交
1928
        ty_nil | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
1929
        ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
E
Eduard Burtescu 已提交
1930
        ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
N
Nick Cameron 已提交
1931
        ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
1932 1933
            maybe_walk_ty(tm.ty, f);
        }
1934
        ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_unboxed_closure(_, _, ref substs) |
1935
        ty_trait(box TyTrait { ref substs, .. }) => {
1936 1937 1938
            for subty in (*substs).types.iter() {
                maybe_walk_ty(*subty, |x| f(x));
            }
1939 1940 1941 1942
        }
        ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
        ty_bare_fn(ref ft) => {
            for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
J
Jakub Bukaj 已提交
1943 1944 1945
            if let ty::FnConverging(output) = ft.sig.output {
                maybe_walk_ty(output, f);
            }
1946 1947 1948
        }
        ty_closure(ref ft) => {
            for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
J
Jakub Bukaj 已提交
1949 1950 1951
            if let ty::FnConverging(output) = ft.sig.output {
                maybe_walk_ty(output, f);
            }
1952
        }
1953 1954 1955
    }
}

1956
// Folds types from the bottom up.
E
Eduard Burtescu 已提交
1957
pub fn fold_ty(cx: &ctxt, t0: t, fldop: |t| -> t) -> t {
1958 1959
    let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
    f.fold_ty(t0)
1960
}
1961

1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
impl ParamTy {
    pub fn new(space: subst::ParamSpace,
               index: uint,
               def_id: ast::DefId)
               -> ParamTy {
        ParamTy { space: space, idx: index, def_id: def_id }
    }

    pub fn for_self(trait_def_id: ast::DefId) -> ParamTy {
        ParamTy::new(subst::SelfSpace, 0, trait_def_id)
    }

    pub fn for_def(def: &TypeParameterDef) -> ParamTy {
        ParamTy::new(def.space, def.index, def.def_id)
    }

    pub fn to_ty(self, tcx: &ty::ctxt) -> ty::t {
        ty::mk_param(tcx, self.space, self.idx, self.def_id)
    }
1981 1982 1983 1984

    pub fn is_self(&self) -> bool {
        self.space == subst::SelfSpace && self.idx == 0
    }
1985 1986
}

1987 1988
impl ItemSubsts {
    pub fn empty() -> ItemSubsts {
1989
        ItemSubsts { substs: Substs::empty() }
N
Niko Matsakis 已提交
1990
    }
1991

1992
    pub fn is_noop(&self) -> bool {
1993
        self.substs.is_noop()
1994 1995 1996
    }
}

1997
// Type utilities
1998

1999 2000 2001
pub fn type_is_nil(ty: t) -> bool {
    get(ty).sty == ty_nil
}
2002

T
Tim Chevalier 已提交
2003
pub fn type_is_error(ty: t) -> bool {
2004
    get(ty).flags.intersects(HAS_TY_ERR)
T
Tim Chevalier 已提交
2005
}
2006

2007
pub fn type_needs_subst(ty: t) -> bool {
2008
    tbox_has_flag(get(ty), NEEDS_SUBST)
2009 2010
}

2011
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
2012
    tref.substs.types.any(|&t| type_is_error(t))
2013 2014
}

2015
pub fn type_is_ty_var(ty: t) -> bool {
2016
    match get(ty).sty {
J
Jakub Bukaj 已提交
2017 2018
        ty_infer(TyVar(_)) => true,
        _ => false
2019 2020 2021
    }
}

2022
pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
2023

2024 2025
pub fn type_is_self(ty: t) -> bool {
    match get(ty).sty {
2026
        ty_param(ref p) => p.space == subst::SelfSpace,
2027 2028 2029 2030
        _ => false
    }
}

2031
fn type_is_slice(ty: t) -> bool {
2032
    match get(ty).sty {
2033
        ty_ptr(mt) | ty_rptr(_, mt) => match get(mt.ty).sty {
2034
            ty_vec(_, None) | ty_str => true,
2035 2036 2037 2038 2039 2040
            _ => false,
        },
        _ => false
    }
}

2041 2042 2043 2044
pub fn type_is_vec(ty: t) -> bool {
    match get(ty).sty {
        ty_vec(..) => true,
        ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
E
Eduard Burtescu 已提交
2045
        ty_uniq(t) => match get(t).sty {
2046 2047 2048 2049 2050 2051 2052
            ty_vec(_, None) => true,
            _ => false
        },
        _ => false
    }
}

2053
pub fn type_is_structural(ty: t) -> bool {
2054
    match get(ty).sty {
N
Nick Cameron 已提交
2055
      ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
2056
      ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
N
Nick Cameron 已提交
2057
      _ => type_is_slice(ty) | type_is_trait(ty)
2058 2059 2060
    }
}

E
Eduard Burtescu 已提交
2061
pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
S
Seo Sanghyeon 已提交
2062 2063 2064 2065 2066 2067
    match get(ty).sty {
        ty_struct(did, _) => lookup_simd(cx, did),
        _ => false
    }
}

E
Eduard Burtescu 已提交
2068
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
2069
    match get(ty).sty {
N
Nick Cameron 已提交
2070 2071 2072 2073 2074
        ty_vec(ty, _) => ty,
        ty_str => mk_mach_uint(ast::TyU8),
        ty_open(ty) => sequence_element_type(cx, ty),
        _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
                                 ty_to_string(cx, ty)).as_slice()),
2075 2076 2077
    }
}

E
Eduard Burtescu 已提交
2078
pub fn simd_type(cx: &ctxt, ty: t) -> t {
S
Seo Sanghyeon 已提交
2079 2080 2081
    match get(ty).sty {
        ty_struct(did, ref substs) => {
            let fields = lookup_struct_fields(cx, did);
2082
            lookup_field_type(cx, did, fields[0].id, substs)
S
Seo Sanghyeon 已提交
2083
        }
S
Steve Klabnik 已提交
2084
        _ => panic!("simd_type called on invalid type")
S
Seo Sanghyeon 已提交
2085 2086 2087
    }
}

E
Eduard Burtescu 已提交
2088
pub fn simd_size(cx: &ctxt, ty: t) -> uint {
S
Seo Sanghyeon 已提交
2089 2090 2091 2092 2093
    match get(ty).sty {
        ty_struct(did, _) => {
            let fields = lookup_struct_fields(cx, did);
            fields.len()
        }
S
Steve Klabnik 已提交
2094
        _ => panic!("simd_size called on invalid type")
S
Seo Sanghyeon 已提交
2095 2096 2097
    }
}

2098
pub fn type_is_region_ptr(ty: t) -> bool {
2099
    match get(ty).sty {
N
Nick Cameron 已提交
2100
        ty_rptr(..) => true,
2101
        _ => false
2102 2103 2104
    }
}

2105
pub fn type_is_unsafe_ptr(ty: t) -> bool {
2106
    match get(ty).sty {
B
Brian Anderson 已提交
2107 2108
      ty_ptr(_) => return true,
      _ => return false
2109 2110 2111
    }
}

2112
pub fn type_is_unique(ty: t) -> bool {
2113
    match get(ty).sty {
N
Nick Cameron 已提交
2114 2115 2116 2117
        ty_uniq(_) => match get(ty).sty {
            ty_trait(..) => false,
            _ => true
        },
2118
        _ => false
B
Brian Anderson 已提交
2119
    }
2120 2121
}

N
Nick Cameron 已提交
2122 2123
pub fn type_is_fat_ptr(cx: &ctxt, ty: t) -> bool {
    match get(ty).sty {
2124 2125
        ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..})
        | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
N
Nick Cameron 已提交
2126 2127 2128 2129
        _ => false,
    }
}

2130 2131 2132 2133 2134
/*
 A scalar type is one that denotes an atomic datum, with no sub-components.
 (A ty_ptr is scalar because it represents a non-managed pointer, so its
 contents are abstract to rustc.)
*/
2135
pub fn type_is_scalar(ty: t) -> bool {
2136
    match get(ty).sty {
2137
      ty_nil | ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
2138
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
A
Alex Crichton 已提交
2139
      ty_bare_fn(..) | ty_ptr(_) => true,
B
Brian Anderson 已提交
2140
      _ => false
M
Marijn Haverbeke 已提交
2141
    }
2142 2143
}

2144 2145 2146 2147 2148 2149 2150 2151
/// Returns true if this type is a floating point type and false otherwise.
pub fn type_is_floating_point(ty: t) -> bool {
    match get(ty).sty {
        ty_float(_) => true,
        _ => false,
    }
}

E
Eduard Burtescu 已提交
2152
pub fn type_needs_drop(cx: &ctxt, ty: t) -> bool {
2153
    type_contents(cx, ty).needs_drop(cx)
2154 2155
}

2156 2157 2158 2159
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
2160 2161 2162
pub fn type_needs_unwind_cleanup(cx: &ctxt, ty: t) -> bool {
    return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| {
        type_needs_unwind_cleanup_(cx, ty, &mut HashSet::new())
2163
    });
2164

2165 2166 2167 2168 2169 2170 2171 2172 2173
    fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t, tycache: &mut HashSet<t>) -> bool {
        // Prevent infinite recursion
        if !tycache.insert(ty) {
            return false;
        }

        let mut needs_unwind_cleanup = false;
        maybe_walk_ty(ty, |ty| {
            needs_unwind_cleanup |= match get(ty).sty {
J
Jakub Bukaj 已提交
2174
                ty_nil | ty_bool | ty_int(_) | ty_uint(_) |
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
                ty_float(_) | ty_tup(_) | ty_ptr(_) => false,

                ty_enum(did, ref substs) =>
                    enum_variants(cx, did).iter().any(|v|
                        v.args.iter().any(|aty| {
                            let t = aty.subst(cx, substs);
                            type_needs_unwind_cleanup_(cx, t, tycache)
                        })
                    ),

                _ => true
            };
            !needs_unwind_cleanup
        });
        needs_unwind_cleanup
    }
2191
}
2192

2193 2194 2195 2196 2197 2198
/**
 * Type contents is how the type checker reasons about kinds.
 * They track what kinds of things are found within a type.  You can
 * think of them as kind of an "anti-kind".  They track the kinds of values
 * and thinks that are contained in types.  Having a larger contents for
 * a type tends to rule that type *out* from various kinds.  For example,
2199
 * a type that contains a reference is not sendable.
2200 2201 2202 2203 2204
 *
 * The reason we compute type contents and not kinds is that it is
 * easier for me (nmatsakis) to think about what is contained within
 * a type than to think about what is *not* contained within a type.
 */
2205
#[deriving(Clone)]
2206
pub struct TypeContents {
2207
    pub bits: u64
2208
}
2209

2210 2211
macro_rules! def_type_content_sets(
    (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
2212
        #[allow(non_snake_case)]
2213 2214
        mod $mname {
            use middle::ty::TypeContents;
2215
            $(
A
Aaron Turon 已提交
2216
                #[allow(non_upper_case_globals)]
2217
                pub const $name: TypeContents = TypeContents { bits: $bits };
2218
             )+
2219 2220 2221 2222 2223 2224
        }
    }
)

def_type_content_sets!(
    mod TC {
F
Flavio Percoco 已提交
2225
        None                                = 0b0000_0000__0000_0000__0000,
2226 2227

        // Things that are interior to the value (first nibble):
F
Flavio Percoco 已提交
2228
        InteriorUnsized                     = 0b0000_0000__0000_0000__0001,
F
Flavio Percoco 已提交
2229 2230
        InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
        // InteriorAll                         = 0b00000000__00000000__1111,
2231 2232

        // Things that are owned by the value (second and third nibbles):
F
Flavio Percoco 已提交
2233 2234 2235 2236 2237
        OwnsOwned                           = 0b0000_0000__0000_0001__0000,
        OwnsDtor                            = 0b0000_0000__0000_0010__0000,
        OwnsManaged /* see [1] below */     = 0b0000_0000__0000_0100__0000,
        OwnsAffine                          = 0b0000_0000__0000_1000__0000,
        OwnsAll                             = 0b0000_0000__1111_1111__0000,
2238 2239

        // Things that are reachable by the value in any way (fourth nibble):
F
Flavio Percoco 已提交
2240 2241 2242
        ReachesBorrowed                     = 0b0000_0010__0000_0000__0000,
        // ReachesManaged /* see [1] below */  = 0b0000_0100__0000_0000__0000,
        ReachesMutable                      = 0b0000_1000__0000_0000__0000,
2243 2244
        ReachesFfiUnsafe                    = 0b0010_0000__0000_0000__0000,
        ReachesAll                          = 0b0011_1111__0000_0000__0000,
2245

2246 2247 2248 2249 2250
        // Things that cause values to *move* rather than *copy*. This
        // is almost the same as the `Copy` trait, but for managed
        // data -- atm, we consider managed data to copy, not move,
        // but it does not impl Copy as a pure memcpy is not good
        // enough. Yuck.
F
Flavio Percoco 已提交
2251
        Moves                               = 0b0000_0000__0000_1011__0000,
2252 2253

        // Things that mean drop glue is necessary
F
Flavio Percoco 已提交
2254
        NeedsDrop                           = 0b0000_0000__0000_0111__0000,
2255 2256

        // Things that prevent values from being considered sized
F
Flavio Percoco 已提交
2257 2258
        Nonsized                            = 0b0000_0000__0000_0000__0001,

2259 2260 2261
        // Things that make values considered not POD (would be same
        // as `Moves`, but for the fact that managed data `@` is
        // not considered POD)
F
Flavio Percoco 已提交
2262
        Noncopy                              = 0b0000_0000__0000_1111__0000,
2263

2264 2265 2266 2267 2268
        // Bits to set when a managed value is encountered
        //
        // [1] Do not set the bits TC::OwnsManaged or
        //     TC::ReachesManaged directly, instead reference
        //     TC::Managed to set them both at once.
F
Flavio Percoco 已提交
2269
        Managed                             = 0b0000_0100__0000_0100__0000,
2270 2271

        // All bits
F
Flavio Percoco 已提交
2272
        All                                 = 0b1111_1111__1111_1111__1111
2273 2274 2275
    }
)

2276
impl TypeContents {
2277 2278
    pub fn when(&self, cond: bool) -> TypeContents {
        if cond {*self} else {TC::None}
2279
    }
2280

2281 2282
    pub fn intersects(&self, tc: TypeContents) -> bool {
        (self.bits & tc.bits) != 0
2283
    }
2284

2285
    pub fn owns_managed(&self) -> bool {
2286
        self.intersects(TC::OwnsManaged)
2287 2288
    }

2289 2290 2291 2292
    pub fn owns_owned(&self) -> bool {
        self.intersects(TC::OwnsOwned)
    }

E
Eduard Burtescu 已提交
2293
    pub fn is_sized(&self, _: &ctxt) -> bool {
2294
        !self.intersects(TC::Nonsized)
2295
    }
2296

2297 2298 2299 2300
    pub fn interior_unsafe(&self) -> bool {
        self.intersects(TC::InteriorUnsafe)
    }

E
Eduard Burtescu 已提交
2301 2302 2303 2304
    pub fn interior_unsized(&self) -> bool {
        self.intersects(TC::InteriorUnsized)
    }

E
Eduard Burtescu 已提交
2305
    pub fn moves_by_default(&self, _: &ctxt) -> bool {
2306
        self.intersects(TC::Moves)
2307 2308
    }

E
Eduard Burtescu 已提交
2309
    pub fn needs_drop(&self, _: &ctxt) -> bool {
2310
        self.intersects(TC::NeedsDrop)
2311 2312
    }

2313 2314 2315
    pub fn owned_pointer(&self) -> TypeContents {
        /*!
         * Includes only those bits that still apply
2316
         * when indirected through a `Box` pointer
2317 2318 2319
         */
        TC::OwnsOwned | (
            *self & (TC::OwnsAll | TC::ReachesAll))
2320
    }
2321

2322
    pub fn reference(&self, bits: TypeContents) -> TypeContents {
2323 2324
        /*!
         * Includes only those bits that still apply
2325
         * when indirected through a reference (`&`)
2326 2327 2328
         */
        bits | (
            *self & TC::ReachesAll)
2329
    }
2330

2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
    pub fn managed_pointer(&self) -> TypeContents {
        /*!
         * Includes only those bits that still apply
         * when indirected through a managed pointer (`@`)
         */
        TC::Managed | (
            *self & TC::ReachesAll)
    }

    pub fn unsafe_pointer(&self) -> TypeContents {
        /*!
         * Includes only those bits that still apply
         * when indirected through an unsafe pointer (`*`)
         */
        *self & TC::ReachesAll
    }

2348
    pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
2349
        v.iter().fold(TC::None, |tc, t| tc | f(t))
2350 2351
    }

2352 2353 2354
    pub fn has_dtor(&self) -> bool {
        self.intersects(TC::OwnsDtor)
    }
2355
}
2356

2357 2358
impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
    fn bitor(&self, other: &TypeContents) -> TypeContents {
2359 2360
        TypeContents {bits: self.bits | other.bits}
    }
2361 2362
}

2363 2364 2365 2366 2367 2368
impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
    fn bitand(&self, other: &TypeContents) -> TypeContents {
        TypeContents {bits: self.bits & other.bits}
    }
}

2369
impl ops::Sub<TypeContents,TypeContents> for TypeContents {
2370
    fn sub(&self, other: &TypeContents) -> TypeContents {
2371 2372
        TypeContents {bits: self.bits & !other.bits}
    }
2373 2374
}

2375 2376
impl fmt::Show for TypeContents {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
A
Alex Crichton 已提交
2377
        write!(f, "TypeContents({:t})", self.bits)
2378
    }
2379
}
2380

2381 2382 2383 2384
pub fn type_interior_is_unsafe(cx: &ctxt, t: ty::t) -> bool {
    type_contents(cx, t).interior_unsafe()
}

E
Eduard Burtescu 已提交
2385
pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
2386 2387 2388
    return memoized_with_key(&cx.tc_cache, ty, |ty| {
        tc_ty(cx, ty, &mut HashMap::new())
    }, |&ty| type_id(ty));
M
Marijn Haverbeke 已提交
2389

E
Eduard Burtescu 已提交
2390
    fn tc_ty(cx: &ctxt,
2391
             ty: t,
2392
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2393 2394 2395 2396 2397
    {
        // Subtle: Note that we are *not* using cx.tc_cache here but rather a
        // private cache for this walk.  This is needed in the case of cyclic
        // types like:
        //
2398
        //     struct List { next: Box<Option<List>>, ... }
2399 2400 2401
        //
        // When computing the type contents of such a type, we wind up deeply
        // recursing as we go.  So when we encounter the recursive reference
2402
        // to List, we temporarily use TC::None as its contents.  Later we'll
2403 2404
        // patch up the cache with the correct value, once we've computed it
        // (this is basically a co-inductive process, if that helps).  So in
2405
        // the end we'll compute TC::OwnsOwned, in this case.
2406 2407 2408
        //
        // The problem is, as we are doing the computation, we will also
        // compute an *intermediate* contents for, e.g., Option<List> of
2409
        // TC::None.  This is ok during the computation of List itself, but if
2410
        // we stored this intermediate value into cx.tc_cache, then later
2411
        // requests for the contents of Option<List> would also yield TC::None
2412 2413
        // which is incorrect.  This value was computed based on the crutch
        // value for the type contents of list.  The correct value is
2414
        // TC::OwnsOwned.  This manifested as issue #4821.
2415 2416 2417 2418 2419
        let ty_id = type_id(ty);
        match cache.find(&ty_id) {
            Some(tc) => { return *tc; }
            None => {}
        }
2420 2421 2422
        match cx.tc_cache.borrow().find(&ty_id) {    // Must check both caches!
            Some(tc) => { return *tc; }
            None => {}
2423
        }
2424
        cache.insert(ty_id, TC::None);
2425

2426
        let result = match get(ty).sty {
2427 2428 2429 2430 2431
            // uint and int are ffi-unsafe
            ty_uint(ast::TyU) | ty_int(ast::TyI) => {
                TC::ReachesFfiUnsafe
            }

2432
            // Scalar and unique types are sendable, and durable
2433
            ty_infer(ty::SkolemizedIntTy(_)) |
J
Jakub Bukaj 已提交
2434
            ty_nil | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
N
Nick Cameron 已提交
2435
            ty_bare_fn(_) | ty::ty_char => {
2436
                TC::None
2437
            }
2438

2439
            ty_closure(ref c) => {
2440
                closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
2441
            }
2442

2443
            ty_uniq(typ) => {
2444
                TC::ReachesFfiUnsafe | match get(typ).sty {
2445
                    ty_str => TC::OwnsOwned,
2446 2447
                    _ => tc_ty(cx, typ, cache).owned_pointer(),
                }
2448 2449
            }

2450
            ty_trait(box TyTrait { bounds, .. }) => {
2451
                object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
2452
            }
2453

2454
            ty_ptr(ref mt) => {
2455
                tc_ty(cx, mt.ty, cache).unsafe_pointer()
2456 2457
            }

2458
            ty_rptr(r, ref mt) => {
2459
                TC::ReachesFfiUnsafe | match get(mt.ty).sty {
2460
                    ty_str => borrowed_contents(r, ast::MutImmutable),
2461
                    ty_vec(..) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2462 2463
                    _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
                }
2464
            }
2465

N
Nick Cameron 已提交
2466 2467
            ty_vec(t, Some(_)) => {
                tc_ty(cx, t, cache)
2468
            }
2469

N
Nick Cameron 已提交
2470 2471 2472 2473 2474
            ty_vec(t, None) => {
                tc_ty(cx, t, cache) | TC::Nonsized
            }
            ty_str => TC::Nonsized,

2475 2476
            ty_struct(did, ref substs) => {
                let flds = struct_fields(cx, did, substs);
2477
                let mut res =
2478 2479
                    TypeContents::union(flds.as_slice(),
                                        |f| tc_mt(cx, f.mt, cache));
2480 2481 2482 2483 2484

                if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
                    res = res | TC::ReachesFfiUnsafe;
                }

2485
                if ty::has_dtor(cx, did) {
2486
                    res = res | TC::OwnsDtor;
2487
                }
2488
                apply_lang_items(cx, did, res)
2489
            }
2490

2491
            ty_unboxed_closure(did, r, ref substs) => {
2492 2493
                // FIXME(#14449): `borrowed_contents` below assumes `&mut`
                // unboxed closure.
2494
                let upvars = unboxed_closure_upvars(cx, did, substs);
2495
                TypeContents::union(upvars.as_slice(),
2496 2497
                                    |f| tc_ty(cx, f.ty, cache)) |
                    borrowed_contents(r, MutMutable)
2498 2499
            }

2500
            ty_tup(ref tys) => {
2501 2502
                TypeContents::union(tys.as_slice(),
                                    |ty| tc_ty(cx, *ty, cache))
2503
            }
2504

2505 2506
            ty_enum(did, ref substs) => {
                let variants = substd_enum_variants(cx, did, substs);
J
Jakub Wieczorek 已提交
2507
                let mut res =
2508 2509 2510
                    TypeContents::union(variants.as_slice(), |variant| {
                        TypeContents::union(variant.args.as_slice(),
                                            |arg_ty| {
2511 2512 2513
                            tc_ty(cx, *arg_ty, cache)
                        })
                    });
2514

J
Jakub Wieczorek 已提交
2515 2516 2517
                if ty::has_dtor(cx, did) {
                    res = res | TC::OwnsDtor;
                }
2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540

                if variants.len() != 0 {
                    let repr_hints = lookup_repr_hints(cx, did);
                    if repr_hints.len() > 1 {
                        // this is an error later on, but this type isn't safe
                        res = res | TC::ReachesFfiUnsafe;
                    }

                    match repr_hints.as_slice().get(0) {
                        Some(h) => if !h.is_ffi_safe() {
                            res = res | TC::ReachesFfiUnsafe;
                        },
                        // ReprAny
                        None => {
                            res = res | TC::ReachesFfiUnsafe;

                            // We allow ReprAny enums if they are eligible for
                            // the nullable pointer optimization and the
                            // contained type is an `extern fn`

                            if variants.len() == 2 {
                                let mut data_idx = 0;

2541
                                if variants[0].args.len() == 0 {
2542 2543 2544
                                    data_idx = 1;
                                }

2545 2546
                                if variants[data_idx].args.len() == 1 {
                                    match get(variants[data_idx].args[0]).sty {
2547 2548 2549 2550 2551 2552 2553 2554 2555 2556
                                        ty_bare_fn(..) => { res = res - TC::ReachesFfiUnsafe; }
                                        _ => { }
                                    }
                                }
                            }
                        }
                    }
                }


2557
                apply_lang_items(cx, did, res)
2558
            }
2559

2560 2561 2562 2563
            ty_param(p) => {
                // We only ever ask for the kind of types that are defined in
                // the current crate; therefore, the only type parameters that
                // could be in scope are those defined in the current crate.
J
Jakub Bukaj 已提交
2564
                // If this assertion fails, it is likely because of a
S
Steve Klabnik 已提交
2565
                // failure of the cross-crate inlining code to translate a
2566
                // def-id.
2567
                assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
2568

2569
                let ty_param_defs = cx.ty_param_defs.borrow();
2570
                let tp_def = &(*ty_param_defs)[p.def_id.node];
2571 2572 2573 2574 2575
                kind_bounds_to_contents(
                    cx,
                    tp_def.bounds.builtin_bounds,
                    tp_def.bounds.trait_bounds.as_slice())
            }
2576

2577 2578 2579
            ty_infer(_) => {
                // This occurs during coherence, but shouldn't occur at other
                // times.
2580
                TC::All
2581
            }
2582

N
Nick Cameron 已提交
2583 2584 2585 2586 2587 2588
            ty_open(t) => {
                let result = tc_ty(cx, t, cache);
                assert!(!result.is_sized(cx))
                result.unsafe_pointer() | TC::Nonsized
            }

2589
            ty_err => {
M
mr.Shu 已提交
2590
                cx.sess.bug("asked to compute contents of error type");
2591
            }
2592 2593 2594 2595 2596
        };

        cache.insert(ty_id, result);
        return result;
    }
2597

E
Eduard Burtescu 已提交
2598
    fn tc_mt(cx: &ctxt,
2599
             mt: mt,
2600
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2601
    {
2602 2603
        let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
        mc | tc_ty(cx, mt.ty, cache)
2604
    }
2605

E
Eduard Burtescu 已提交
2606
    fn apply_lang_items(cx: &ctxt,
2607 2608
                        did: ast::DefId,
                        tc: TypeContents)
2609 2610 2611
                        -> TypeContents
    {
        if Some(did) == cx.lang_items.managed_bound() {
2612
            tc | TC::Managed
F
Flavio Percoco 已提交
2613
        } else if Some(did) == cx.lang_items.no_copy_bound() {
2614
            tc | TC::OwnsAffine
F
Flavio Percoco 已提交
2615
        } else if Some(did) == cx.lang_items.unsafe_type() {
2616
            tc | TC::InteriorUnsafe
2617 2618 2619
        } else {
            tc
        }
D
Daniel Micay 已提交
2620 2621
    }

2622
    fn borrowed_contents(region: ty::Region,
2623 2624
                         mutbl: ast::Mutability)
                         -> TypeContents {
2625
        /*!
2626
         * Type contents due to containing a reference
2627
         * with the region `region` and borrow kind `bk`
2628
         */
2629

2630 2631 2632 2633
        let b = match mutbl {
            ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine,
            ast::MutImmutable => TC::None,
        };
2634
        b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
2635 2636
    }

E
Eduard Burtescu 已提交
2637
    fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
2638 2639
        // Closure contents are just like trait contents, but with potentially
        // even more stuff.
N
Nick Cameron 已提交
2640 2641 2642 2643 2644 2645 2646 2647 2648 2649
        let st = object_contents(cx, cty.bounds);

        let st = match cty.store {
            UniqTraitStore => {
                st.owned_pointer()
            }
            RegionTraitStore(r, mutbl) => {
                st.reference(borrowed_contents(r, mutbl))
            }
        };
2650

2651 2652
        // This also prohibits "@once fn" from being copied, which allows it to
        // be called. Neither way really makes much sense.
2653
        let ot = match cty.onceness {
2654 2655
            ast::Once => TC::OwnsAffine,
            ast::Many => TC::None,
2656
        };
2657

2658
        st | ot
2659 2660
    }

E
Eduard Burtescu 已提交
2661
    fn object_contents(cx: &ctxt,
2662
                       bounds: ExistentialBounds)
2663 2664
                       -> TypeContents {
        // These are the type contents of the (opaque) interior
2665
        kind_bounds_to_contents(cx, bounds.builtin_bounds, [])
2666 2667
    }

E
Eduard Burtescu 已提交
2668
    fn kind_bounds_to_contents(cx: &ctxt,
2669
                               bounds: BuiltinBounds,
E
Eduard Burtescu 已提交
2670
                               traits: &[Rc<TraitRef>])
2671
                               -> TypeContents {
2672
        let _i = indenter();
2673
        let mut tc = TC::All;
2674
        each_inherited_builtin_bound(cx, bounds, traits, |bound| {
2675
            tc = tc - match bound {
2676
                BoundSync | BoundSend => TC::None,
2677
                BoundSized => TC::Nonsized,
F
Flavio Percoco 已提交
2678
                BoundCopy => TC::Noncopy,
2679
            };
2680
        });
2681
        return tc;
2682 2683 2684

        // Iterates over all builtin bounds on the type parameter def, including
        // those inherited from traits with builtin-kind-supertraits.
E
Eduard Burtescu 已提交
2685
        fn each_inherited_builtin_bound(cx: &ctxt,
2686
                                        bounds: BuiltinBounds,
E
Eduard Burtescu 已提交
2687
                                        traits: &[Rc<TraitRef>],
2688
                                        f: |BuiltinBound|) {
2689
            for bound in bounds.iter() {
2690 2691 2692
                f(bound);
            }

2693
            each_bound_trait_and_supertraits(cx, traits, |trait_ref| {
2694
                let trait_def = lookup_trait_def(cx, trait_ref.def_id);
2695
                for bound in trait_def.bounds.builtin_bounds.iter() {
2696 2697 2698
                    f(bound);
                }
                true
2699
            });
2700
        }
2701
    }
2702 2703
}

E
Eduard Burtescu 已提交
2704
pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
2705 2706 2707
    type_contents(cx, ty).moves_by_default(cx)
}

2708 2709 2710 2711
pub fn is_ffi_safe(cx: &ctxt, ty: t) -> bool {
    !type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe)
}

2712
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
E
Eduard Burtescu 已提交
2713 2714
pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
    fn type_requires(cx: &ctxt, seen: &mut Vec<DefId>,
2715
                     r_ty: t, ty: t) -> bool {
2716
        debug!("type_requires({}, {})?",
2717 2718
               ::util::ppaux::ty_to_string(cx, r_ty),
               ::util::ppaux::ty_to_string(cx, ty));
2719 2720

        let r = {
2721
            get(r_ty).sty == get(ty).sty ||
2722 2723 2724
                subtypes_require(cx, seen, r_ty, ty)
        };

2725
        debug!("type_requires({}, {})? {}",
2726 2727
               ::util::ppaux::ty_to_string(cx, r_ty),
               ::util::ppaux::ty_to_string(cx, ty),
P
Paul Stansifer 已提交
2728
               r);
B
Brian Anderson 已提交
2729
        return r;
2730 2731
    }

E
Eduard Burtescu 已提交
2732
    fn subtypes_require(cx: &ctxt, seen: &mut Vec<DefId>,
2733
                        r_ty: t, ty: t) -> bool {
2734
        debug!("subtypes_require({}, {})?",
2735 2736
               ::util::ppaux::ty_to_string(cx, r_ty),
               ::util::ppaux::ty_to_string(cx, ty));
2737

2738
        let r = match get(ty).sty {
2739 2740
            // fixed length vectors need special treatment compared to
            // normal vectors, since they don't necessarily have the
J
Joseph Crail 已提交
2741
            // possibility to have length zero.
2742
            ty_vec(_, Some(0)) => false, // don't need no contents
N
Nick Cameron 已提交
2743
            ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
2744

2745 2746
            ty_nil |
            ty_bool |
2747
            ty_char |
2748 2749 2750
            ty_int(_) |
            ty_uint(_) |
            ty_float(_) |
2751
            ty_str |
2752 2753 2754 2755 2756
            ty_bare_fn(_) |
            ty_closure(_) |
            ty_infer(_) |
            ty_err |
            ty_param(_) |
2757
            ty_vec(_, None) => {
2758 2759
                false
            }
E
Eduard Burtescu 已提交
2760
            ty_uniq(typ) | ty_open(typ) => {
2761 2762
                type_requires(cx, seen, r_ty, typ)
            }
2763 2764 2765
            ty_rptr(_, ref mt) => {
                type_requires(cx, seen, r_ty, mt.ty)
            }
2766

A
Alex Crichton 已提交
2767
            ty_ptr(..) => {
2768 2769
                false           // unsafe ptrs can always be NULL
            }
2770

2771
            ty_trait(..) => {
2772 2773
                false
            }
2774

2775
            ty_struct(ref did, _) if seen.contains(did) => {
2776 2777
                false
            }
2778

2779 2780 2781
            ty_struct(did, ref substs) => {
                seen.push(did);
                let fields = struct_fields(cx, did, substs);
2782
                let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
2783
                seen.pop().unwrap();
2784 2785
                r
            }
2786

2787 2788
            ty_unboxed_closure(did, _, ref substs) => {
                let upvars = unboxed_closure_upvars(cx, did, substs);
2789 2790 2791
                upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
            }

2792
            ty_tup(ref ts) => {
2793
                ts.iter().any(|t| type_requires(cx, seen, r_ty, *t))
2794
            }
2795

2796
            ty_enum(ref did, _) if seen.contains(did) => {
2797 2798
                false
            }
2799

2800 2801 2802
            ty_enum(did, ref substs) => {
                seen.push(did);
                let vs = enum_variants(cx, did);
2803 2804
                let r = !vs.is_empty() && vs.iter().all(|variant| {
                    variant.args.iter().any(|aty| {
2805
                        let sty = aty.subst(cx, substs);
2806
                        type_requires(cx, seen, r_ty, sty)
2807 2808
                    })
                });
2809
                seen.pop().unwrap();
2810 2811
                r
            }
2812 2813
        };

2814
        debug!("subtypes_require({}, {})? {}",
2815 2816
               ::util::ppaux::ty_to_string(cx, r_ty),
               ::util::ppaux::ty_to_string(cx, ty),
P
Paul Stansifer 已提交
2817
               r);
2818

B
Brian Anderson 已提交
2819
        return r;
2820 2821
    }

2822
    let mut seen = Vec::new();
2823
    !subtypes_require(cx, &mut seen, r_ty, r_ty)
2824 2825
}

2826 2827 2828 2829 2830
/// Describes whether a type is representable. For types that are not
/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
/// distinguish between types that are recursive with themselves and types that
/// contain a different recursive type. These cases can therefore be treated
/// differently when reporting errors.
2831 2832 2833 2834
///
/// The ordering of the cases is significant. They are sorted so that cmp::max
/// will keep the "more erroneous" of two values.
#[deriving(PartialOrd, Ord, Eq, PartialEq, Show)]
2835 2836 2837
pub enum Representability {
    Representable,
    ContainsRecursive,
2838
    SelfRecursive,
2839 2840 2841 2842
}

/// Check whether a type is representable. This means it cannot contain unboxed
/// structural recursion. This check is needed for structs and enums.
2843
pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
2844 2845

    // Iterate until something non-representable is found
2846
    fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, sp: Span, seen: &mut Vec<t>,
2847
                                              mut iter: It) -> Representability {
2848 2849
        iter.fold(Representable,
                  |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
2850 2851
    }

2852 2853
    fn are_inner_types_recursive(cx: &ctxt, sp: Span,
                                 seen: &mut Vec<t>, ty: t) -> Representability {
2854 2855
        match get(ty).sty {
            ty_tup(ref ts) => {
2856
                find_nonrepresentable(cx, sp, seen, ts.iter().map(|t| *t))
2857
            }
2858 2859
            // Fixed-length vectors.
            // FIXME(#11924) Behavior undecided for zero-length vectors.
N
Nick Cameron 已提交
2860
            ty_vec(ty, Some(_)) => {
2861
                is_type_structurally_recursive(cx, sp, seen, ty)
2862 2863 2864
            }
            ty_struct(did, ref substs) => {
                let fields = struct_fields(cx, did, substs);
2865
                find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
2866 2867 2868
            }
            ty_enum(did, ref substs) => {
                let vs = enum_variants(cx, did);
2869 2870 2871
                let iter = vs.iter()
                    .flat_map(|variant| { variant.args.iter() })
                    .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
2872

2873 2874
                find_nonrepresentable(cx, sp, seen, iter)
            }
2875 2876
            ty_unboxed_closure(did, _, ref substs) => {
                let upvars = unboxed_closure_upvars(cx, did, substs);
2877 2878 2879 2880 2881
                find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty))
            }
            _ => Representable,
        }
    }
2882

2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897
    fn same_struct_or_enum_def_id(ty: t, did: DefId) -> bool {
        match get(ty).sty {
            ty_struct(ty_did, _) | ty_enum(ty_did, _) => {
                 ty_did == did
            }
            _ => false
        }
    }

    fn same_type(a: t, b: t) -> bool {
        match (&get(a).sty, &get(b).sty) {
            (&ty_struct(did_a, ref substs_a), &ty_struct(did_b, ref substs_b)) |
            (&ty_enum(did_a, ref substs_a), &ty_enum(did_b, ref substs_b)) => {
                if did_a != did_b {
                    return false;
2898 2899
                }

2900 2901
                let types_a = substs_a.types.get_slice(subst::TypeSpace);
                let types_b = substs_b.types.get_slice(subst::TypeSpace);
2902

2903 2904 2905 2906 2907 2908
                let mut pairs = types_a.iter().zip(types_b.iter());

                pairs.all(|(&a, &b)| same_type(a, b))
            }
            _ => {
                type_id(a) == type_id(b)
2909
            }
2910 2911
        }
    }
2912

2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
    // Does the type `ty` directly (without indirection through a pointer)
    // contain any types on stack `seen`?
    fn is_type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<t>,
                                      ty: t) -> Representability {
        debug!("is_type_structurally_recursive: {}",
               ::util::ppaux::ty_to_string(cx, ty));

        match get(ty).sty {
            ty_struct(did, _) | ty_enum(did, _) => {
                {
                    // Iterate through stack of previously seen types.
                    let mut iter = seen.iter();

                    // The first item in `seen` is the type we are actually curious about.
                    // We want to return SelfRecursive if this type contains itself.
                    // It is important that we DON'T take generic parameters into account
                    // for this check, so that Bar<T> in this example counts as SelfRecursive:
                    //
                    // struct Foo;
                    // struct Bar<T> { x: Bar<Foo> }

                    match iter.next() {
                        Some(&seen_type) => {
                            if same_struct_or_enum_def_id(seen_type, did) {
                                debug!("SelfRecursive: {} contains {}",
                                       ::util::ppaux::ty_to_string(cx, seen_type),
                                       ::util::ppaux::ty_to_string(cx, ty));
                                return SelfRecursive;
                            }
                        }
                        None => {}
                    }

                    // We also need to know whether the first item contains other types that
                    // are structurally recursive. If we don't catch this case, we will recurse
                    // infinitely for some inputs.
                    //
                    // It is important that we DO take generic parameters into account here,
                    // so that code like this is considered SelfRecursive, not ContainsRecursive:
                    //
                    // struct Foo { Option<Option<Foo>> }

                    for &seen_type in iter {
                        if same_type(ty, seen_type) {
                            debug!("ContainsRecursive: {} contains {}",
                                   ::util::ppaux::ty_to_string(cx, seen_type),
                                   ::util::ppaux::ty_to_string(cx, ty));
                            return ContainsRecursive;
                        }
                    }
                }

                // For structs and enums, track all previously seen types by pushing them
                // onto the 'seen' stack.
                seen.push(ty);
                let out = are_inner_types_recursive(cx, sp, seen, ty);
                seen.pop();
                out
            }
            _ => {
                // No need to push in other cases.
                are_inner_types_recursive(cx, sp, seen, ty)
            }
2976
        }
M
Marijn Haverbeke 已提交
2977 2978
    }

2979
    debug!("is_type_representable: {}",
2980
           ::util::ppaux::ty_to_string(cx, ty));
2981 2982 2983 2984

    // To avoid a stack overflow when checking an enum variant or struct that
    // contains a different, structurally recursive type, maintain a stack
    // of seen types and check recursion for each of them (issues #3008, #3779).
2985 2986 2987 2988 2989
    let mut seen: Vec<t> = Vec::new();
    let r = is_type_structurally_recursive(cx, sp, &mut seen, ty);
    debug!("is_type_representable: {} is {}",
           ::util::ppaux::ty_to_string(cx, ty), r);
    r
2990 2991
}

2992
pub fn type_is_trait(ty: t) -> bool {
2993 2994 2995 2996
    type_trait_info(ty).is_some()
}

pub fn type_trait_info(ty: t) -> Option<&'static TyTrait> {
2997
    match get(ty).sty {
2998
        ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match get(ty).sty {
2999 3000
            ty_trait(ref t) => Some(&**t),
            _ => None
N
Nick Cameron 已提交
3001
        },
3002 3003
        ty_trait(ref t) => Some(&**t),
        _ => None
3004 3005 3006
    }
}

3007
pub fn type_is_integral(ty: t) -> bool {
3008
    match get(ty).sty {
3009
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
B
Brian Anderson 已提交
3010
      _ => false
M
Marijn Haverbeke 已提交
3011 3012 3013
    }
}

3014 3015 3016 3017 3018 3019 3020 3021
pub fn type_is_skolemized(ty: t) -> bool {
    match get(ty).sty {
      ty_infer(SkolemizedTy(_)) => true,
      ty_infer(SkolemizedIntTy(_)) => true,
      _ => false
    }
}

3022 3023 3024 3025 3026 3027 3028
pub fn type_is_uint(ty: t) -> bool {
    match get(ty).sty {
      ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
      _ => false
    }
}

3029
pub fn type_is_char(ty: t) -> bool {
3030
    match get(ty).sty {
3031
        ty_char => true,
3032 3033 3034 3035
        _ => false
    }
}

3036 3037
pub fn type_is_bare_fn(ty: t) -> bool {
    match get(ty).sty {
A
Alex Crichton 已提交
3038
        ty_bare_fn(..) => true,
3039 3040 3041 3042
        _ => false
    }
}

3043
pub fn type_is_fp(ty: t) -> bool {
3044
    match get(ty).sty {
3045
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
3046
      _ => false
M
Marijn Haverbeke 已提交
3047 3048 3049
    }
}

3050
pub fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
3051
    return type_is_integral(ty) || type_is_fp(ty);
3052 3053
}

3054
pub fn type_is_signed(ty: t) -> bool {
3055
    match get(ty).sty {
B
Brian Anderson 已提交
3056 3057
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
3058 3059 3060
    }
}

S
Seo Sanghyeon 已提交
3061 3062
pub fn type_is_machine(ty: t) -> bool {
    match get(ty).sty {
3063
        ty_int(ast::TyI) | ty_uint(ast::TyU) => false,
A
Alex Crichton 已提交
3064
        ty_int(..) | ty_uint(..) | ty_float(..) => true,
S
Seo Sanghyeon 已提交
3065 3066 3067 3068
        _ => false
    }
}

3069
// Is the type's representation size known at compile time?
N
Nick Cameron 已提交
3070
pub fn type_is_sized(cx: &ctxt, ty: t) -> bool {
N
Nick Cameron 已提交
3071
    type_contents(cx, ty).is_sized(cx)
3072 3073
}

N
Nick Cameron 已提交
3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
pub fn lltype_is_sized(cx: &ctxt, ty: t) -> bool {
    match get(ty).sty {
        ty_open(_) => true,
        _ => type_contents(cx, ty).is_sized(cx)
    }
}

// Return the smallest part of t which is unsized. Fails if t is sized.
// 'Smallest' here means component of the static representation of the type; not
// the size of an object at runtime.
pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
    match get(ty).sty {
        ty_str | ty_trait(..) | ty_vec(..) => ty,
N
Nick Cameron 已提交
3087 3088 3089 3090 3091 3092 3093
        ty_struct(def_id, ref substs) => {
            let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
                .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
            // Exactly one of the fields must be unsized.
            assert!(unsized_fields.len() == 1)

            unsized_part_of_type(cx, unsized_fields[0])
N
Nick Cameron 已提交
3094 3095 3096 3097
        }
        _ => {
            assert!(type_is_sized(cx, ty),
                    "unsized_part_of_type failed even though ty is unsized");
S
Steve Klabnik 已提交
3098
            panic!("called unsized_part_of_type with sized ty");
N
Nick Cameron 已提交
3099 3100 3101 3102
        }
    }
}

V
Virgile Andreani 已提交
3103
// Whether a type is enum like, that is an enum type with only nullary
3104
// constructors
E
Eduard Burtescu 已提交
3105
pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
3106
    match get(ty).sty {
3107 3108 3109 3110 3111
        ty_enum(did, _) => {
            let variants = enum_variants(cx, did);
            if variants.len() == 0 {
                false
            } else {
3112
                variants.iter().all(|v| v.args.len() == 0)
3113 3114 3115
            }
        }
        _ => false
3116 3117 3118
    }
}

3119 3120
// Returns the type and mutability of *t.
//
3121 3122
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
3123
pub fn deref(t: t, explicit: bool) -> Option<mt> {
3124
    match get(t).sty {
E
Eduard Burtescu 已提交
3125
        ty_uniq(ty) => {
N
Nick Cameron 已提交
3126 3127
            Some(mt {
                ty: ty,
3128
                mutbl: ast::MutImmutable,
N
Nick Cameron 已提交
3129
            })
3130
        },
N
Nick Cameron 已提交
3131
        ty_rptr(_, mt) => Some(mt),
3132
        ty_ptr(mt) if explicit => Some(mt),
3133
        _ => None
3134 3135 3136
    }
}

N
Nick Cameron 已提交
3137 3138
pub fn deref_or_dont(t: t) -> t {
    match get(t).sty {
E
Eduard Burtescu 已提交
3139
        ty_uniq(ty) => ty,
N
Nick Cameron 已提交
3140 3141 3142 3143 3144
        ty_rptr(_, mt) | ty_ptr(mt) => mt.ty,
        _ => t
    }
}

N
Nick Cameron 已提交
3145
pub fn close_type(cx: &ctxt, t: t) -> t {
3146
    match get(t).sty {
N
Nick Cameron 已提交
3147 3148
        ty_open(t) => mk_rptr(cx, ReStatic, mt {ty: t, mutbl:ast::MutImmutable}),
        _ => cx.sess.bug(format!("Trying to close a non-open type {}",
N
Nick Cameron 已提交
3149
                                 ty_to_string(cx, t)).as_slice())
N
Nick Cameron 已提交
3150 3151 3152 3153 3154
    }
}

pub fn type_content(t: t) -> t {
    match get(t).sty {
E
Eduard Burtescu 已提交
3155
        ty_uniq(ty) => ty,
N
Nick Cameron 已提交
3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173
        ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
        _ => t
    }

}

// Extract the unsized type in an open type (or just return t if it is not open).
pub fn unopen_type(t: t) -> t {
    match get(t).sty {
        ty_open(t) => t,
        _ => t
    }
}

// Returns the type of t[i]
pub fn index(ty: t) -> Option<t> {
    match get(ty).sty {
        ty_vec(t, _) => Some(t),
3174 3175 3176 3177 3178 3179 3180
        _ => None
    }
}

// Returns the type of elements contained within an 'array-like' type.
// This is exactly the same as the above, except it supports strings,
// which can't actually be indexed.
N
Nick Cameron 已提交
3181
pub fn array_element_ty(t: t) -> Option<t> {
N
Nick Cameron 已提交
3182
    match get(t).sty {
N
Nick Cameron 已提交
3183
        ty_vec(t, _) => Some(t),
N
Nick Cameron 已提交
3184
        ty_str => Some(mk_u8()),
3185
        _ => None
3186
    }
3187 3188
}

E
Eduard Burtescu 已提交
3189
pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> Rc<ty::TraitRef> {
3190
    match cx.trait_refs.borrow().find(&id) {
E
Eduard Burtescu 已提交
3191 3192 3193
        Some(t) => t.clone(),
        None => cx.sess.bug(
            format!("node_id_to_trait_ref: no trait ref for node `{}`",
3194
                    cx.map.node_to_string(id)).as_slice())
3195 3196 3197
    }
}

E
Eduard Burtescu 已提交
3198
pub fn try_node_id_to_type(cx: &ctxt, id: ast::NodeId) -> Option<t> {
3199
    cx.node_types.borrow().find_copy(&(id as uint))
3200 3201
}

E
Eduard Burtescu 已提交
3202
pub fn node_id_to_type(cx: &ctxt, id: ast::NodeId) -> t {
3203
    match try_node_id_to_type(cx, id) {
3204
       Some(t) => t,
B
Brian Anderson 已提交
3205
       None => cx.sess.bug(
A
Alex Crichton 已提交
3206
           format!("node_id_to_type: no type for node `{}`",
3207
                   cx.map.node_to_string(id)).as_slice())
T
Tim Chevalier 已提交
3208
    }
3209 3210
}

E
Eduard Burtescu 已提交
3211
pub fn node_id_to_type_opt(cx: &ctxt, id: ast::NodeId) -> Option<t> {
3212
    match cx.node_types.borrow().find(&(id as uint)) {
3213 3214 3215 3216 3217
       Some(&t) => Some(t),
       None => None
    }
}

3218 3219 3220 3221
pub fn node_id_item_substs(cx: &ctxt, id: ast::NodeId) -> ItemSubsts {
    match cx.item_substs.borrow().find(&id) {
      None => ItemSubsts::empty(),
      Some(ts) => ts.clone(),
3222 3223 3224
    }
}

3225 3226 3227 3228 3229
pub fn fn_is_variadic(fty: t) -> bool {
    match get(fty).sty {
        ty_bare_fn(ref f) => f.sig.variadic,
        ty_closure(ref f) => f.sig.variadic,
        ref s => {
S
Steve Klabnik 已提交
3230
            panic!("fn_is_variadic() called on non-fn type: {}", s)
3231 3232 3233 3234
        }
    }
}

3235 3236
pub fn ty_fn_sig(fty: t) -> FnSig {
    match get(fty).sty {
3237 3238
        ty_bare_fn(ref f) => f.sig.clone(),
        ty_closure(ref f) => f.sig.clone(),
3239
        ref s => {
S
Steve Klabnik 已提交
3240
            panic!("ty_fn_sig() called on non-fn type: {}", s)
3241 3242 3243 3244
        }
    }
}

3245 3246 3247 3248 3249
/// Returns the ABI of the given function.
pub fn ty_fn_abi(fty: t) -> abi::Abi {
    match get(fty).sty {
        ty_bare_fn(ref f) => f.abi,
        ty_closure(ref f) => f.abi,
S
Steve Klabnik 已提交
3250
        _ => panic!("ty_fn_abi() called on non-fn type"),
3251 3252 3253
    }
}

3254
// Type accessors for substructures of types
3255
pub fn ty_fn_args(fty: t) -> Vec<t> {
3256
    match get(fty).sty {
3257 3258
        ty_bare_fn(ref f) => f.sig.inputs.clone(),
        ty_closure(ref f) => f.sig.inputs.clone(),
3259
        ref s => {
S
Steve Klabnik 已提交
3260
            panic!("ty_fn_args() called on non-fn type: {}", s)
3261
        }
3262 3263 3264
    }
}

3265
pub fn ty_closure_store(fty: t) -> TraitStore {
3266
    match get(fty).sty {
3267
        ty_closure(ref f) => f.store,
3268
        ty_unboxed_closure(..) => {
3269 3270 3271 3272
            // Close enough for the purposes of all the callers of this
            // function (which is soon to be deprecated anyhow).
            UniqTraitStore
        }
3273
        ref s => {
S
Steve Klabnik 已提交
3274
            panic!("ty_closure_store() called on non-closure type: {}", s)
3275
        }
M
Marijn Haverbeke 已提交
3276
    }
G
Graydon Hoare 已提交
3277 3278
}

J
Jakub Bukaj 已提交
3279
pub fn ty_fn_ret(fty: t) -> FnOutput {
3280
    match get(fty).sty {
3281 3282 3283
        ty_bare_fn(ref f) => f.sig.output,
        ty_closure(ref f) => f.sig.output,
        ref s => {
S
Steve Klabnik 已提交
3284
            panic!("ty_fn_ret() called on non-fn type: {}", s)
3285
        }
3286
    }
G
Graydon Hoare 已提交
3287 3288
}

3289
pub fn is_fn_ty(fty: t) -> bool {
3290
    match get(fty).sty {
3291 3292 3293
        ty_bare_fn(_) => true,
        ty_closure(_) => true,
        _ => false
3294 3295 3296
    }
}

E
Eduard Burtescu 已提交
3297
pub fn ty_region(tcx: &ctxt,
3298
                 span: Span,
3299
                 ty: t) -> Region {
3300
    match get(ty).sty {
3301 3302 3303 3304
        ty_rptr(r, _) => r,
        ref s => {
            tcx.sess.span_bug(
                span,
L
Luqman Aden 已提交
3305
                format!("ty_region() invoked on an inappropriate ty: {}",
3306
                        s).as_slice());
3307
        }
3308
    }
G
Graydon Hoare 已提交
3309 3310
}

3311 3312 3313 3314 3315 3316 3317 3318
pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
    -> ty::Region
{
    ty::ReFree(ty::FreeRegion { scope_id: free_id,
                                bound_region: ty::BrNamed(def.def_id,
                                                          def.name) })
}

3319 3320
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
E
Eduard Burtescu 已提交
3321
pub fn pat_ty(cx: &ctxt, pat: &ast::Pat) -> t {
B
Brian Anderson 已提交
3322
    return node_id_to_type(cx, pat.id);
3323 3324
}

3325

3326 3327
// Returns the type of an expression as a monotype.
//
3328 3329 3330 3331 3332 3333
// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
// some cases, we insert `AutoAdjustment` annotations such as auto-deref or
// auto-ref.  The type returned by this function does not consider such
// adjustments.  See `expr_ty_adjusted()` instead.
//
// NB (2): This type doesn't provide type parameter substitutions; e.g. if you
3334
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
3335
// instead of "fn(t) -> T with T = int".
E
Eduard Burtescu 已提交
3336
pub fn expr_ty(cx: &ctxt, expr: &ast::Expr) -> t {
B
Brian Anderson 已提交
3337
    return node_id_to_type(cx, expr.id);
3338 3339
}

E
Eduard Burtescu 已提交
3340
pub fn expr_ty_opt(cx: &ctxt, expr: &ast::Expr) -> Option<t> {
3341 3342 3343
    return node_id_to_type_opt(cx, expr.id);
}

3344
pub fn expr_ty_adjusted(cx: &ctxt, expr: &ast::Expr) -> t {
3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357
    /*!
     *
     * Returns the type of `expr`, considering any `AutoAdjustment`
     * entry recorded for that expression.
     *
     * It would almost certainly be better to store the adjusted ty in with
     * the `AutoAdjustment`, but I opted not to do this because it would
     * require serializing and deserializing the type and, although that's not
     * hard to do, I just hate that code so much I didn't want to touch it
     * unless it was to fix it properly, which seemed a distraction from the
     * task at hand! -nmatsakis
     */

3358 3359 3360
    adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
              cx.adjustments.borrow().find(&expr.id),
              |method_call| cx.method_map.borrow().find(&method_call).map(|method| method.ty))
3361 3362
}

E
Eduard Burtescu 已提交
3363
pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
3364
    match cx.map.find(id) {
3365 3366 3367 3368
        Some(ast_map::NodeExpr(e)) => {
            e.span
        }
        Some(f) => {
L
Luqman Aden 已提交
3369
            cx.sess.bug(format!("Node id {} is not an expr: {}",
3370 3371
                                id,
                                f).as_slice());
3372 3373 3374
        }
        None => {
            cx.sess.bug(format!("Node id {} is not present \
3375
                                in the node map", id).as_slice());
3376 3377 3378 3379
        }
    }
}

E
Eduard Burtescu 已提交
3380
pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
3381
    match cx.map.find(id) {
3382 3383
        Some(ast_map::NodeLocal(pat)) => {
            match pat.node {
3384 3385
                ast::PatIdent(_, ref path1, _) => {
                    token::get_ident(path1.node)
3386 3387 3388
                }
                _ => {
                    cx.sess.bug(
L
Luqman Aden 已提交
3389
                        format!("Variable id {} maps to {}, not local",
3390 3391
                                id,
                                pat).as_slice());
3392 3393 3394 3395
                }
            }
        }
        r => {
L
Luqman Aden 已提交
3396
            cx.sess.bug(format!("Variable id {} maps to {}, not local",
3397 3398
                                id,
                                r).as_slice());
3399 3400 3401 3402
        }
    }
}

E
Eduard Burtescu 已提交
3403
pub fn adjust_ty(cx: &ctxt,
3404
                 span: Span,
3405
                 expr_id: ast::NodeId,
3406
                 unadjusted_ty: ty::t,
3407
                 adjustment: Option<&AutoAdjustment>,
3408
                 method_type: |typeck::MethodCall| -> Option<ty::t>)
3409
                 -> ty::t {
3410
    /*! See `expr_ty_adjusted` */
3411

3412 3413 3414 3415 3416
    match get(unadjusted_ty).sty {
        ty_err => return unadjusted_ty,
        _ => {}
    }

3417
    return match adjustment {
3418 3419
        Some(adjustment) => {
            match *adjustment {
3420
                AdjustAddEnv(store) => {
3421 3422
                    match ty::get(unadjusted_ty).sty {
                        ty::ty_bare_fn(ref b) => {
3423 3424 3425 3426 3427
                            let bounds = ty::ExistentialBounds {
                                region_bound: ReStatic,
                                builtin_bounds: all_builtin_bounds(),
                            };

3428 3429
                            ty::mk_closure(
                                cx,
3430 3431 3432 3433 3434 3435
                                ty::ClosureTy {fn_style: b.fn_style,
                                               onceness: ast::Many,
                                               store: store,
                                               bounds: bounds,
                                               sig: b.sig.clone(),
                                               abi: b.abi})
3436 3437 3438 3439
                        }
                        ref b => {
                            cx.sess.bug(
                                format!("add_env adjustment on non-bare-fn: \
L
Luqman Aden 已提交
3440
                                         {}",
3441
                                        b).as_slice());
3442
                        }
3443 3444 3445
                    }
                }

3446
                AdjustDerefRef(ref adj) => {
3447 3448
                    let mut adjusted_ty = unadjusted_ty;

H
Huon Wilson 已提交
3449
                    if !ty::type_is_error(adjusted_ty) {
3450
                        for i in range(0, adj.autoderefs) {
3451
                            let method_call = typeck::MethodCall::autoderef(expr_id, i);
3452
                            match method_type(method_call) {
3453
                                Some(method_ty) => {
J
Jakub Bukaj 已提交
3454 3455 3456
                                    if let ty::FnConverging(result_type) = ty_fn_ret(method_ty) {
                                        adjusted_ty = result_type;
                                    }
3457 3458 3459 3460
                                }
                                None => {}
                            }
                            match deref(adjusted_ty, true) {
3461 3462 3463 3464
                                Some(mt) => { adjusted_ty = mt.ty; }
                                None => {
                                    cx.sess.span_bug(
                                        span,
M
mr.Shu 已提交
3465
                                        format!("the {}th autoderef failed: \
3466 3467
                                                {}",
                                                i,
3468
                                                ty_to_string(cx, adjusted_ty))
3469
                                                          .as_slice());
3470 3471
                                }
                            }
3472
                        }
3473
                    }
3474

3475 3476
                    match adj.autoref {
                        None => adjusted_ty,
N
Nick Cameron 已提交
3477
                        Some(ref autoref) => adjust_for_autoref(cx, span, adjusted_ty, autoref)
N
Nick Cameron 已提交
3478
                    }
3479 3480
                }
            }
3481
        }
3482
        None => unadjusted_ty
3483 3484
    };

N
Nick Cameron 已提交
3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499
    fn adjust_for_autoref(cx: &ctxt,
                          span: Span,
                          ty: ty::t,
                          autoref: &AutoRef) -> ty::t{
        match *autoref {
            AutoPtr(r, m, ref a) => {
                let adjusted_ty = match a {
                    &Some(box ref a) => adjust_for_autoref(cx, span, ty, a),
                    &None => ty
                };
                mk_rptr(cx, r, mt {
                    ty: adjusted_ty,
                    mutbl: m
                })
            }
3500

3501 3502 3503 3504 3505 3506
            AutoUnsafe(m, ref a) => {
                let adjusted_ty = match a {
                    &Some(box ref a) => adjust_for_autoref(cx, span, ty, a),
                    &None => ty
                };
                mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3507
            }
N
Nick Cameron 已提交
3508 3509 3510

            AutoUnsize(ref k) => unsize_ty(cx, ty, k, span),
            AutoUnsizeUniq(ref k) => ty::mk_uniq(cx, unsize_ty(cx, ty, k, span)),
3511 3512
        }
    }
N
Nick Cameron 已提交
3513
}
3514

N
Nick Cameron 已提交
3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529
// Take a sized type and a sizing adjustment and produce an unsized version of
// the type.
pub fn unsize_ty(cx: &ctxt,
                 ty: ty::t,
                 kind: &UnsizeKind,
                 span: Span)
                 -> ty::t {
    match kind {
        &UnsizeLength(len) => match get(ty).sty {
            ty_vec(t, Some(n)) => {
                assert!(len == n);
                mk_vec(cx, t, None)
            }
            _ => cx.sess.span_bug(span,
                                  format!("UnsizeLength with bad sty: {}",
N
Nick Cameron 已提交
3530
                                          ty_to_string(cx, ty)).as_slice())
N
Nick Cameron 已提交
3531 3532 3533
        },
        &UnsizeStruct(box ref k, tp_index) => match get(ty).sty {
            ty_struct(did, ref substs) => {
N
Nick Cameron 已提交
3534 3535
                let ty_substs = substs.types.get_slice(subst::TypeSpace);
                let new_ty = unsize_ty(cx, ty_substs[tp_index], k, span);
N
Nick Cameron 已提交
3536
                let mut unsized_substs = substs.clone();
N
Nick Cameron 已提交
3537
                unsized_substs.types.get_mut_slice(subst::TypeSpace)[tp_index] = new_ty;
N
Nick Cameron 已提交
3538
                mk_struct(cx, did, unsized_substs)
3539
            }
N
Nick Cameron 已提交
3540 3541
            _ => cx.sess.span_bug(span,
                                  format!("UnsizeStruct with bad sty: {}",
N
Nick Cameron 已提交
3542
                                          ty_to_string(cx, ty)).as_slice())
N
Nick Cameron 已提交
3543
        },
3544
        &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => {
N
Nick Cameron 已提交
3545
            mk_trait(cx, def_id, substs.clone(), bounds)
3546 3547
        }
    }
3548 3549
}

3550
pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
3551
    match tcx.def_map.borrow().find(&expr.id) {
3552
        Some(&def) => def,
3553
        None => {
A
Alex Crichton 已提交
3554
            tcx.sess.span_bug(expr.span, format!(
L
Luqman Aden 已提交
3555
                "no def-map entry for expr {}", expr.id).as_slice());
3556 3557 3558 3559
        }
    }
}

3560 3561
pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
    match expr_kind(tcx, e) {
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571
        LvalueExpr => true,
        RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
    }
}

/// We categorize expressions into three kinds.  The distinction between
/// lvalue/rvalue is fundamental to the language.  The distinction between the
/// two kinds of rvalues is an artifact of trans which reflects how we will
/// generate code for that kind of expression.  See trans/expr.rs for more
/// information.
3572
pub enum ExprKind {
3573 3574 3575 3576 3577 3578
    LvalueExpr,
    RvalueDpsExpr,
    RvalueDatumExpr,
    RvalueStmtExpr
}

3579 3580
pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
    if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
3581
        // Overloaded operations are generally calls, and hence they are
3582
        // generated via DPS, but there are a few exceptions:
3583
        return match expr.node {
3584
            // `a += b` has a unit result.
3585
            ast::ExprAssignOp(..) => RvalueStmtExpr,
3586 3587

            // the deref method invoked for `*a` always yields an `&T`
3588
            ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
3589

3590 3591 3592
            // the index method invoked for `a[i]` always yields an `&T`
            ast::ExprIndex(..) => LvalueExpr,

N
Nick Cameron 已提交
3593 3594 3595
            // the slice method invoked for `a[..]` always yields an `&T`
            ast::ExprSlice(..) => LvalueExpr,

3596 3597 3598
            // `for` loops are statements
            ast::ExprForLoop(..) => RvalueStmtExpr,

3599
            // in the general case, result could be any type, use DPS
3600 3601
            _ => RvalueDpsExpr
        };
3602 3603 3604
    }

    match expr.node {
3605
        ast::ExprPath(..) => {
3606
            match resolve_expr(tcx, expr) {
3607
                def::DefVariant(tid, vid, _) => {
3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
                    let variant_info = enum_variant_with_id(tcx, tid, vid);
                    if variant_info.args.len() > 0u {
                        // N-ary variant.
                        RvalueDatumExpr
                    } else {
                        // Nullary variant.
                        RvalueDpsExpr
                    }
                }

3618
                def::DefStruct(_) => {
3619 3620 3621 3622 3623
                    match get(expr_ty(tcx, expr)).sty {
                        ty_bare_fn(..) => RvalueDatumExpr,
                        _ => RvalueDpsExpr
                    }
                }
3624

3625 3626
                // Special case: A unit like struct's constructor must be called without () at the
                // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
J
Joseph Crail 已提交
3627
                // of unit structs this is should not be interpreted as function pointer but as
3628
                // call to the constructor.
3629
                def::DefFn(_, true) => RvalueDpsExpr,
3630

3631
                // Fn pointers are just scalar values.
3632
                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
3633

3634
                // Note: there is actually a good case to be made that
3635
                // DefArg's, particularly those of immediate type, ought to
3636
                // considered rvalues.
3637 3638 3639
                def::DefStatic(..) |
                def::DefUpvar(..) |
                def::DefLocal(..) => LvalueExpr,
3640

3641 3642
                def::DefConst(..) => RvalueDatumExpr,

L
Luqman Aden 已提交
3643
                def => {
3644 3645
                    tcx.sess.span_bug(
                        expr.span,
L
Luqman Aden 已提交
3646
                        format!("uncategorized def for expr {}: {}",
3647 3648
                                expr.id,
                                def).as_slice());
3649 3650 3651 3652
                }
            }
        }

3653
        ast::ExprUnary(ast::UnDeref, _) |
A
Alex Crichton 已提交
3654
        ast::ExprField(..) |
3655
        ast::ExprTupField(..) |
N
Nick Cameron 已提交
3656 3657
        ast::ExprIndex(..) |
        ast::ExprSlice(..) => {
3658 3659 3660
            LvalueExpr
        }

A
Alex Crichton 已提交
3661 3662 3663 3664 3665 3666 3667 3668
        ast::ExprCall(..) |
        ast::ExprMethodCall(..) |
        ast::ExprStruct(..) |
        ast::ExprTup(..) |
        ast::ExprIf(..) |
        ast::ExprMatch(..) |
        ast::ExprFnBlock(..) |
        ast::ExprProc(..) |
3669
        ast::ExprUnboxedFn(..) |
A
Alex Crichton 已提交
3670 3671 3672
        ast::ExprBlock(..) |
        ast::ExprRepeat(..) |
        ast::ExprVec(..) => {
3673 3674 3675
            RvalueDpsExpr
        }

K
Kevin Ballard 已提交
3676 3677 3678
        ast::ExprIfLet(..) => {
            tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
        }
J
John Gallagher 已提交
3679 3680 3681
        ast::ExprWhileLet(..) => {
            tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
        }
K
Kevin Ballard 已提交
3682

3683
        ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
3684 3685 3686
            RvalueDpsExpr
        }

A
Alex Crichton 已提交
3687
        ast::ExprCast(..) => {
3688
            match tcx.node_types.borrow().find(&(expr.id as uint)) {
D
Daniel Micay 已提交
3689
                Some(&t) => {
3690
                    if type_is_trait(t) {
3691
                        RvalueDpsExpr
3692 3693
                    } else {
                        RvalueDatumExpr
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705
                    }
                }
                None => {
                    // Technically, it should not happen that the expr is not
                    // present within the table.  However, it DOES happen
                    // during type check, because the final types from the
                    // expressions are not yet recorded in the tcx.  At that
                    // time, though, we are only interested in knowing lvalue
                    // vs rvalue.  It would be better to base this decision on
                    // the AST type in cast node---but (at the time of this
                    // writing) it's not easy to distinguish casts to traits
                    // from other casts based on the AST.  This should be
3706
                    // easier in the future, when casts to traits
3707
                    // would like @Foo, Box<Foo>, or &Foo.
3708 3709 3710 3711 3712
                    RvalueDatumExpr
                }
            }
        }

A
Alex Crichton 已提交
3713 3714 3715 3716 3717 3718 3719
        ast::ExprBreak(..) |
        ast::ExprAgain(..) |
        ast::ExprRet(..) |
        ast::ExprWhile(..) |
        ast::ExprLoop(..) |
        ast::ExprAssign(..) |
        ast::ExprInlineAsm(..) |
3720 3721
        ast::ExprAssignOp(..) |
        ast::ExprForLoop(..) => {
3722 3723 3724
            RvalueStmtExpr
        }

3725
        ast::ExprLit(_) | // Note: LitStr is carved out above
A
Alex Crichton 已提交
3726 3727
        ast::ExprUnary(..) |
        ast::ExprAddrOf(..) |
N
Nick Cameron 已提交
3728
        ast::ExprBinary(..) => {
3729 3730 3731
            RvalueDatumExpr
        }

3732
        ast::ExprBox(ref place, _) => {
E
Eduard Burtescu 已提交
3733
            // Special case `Box<T>` for now:
3734
            let definition = match tcx.def_map.borrow().find(&place.id) {
3735
                Some(&def) => def,
S
Steve Klabnik 已提交
3736
                None => panic!("no def for place"),
3737
            };
3738
            let def_id = definition.def_id();
E
Eduard Burtescu 已提交
3739
            if tcx.lang_items.exchange_heap() == Some(def_id) {
3740 3741 3742
                RvalueDatumExpr
            } else {
                RvalueDpsExpr
3743 3744 3745
            }
        }

3746
        ast::ExprParen(ref e) => expr_kind(tcx, &**e),
3747

A
Alex Crichton 已提交
3748
        ast::ExprMac(..) => {
3749 3750
            tcx.sess.span_bug(
                expr.span,
S
Seo Sanghyeon 已提交
3751
                "macro expression remains after expansion");
3752
        }
M
Marijn Haverbeke 已提交
3753 3754 3755
    }
}

3756
pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
3757
    match s.node {
3758
      ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
B
Brian Anderson 已提交
3759
        return id;
3760
      }
S
Steve Klabnik 已提交
3761
      ast::StmtMac(..) => panic!("unexpanded macro in trans")
3762 3763 3764
    }
}

E
Eduard Burtescu 已提交
3765
pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
3766
                     -> uint {
3767
    let mut i = 0u;
3768
    for f in fields.iter() { if f.name == name { return i; } i += 1u; }
A
Alex Crichton 已提交
3769
    tcx.sess.bug(format!(
L
Luqman Aden 已提交
3770
        "no field named `{}` found in the list of fields `{}`",
3771
        token::get_name(name),
3772
        fields.iter()
3773
              .map(|f| token::get_name(f.name).get().to_string())
3774
              .collect::<Vec<String>>()).as_slice());
3775 3776
}

3777
pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
3778
                              -> Option<uint> {
3779
    trait_items.iter().position(|m| m.name() == id)
3780 3781
}

3782
pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
3783
    match get(t).sty {
J
Jakub Bukaj 已提交
3784
        ty_nil | ty_bool | ty_char | ty_int(_) |
3785
        ty_uint(_) | ty_float(_) | ty_str => {
3786
            ::util::ppaux::ty_to_string(cx, t)
3787 3788
        }

A
Alex Crichton 已提交
3789
        ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
3790
        ty_uniq(_) => "box".to_string(),
3791 3792
        ty_vec(_, Some(n)) => format!("array of {} elements", n),
        ty_vec(_, None) => "slice".to_string(),
3793 3794 3795 3796
        ty_ptr(_) => "*-ptr".to_string(),
        ty_rptr(_, _) => "&-ptr".to_string(),
        ty_bare_fn(_) => "extern fn".to_string(),
        ty_closure(_) => "fn".to_string(),
3797
        ty_trait(ref inner) => {
A
Alex Crichton 已提交
3798
            format!("trait {}", item_path_str(cx, inner.def_id))
3799 3800
        }
        ty_struct(id, _) => {
A
Alex Crichton 已提交
3801
            format!("struct {}", item_path_str(cx, id))
3802
        }
3803
        ty_unboxed_closure(..) => "closure".to_string(),
3804 3805 3806 3807
        ty_tup(_) => "tuple".to_string(),
        ty_infer(TyVar(_)) => "inferred type".to_string(),
        ty_infer(IntVar(_)) => "integral variable".to_string(),
        ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
3808 3809
        ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
        ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
3810 3811 3812 3813 3814 3815 3816
        ty_param(ref p) => {
            if p.space == subst::SelfSpace {
                "Self".to_string()
            } else {
                "type parameter".to_string()
            }
        }
3817
        ty_err => "type error".to_string(),
N
Nick Cameron 已提交
3818
        ty_open(_) => "opened DST".to_string(),
3819 3820 3821
    }
}

3822
pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> String {
3823 3824 3825 3826 3827 3828 3829 3830 3831
    /*!
     *
     * Explains the source of a type err in a short,
     * human readable way.  This is meant to be placed in
     * parentheses after some larger message.  You should
     * also invoke `note_and_explain_type_err()` afterwards
     * to present additional details, particularly when
     * it comes to lifetime-related errors. */

3832
    fn tstore_to_closure(s: &TraitStore) -> String {
3833
        match s {
3834 3835
            &UniqTraitStore => "proc".to_string(),
            &RegionTraitStore(..) => "closure".to_string()
3836 3837 3838
        }
    }

N
Niko Matsakis 已提交
3839
    match *err {
3840
        terr_cyclic_ty => "cyclic type of infinite size".to_string(),
3841
        terr_mismatch => "types differ".to_string(),
3842
        terr_fn_style_mismatch(values) => {
3843
            format!("expected {} fn, found {} fn",
3844 3845
                    values.expected.to_string(),
                    values.found.to_string())
3846
        }
3847
        terr_abi_mismatch(values) => {
3848
            format!("expected {} fn, found {} fn",
3849 3850
                    values.expected.to_string(),
                    values.found.to_string())
3851
        }
3852
        terr_onceness_mismatch(values) => {
3853
            format!("expected {} fn, found {} fn",
3854 3855
                    values.expected.to_string(),
                    values.found.to_string())
3856
        }
3857
        terr_sigil_mismatch(values) => {
A
Alex Crichton 已提交
3858 3859 3860
            format!("expected {}, found {}",
                    tstore_to_closure(&values.expected),
                    tstore_to_closure(&values.found))
3861
        }
3862
        terr_mutability => "values differ in mutability".to_string(),
3863
        terr_box_mutability => {
3864
            "boxed values differ in mutability".to_string()
3865
        }
3866 3867 3868
        terr_vec_mutability => "vectors differ in mutability".to_string(),
        terr_ptr_mutability => "pointers differ in mutability".to_string(),
        terr_ref_mutability => "references differ in mutability".to_string(),
3869
        terr_ty_param_size(values) => {
3870 3871
            format!("expected a type with {} type params, \
                     found one with {} type params",
A
Alex Crichton 已提交
3872 3873
                    values.expected,
                    values.found)
3874
        }
3875 3876
        terr_fixed_array_size(values) => {
            format!("expected an array with a fixed size of {} elements, \
3877
                     found one with {} elements",
A
Alex Crichton 已提交
3878 3879
                    values.expected,
                    values.found)
3880
        }
3881 3882 3883
        terr_tuple_size(values) => {
            format!("expected a tuple with {} elements, \
                     found one with {} elements",
A
Alex Crichton 已提交
3884 3885
                    values.expected,
                    values.found)
3886
        }
3887
        terr_arg_count => {
3888
            "incorrect number of function parameters".to_string()
3889
        }
A
Alex Crichton 已提交
3890
        terr_regions_does_not_outlive(..) => {
3891
            "lifetime mismatch".to_string()
3892
        }
A
Alex Crichton 已提交
3893
        terr_regions_not_same(..) => {
3894
            "lifetimes are not the same".to_string()
3895
        }
A
Alex Crichton 已提交
3896
        terr_regions_no_overlap(..) => {
3897
            "lifetimes do not intersect".to_string()
3898 3899
        }
        terr_regions_insufficiently_polymorphic(br, _) => {
A
Alex Crichton 已提交
3900
            format!("expected bound lifetime parameter {}, \
3901
                     found concrete lifetime",
3902
                    bound_region_ptr_to_string(cx, br))
3903 3904
        }
        terr_regions_overly_polymorphic(br, _) => {
A
Alex Crichton 已提交
3905
            format!("expected concrete lifetime, \
3906
                     found bound lifetime parameter {}",
3907
                    bound_region_ptr_to_string(cx, br))
3908
        }
3909
        terr_trait_stores_differ(_, ref values) => {
3910
            format!("trait storage differs: expected `{}`, found `{}`",
3911 3912
                    trait_store_to_string(cx, (*values).expected),
                    trait_store_to_string(cx, (*values).found))
3913
        }
3914
        terr_sorts(values) => {
J
Jakub Bukaj 已提交
3915 3916 3917 3918 3919 3920 3921 3922 3923
            // A naive approach to making sure that we're not reporting silly errors such as:
            // (expected closure, found closure).
            let expected_str = ty_sort_string(cx, values.expected);
            let found_str = ty_sort_string(cx, values.found);
            if expected_str == found_str {
                format!("expected {}, found a different {}", expected_str, found_str)
            } else {
                format!("expected {}, found {}", expected_str, found_str)
            }
3924
        }
3925
        terr_traits(values) => {
3926
            format!("expected trait `{}`, found trait `{}`",
A
Alex Crichton 已提交
3927 3928
                    item_path_str(cx, values.expected),
                    item_path_str(cx, values.found))
3929
        }
3930 3931
        terr_builtin_bounds(values) => {
            if values.expected.is_empty() {
3932
                format!("expected no bounds, found `{}`",
A
Alex Crichton 已提交
3933
                        values.found.user_string(cx))
3934
            } else if values.found.is_empty() {
3935
                format!("expected bounds `{}`, found no bounds",
A
Alex Crichton 已提交
3936
                        values.expected.user_string(cx))
3937
            } else {
3938
                format!("expected bounds `{}`, found bounds `{}`",
A
Alex Crichton 已提交
3939 3940
                        values.expected.user_string(cx),
                        values.found.user_string(cx))
3941 3942
            }
        }
3943
        terr_integer_as_char => {
3944
            "expected an integral type, found `char`".to_string()
3945
        }
3946
        terr_int_mismatch(ref values) => {
3947
            format!("expected `{}`, found `{}`",
3948 3949
                    values.expected.to_string(),
                    values.found.to_string())
3950 3951
        }
        terr_float_mismatch(ref values) => {
3952
            format!("expected `{}`, found `{}`",
3953 3954
                    values.expected.to_string(),
                    values.found.to_string())
3955
        }
3956
        terr_variadic_mismatch(ref values) => {
3957
            format!("expected {} fn, found {} function",
A
Alex Crichton 已提交
3958 3959
                    if values.expected { "variadic" } else { "non-variadic" },
                    if values.found { "variadic" } else { "non-variadic" })
3960
        }
J
Jakub Bukaj 已提交
3961 3962 3963 3964 3965
        terr_convergence_mismatch(ref values) => {
            format!("expected {} fn, found {} function",
                    if values.expected { "converging" } else { "diverging" },
                    if values.found { "converging" } else { "diverging" })
        }
3966 3967 3968
    }
}

E
Eduard Burtescu 已提交
3969
pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
3970 3971
    match *err {
        terr_regions_does_not_outlive(subregion, superregion) => {
3972 3973 3974
            note_and_explain_region(cx, "", subregion, "...");
            note_and_explain_region(cx, "...does not necessarily outlive ",
                                    superregion, "");
3975 3976
        }
        terr_regions_not_same(region1, region2) => {
3977 3978 3979
            note_and_explain_region(cx, "", region1, "...");
            note_and_explain_region(cx, "...is not the same lifetime as ",
                                    region2, "");
3980 3981
        }
        terr_regions_no_overlap(region1, region2) => {
3982 3983 3984
            note_and_explain_region(cx, "", region1, "...");
            note_and_explain_region(cx, "...does not overlap ",
                                    region2, "");
3985
        }
3986 3987
        terr_regions_insufficiently_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
3988 3989
                                    "concrete lifetime that was found is ",
                                    conc_region, "");
3990 3991 3992
        }
        terr_regions_overly_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
3993 3994
                                    "expected concrete lifetime is ",
                                    conc_region, "");
3995
        }
3996 3997 3998 3999
        _ => {}
    }
}

E
Eduard Burtescu 已提交
4000
pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
4001
    cx.provided_method_sources.borrow().find(&id).map(|x| *x)
4002 4003
}

E
Eduard Burtescu 已提交
4004
pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
4005
    if is_local(id) {
E
Eduard Burtescu 已提交
4006 4007 4008
        match cx.map.find(id.node) {
            Some(ast_map::NodeItem(item)) => {
                match item.node {
4009
                    ItemTrait(_, _, _, ref ms) => {
4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022
                        let (_, p) =
                            ast_util::split_trait_methods(ms.as_slice());
                        p.iter()
                         .map(|m| {
                            match impl_or_trait_item(
                                    cx,
                                    ast_util::local_def(m.id)) {
                                MethodTraitItem(m) => m,
                                TypeTraitItem(_) => {
                                    cx.sess.bug("provided_trait_methods(): \
                                                 split_trait_methods() put \
                                                 associated types in the \
                                                 provided method bucket?!")
4023
                                }
4024
                            }
4025
                         }).collect()
4026
                    }
4027 4028 4029 4030 4031
                    _ => {
                        cx.sess.bug(format!("provided_trait_methods: `{}` is \
                                             not a trait",
                                            id).as_slice())
                    }
4032
                }
P
Patrick Walton 已提交
4033
            }
4034 4035 4036 4037 4038
            _ => {
                cx.sess.bug(format!("provided_trait_methods: `{}` is not a \
                                     trait",
                                    id).as_slice())
            }
4039
        }
4040
    } else {
4041
        csearch::get_provided_trait_methods(cx, id)
4042 4043 4044
    }
}

4045
fn lookup_locally_or_in_crate_store<V:Clone>(
4046 4047
                                    descr: &str,
                                    def_id: ast::DefId,
4048
                                    map: &mut DefIdMap<V>,
4049
                                    load_external: || -> V) -> V {
4050 4051 4052
    /*!
     * Helper for looking things up in the various maps
     * that are populated during typeck::collect (e.g.,
4053
     * `cx.impl_or_trait_items`, `cx.tcache`, etc).  All of these share
4054 4055 4056 4057 4058 4059
     * the pattern that if the id is local, it should have
     * been loaded into the map by the `typeck::collect` phase.
     * If the def-id is external, then we have to go consult
     * the crate loading code (and cache the result for the future).
     */

4060 4061
    match map.find_copy(&def_id) {
        Some(v) => { return v; }
4062 4063 4064
        None => { }
    }

4065
    if def_id.krate == ast::LOCAL_CRATE {
S
Steve Klabnik 已提交
4066
        panic!("No def'n found for {} in tcx.{}", def_id, descr);
4067 4068
    }
    let v = load_external();
4069 4070
    map.insert(def_id, v.clone());
    v
4071 4072
}

4073 4074
pub fn trait_item(cx: &ctxt, trait_did: ast::DefId, idx: uint)
                  -> ImplOrTraitItem {
4075
    let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id();
4076
    impl_or_trait_item(cx, method_def_id)
4077 4078
}

4079 4080 4081 4082 4083
pub fn trait_items(cx: &ctxt, trait_did: ast::DefId)
                   -> Rc<Vec<ImplOrTraitItem>> {
    let mut trait_items = cx.trait_items_cache.borrow_mut();
    match trait_items.find_copy(&trait_did) {
        Some(trait_items) => trait_items,
4084
        None => {
4085 4086 4087 4088 4089 4090 4091
            let def_ids = ty::trait_item_def_ids(cx, trait_did);
            let items: Rc<Vec<ImplOrTraitItem>> =
                Rc::new(def_ids.iter()
                               .map(|d| impl_or_trait_item(cx, d.def_id()))
                               .collect());
            trait_items.insert(trait_did, items.clone());
            items
4092
        }
4093 4094
    }
}
4095

4096 4097 4098 4099 4100 4101 4102
pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
    lookup_locally_or_in_crate_store("impl_or_trait_items",
                                     id,
                                     &mut *cx.impl_or_trait_items
                                             .borrow_mut(),
                                     || {
        csearch::get_impl_or_trait_item(cx, id)
4103
    })
4104 4105
}

4106 4107 4108
/// Returns true if the given ID refers to an associated type and false if it
/// refers to anything else.
pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
4109 4110 4111 4112 4113 4114 4115 4116
    memoized(&cx.associated_types, id, |id: ast::DefId| {
        if id.krate == ast::LOCAL_CRATE {
            match cx.impl_or_trait_items.borrow().find(&id) {
                Some(ref item) => {
                    match **item {
                        TypeTraitItem(_) => true,
                        MethodTraitItem(_) => false,
                    }
4117
                }
4118
                None => false,
4119
            }
4120 4121
        } else {
            csearch::is_associated_type(&cx.sess.cstore, id)
4122
        }
4123
    })
4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142
}

/// Returns the parameter index that the given associated type corresponds to.
pub fn associated_type_parameter_index(cx: &ctxt,
                                       trait_def: &TraitDef,
                                       associated_type_id: ast::DefId)
                                       -> uint {
    for type_parameter_def in trait_def.generics.types.iter() {
        if type_parameter_def.def_id == associated_type_id {
            return type_parameter_def.index
        }
    }
    cx.sess.bug("couldn't find associated type parameter index")
}

#[deriving(PartialEq, Eq)]
pub struct AssociatedTypeInfo {
    pub def_id: ast::DefId,
    pub index: uint,
4143
    pub name: ast::Name,
4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169
}

impl PartialOrd for AssociatedTypeInfo {
    fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
        Some(self.index.cmp(&other.index))
    }
}

impl Ord for AssociatedTypeInfo {
    fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
        self.index.cmp(&other.index)
    }
}

/// Returns the associated types belonging to the given trait, in parameter
/// order.
pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
                                  -> Rc<Vec<AssociatedTypeInfo>> {
    cx.trait_associated_types
      .borrow()
      .find(&trait_id)
      .expect("associated_types_for_trait(): trait not found, try calling \
               ensure_associated_types()")
      .clone()
}

4170 4171 4172
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
                          -> Rc<Vec<ImplOrTraitItemId>> {
    lookup_locally_or_in_crate_store("trait_item_def_ids",
4173
                                     id,
4174
                                     &mut *cx.trait_item_def_ids.borrow_mut(),
4175
                                     || {
4176
        Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
4177
    })
4178 4179
}

E
Eduard Burtescu 已提交
4180
pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<Rc<TraitRef>> {
4181 4182
    memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
        if id.krate == ast::LOCAL_CRATE {
L
Luqman Aden 已提交
4183
            debug!("(impl_trait_ref) searching for trait impl {}", id);
4184 4185 4186 4187 4188 4189 4190 4191 4192
            match cx.map.find(id.node) {
                Some(ast_map::NodeItem(item)) => {
                    match item.node {
                        ast::ItemImpl(_, ref opt_trait, _, _) => {
                            match opt_trait {
                                &Some(ref t) => {
                                    Some(ty::node_id_to_trait_ref(cx, t.ref_id))
                                }
                                &None => None
4193 4194
                            }
                        }
4195
                        _ => None
P
Patrick Walton 已提交
4196
                    }
4197
                }
4198
                _ => None
4199
            }
4200 4201
        } else {
            csearch::get_impl_trait(cx, id)
4202
        }
4203
    })
4204 4205
}

E
Eduard Burtescu 已提交
4206
pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
4207
    let def = *tcx.def_map.borrow()
P
Patrick Walton 已提交
4208 4209
                     .find(&tr.ref_id)
                     .expect("no def-map entry for trait");
4210
    def.def_id()
4211 4212
}

4213 4214 4215 4216 4217 4218
pub fn try_add_builtin_trait(
    tcx: &ctxt,
    trait_def_id: ast::DefId,
    builtin_bounds: &mut EnumSet<BuiltinBound>)
    -> bool
{
4219 4220 4221 4222 4223 4224 4225 4226 4227
    //! Checks whether `trait_ref` refers to one of the builtin
    //! traits, like `Send`, and adds the corresponding
    //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
    //! is a builtin trait.

    match tcx.lang_items.to_builtin_kind(trait_def_id) {
        Some(bound) => { builtin_bounds.add(bound); true }
        None => false
    }
4228 4229
}

4230
pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
4231
    match get(ty).sty {
4232 4233
        ty_trait(box TyTrait { def_id: id, .. }) |
        ty_struct(id, _) |
4234
        ty_enum(id, _) |
4235
        ty_unboxed_closure(id, _, _) => Some(id),
C
Corey Richardson 已提交
4236
        _ => None
4237 4238 4239
    }
}

4240
// Enum information
4241
#[deriving(Clone)]
4242
pub struct VariantInfo {
4243 4244
    pub args: Vec<t>,
    pub arg_names: Option<Vec<ast::Ident> >,
J
Jakub Bukaj 已提交
4245
    pub ctor_ty: Option<t>,
4246
    pub name: ast::Name,
4247 4248 4249
    pub id: ast::DefId,
    pub disr_val: Disr,
    pub vis: Visibility
4250 4251
}

4252 4253 4254 4255 4256
impl VariantInfo {

    /// Creates a new VariantInfo from the corresponding ast representation.
    ///
    /// Does not do any caching of the value in the type context.
E
Eduard Burtescu 已提交
4257
    pub fn from_ast_variant(cx: &ctxt,
4258
                            ast_variant: &ast::Variant,
4259
                            discriminant: Disr) -> VariantInfo {
4260 4261 4262
        let ctor_ty = node_id_to_type(cx, ast_variant.node.id);

        match ast_variant.node.kind {
4263
            ast::TupleVariantKind(ref args) => {
4264
                let arg_tys = if args.len() > 0 {
4265
                    ty_fn_args(ctor_ty).iter().map(|a| *a).collect()
4266 4267 4268
                } else {
                    Vec::new()
                };
4269 4270 4271 4272

                return VariantInfo {
                    args: arg_tys,
                    arg_names: None,
J
Jakub Bukaj 已提交
4273
                    ctor_ty: Some(ctor_ty),
4274
                    name: ast_variant.node.name.name,
4275 4276 4277 4278 4279
                    id: ast_util::local_def(ast_variant.node.id),
                    disr_val: discriminant,
                    vis: ast_variant.node.vis
                };
            },
4280
            ast::StructVariantKind(ref struct_def) => {
4281

4282
                let fields: &[StructField] = struct_def.fields.as_slice();
4283 4284 4285

                assert!(fields.len() > 0);

J
Jakub Bukaj 已提交
4286 4287
                let arg_tys = struct_def.fields.iter()
                    .map(|field| node_id_to_type(cx, field.node.id)).collect();
4288
                let arg_names = fields.iter().map(|field| {
4289
                    match field.node.kind {
4290
                        NamedField(ident, _) => ident,
4291
                        UnnamedField(..) => cx.sess.bug(
4292
                            "enum_variants: all fields in struct must have a name")
4293
                    }
4294
                }).collect();
4295 4296 4297 4298

                return VariantInfo {
                    args: arg_tys,
                    arg_names: Some(arg_names),
J
Jakub Bukaj 已提交
4299
                    ctor_ty: None,
4300
                    name: ast_variant.node.name.name,
4301 4302 4303 4304 4305 4306 4307 4308
                    id: ast_util::local_def(ast_variant.node.id),
                    disr_val: discriminant,
                    vis: ast_variant.node.vis
                };
            }
        }
    }
}
M
Marijn Haverbeke 已提交
4309

E
Eduard Burtescu 已提交
4310
pub fn substd_enum_variants(cx: &ctxt,
4311
                            id: ast::DefId,
4312
                            substs: &Substs)
E
Eduard Burtescu 已提交
4313
                         -> Vec<Rc<VariantInfo>> {
4314
    enum_variants(cx, id).iter().map(|variant_info| {
4315
        let substd_args = variant_info.args.iter()
4316
            .map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>();
4317

4318
        let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
4319

E
Eduard Burtescu 已提交
4320
        Rc::new(VariantInfo {
4321 4322 4323
            args: substd_args,
            ctor_ty: substd_ctor_ty,
            ..(**variant_info).clone()
E
Eduard Burtescu 已提交
4324
        })
4325
    }).collect()
4326 4327
}

4328
pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
4329
    with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
4330 4331
}

4332
pub enum DtorKind {
4333
    NoDtor,
4334
    TraitDtor(DefId, bool)
4335 4336
}

4337
impl DtorKind {
J
Jakub Wieczorek 已提交
4338
    pub fn is_present(&self) -> bool {
4339
        match *self {
J
Jakub Wieczorek 已提交
4340
            TraitDtor(..) => true,
4341 4342 4343
            _ => false
        }
    }
4344

4345 4346 4347 4348 4349 4350
    pub fn has_drop_flag(&self) -> bool {
        match self {
            &NoDtor => false,
            &TraitDtor(_, flag) => flag
        }
    }
4351 4352
}

4353
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
4354
   Otherwise return none. */
E
Eduard Burtescu 已提交
4355
pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
4356
    match cx.destructor_for_type.borrow().find(&struct_id) {
4357
        Some(&method_def_id) => {
4358
            let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
4359 4360 4361

            TraitDtor(method_def_id, flag)
        }
4362
        None => NoDtor,
4363 4364 4365
    }
}

E
Eduard Burtescu 已提交
4366
pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
4367
    cx.destructor_for_type.borrow().contains_key(&struct_id)
4368 4369
}

E
Eduard Burtescu 已提交
4370
pub fn with_path<T>(cx: &ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
4371 4372 4373 4374
    if id.krate == ast::LOCAL_CRATE {
        cx.map.with_path(id.node, f)
    } else {
        f(ast_map::Values(csearch::get_item_path(cx, id).iter()).chain(None))
4375 4376 4377
    }
}

E
Eduard Burtescu 已提交
4378
pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
4379
    enum_variants(cx, id).len() == 1
4380 4381
}

E
Eduard Burtescu 已提交
4382
pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
4383
    match ty::get(t).sty {
B
Brian Anderson 已提交
4384 4385
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
4386 4387 4388
     }
}

E
Eduard Burtescu 已提交
4389
pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442
    memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
        if ast::LOCAL_CRATE != id.krate {
            Rc::new(csearch::get_enum_variants(cx, id))
        } else {
            /*
              Although both this code and check_enum_variants in typeck/check
              call eval_const_expr, it should never get called twice for the same
              expr, since check_enum_variants also updates the enum_var_cache
             */
            match cx.map.get(id.node) {
                ast_map::NodeItem(ref item) => {
                    match item.node {
                        ast::ItemEnum(ref enum_definition, _) => {
                            let mut last_discriminant: Option<Disr> = None;
                            Rc::new(enum_definition.variants.iter().map(|variant| {

                                let mut discriminant = match last_discriminant {
                                    Some(val) => val + 1,
                                    None => INITIAL_DISCRIMINANT_VALUE
                                };

                                match variant.node.disr_expr {
                                    Some(ref e) =>
                                        match const_eval::eval_const_expr_partial(cx, &**e) {
                                            Ok(const_eval::const_int(val)) => {
                                                discriminant = val as Disr
                                            }
                                            Ok(const_eval::const_uint(val)) => {
                                                discriminant = val as Disr
                                            }
                                            Ok(_) => {
                                                cx.sess
                                                  .span_err(e.span,
                                                            "expected signed integer constant");
                                            }
                                            Err(ref err) => {
                                                cx.sess
                                                  .span_err(e.span,
                                                            format!("expected constant: {}",
                                                                    *err).as_slice());
                                            }
                                        },
                                    None => {}
                                };

                                last_discriminant = Some(discriminant);
                                Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
                                                                      discriminant))
                            }).collect())
                        }
                        _ => {
                            cx.sess.bug("enum_variants: id not bound to an enum")
                        }
4443
                    }
E
Eduard Burtescu 已提交
4444
                }
4445
                _ => cx.sess.bug("enum_variants: id not bound to an enum")
P
Patrick Walton 已提交
4446
            }
4447
        }
4448
    })
4449
}
4450

P
Patrick Walton 已提交
4451
// Returns information about the enum variant with the given ID:
E
Eduard Burtescu 已提交
4452
pub fn enum_variant_with_id(cx: &ctxt,
4453 4454
                            enum_id: ast::DefId,
                            variant_id: ast::DefId)
E
Eduard Burtescu 已提交
4455 4456 4457 4458 4459
                         -> Rc<VariantInfo> {
    enum_variants(cx, enum_id).iter()
                              .find(|variant| variant.id == variant_id)
                              .expect("enum_variant_with_id(): no variant exists with that ID")
                              .clone()
4460 4461
}

4462

4463 4464
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
E
Eduard Burtescu 已提交
4465
pub fn lookup_item_type(cx: &ctxt,
4466
                        did: ast::DefId)
4467
                     -> Polytype {
4468
    lookup_locally_or_in_crate_store(
4469
        "tcache", did, &mut *cx.tcache.borrow_mut(),
4470
        || csearch::get_type(cx, did))
T
Tim Chevalier 已提交
4471 4472
}

4473
/// Given the did of a trait, returns its canonical trait ref.
4474 4475 4476 4477 4478
pub fn lookup_trait_def(cx: &ctxt, did: DefId) -> Rc<ty::TraitDef> {
    memoized(&cx.trait_defs, did, |did: DefId| {
        assert!(did.krate != ast::LOCAL_CRATE);
        Rc::new(csearch::get_trait_def(cx, did))
    })
4479 4480
}

4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492
/// Given a reference to a trait, returns the bounds declared on the
/// trait, with appropriate substitutions applied.
pub fn bounds_for_trait_ref(tcx: &ctxt,
                            trait_ref: &TraitRef)
                            -> ty::ParamBounds
{
    let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
    debug!("bounds_for_trait_ref(trait_def={}, trait_ref={})",
           trait_def.repr(tcx), trait_ref.repr(tcx));
    trait_def.bounds.subst(tcx, &trait_ref.substs)
}

4493
/// Iterate over attributes of a definition.
4494 4495
// (This should really be an iterator, but that would require csearch and
// decoder to use iterators instead of higher-order functions.)
4496
pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool {
4497
    if is_local(did) {
4498
        let item = tcx.map.expect_item(did.node);
L
Luqman Aden 已提交
4499
        item.attrs.iter().all(|attr| f(attr))
4500
    } else {
4501
        info!("getting foreign attrs");
4502
        let mut cont = true;
4503
        csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
4504
            if cont {
L
Luqman Aden 已提交
4505
                cont = attrs.iter().all(|attr| f(attr));
4506
            }
4507
        });
4508
        info!("done");
4509
        cont
4510 4511 4512
    }
}

4513
/// Determine whether an item is annotated with an attribute
E
Eduard Burtescu 已提交
4514
pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
4515 4516
    let mut found = false;
    each_attr(tcx, did, |item| {
4517
        if item.check_name(attr) {
4518 4519 4520 4521 4522 4523
            found = true;
            false
        } else {
            true
        }
    });
4524
    found
4525 4526
}

4527
/// Determine whether an item is annotated with `#[repr(packed)]`
E
Eduard Burtescu 已提交
4528
pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
4529
    lookup_repr_hints(tcx, did).contains(&attr::ReprPacked)
4530 4531
}

S
Seo Sanghyeon 已提交
4532
/// Determine whether an item is annotated with `#[simd]`
E
Eduard Burtescu 已提交
4533
pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
S
Seo Sanghyeon 已提交
4534 4535 4536
    has_attr(tcx, did, "simd")
}

4537
/// Obtain the representation annotation for a struct definition.
4538
pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550
    memoized(&tcx.repr_hint_cache, did, |did: DefId| {
        Rc::new(if did.krate == LOCAL_CRATE {
            let mut acc = Vec::new();
            ty::each_attr(tcx, did, |meta| {
                acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(),
                                                 meta).into_iter());
                true
            });
            acc
        } else {
            csearch::get_repr_attrs(&tcx.sess.cstore, did)
        })
4551
    })
4552 4553
}

T
Tim Chevalier 已提交
4554
// Look up a field ID, whether or not it's local
4555
// Takes a list of type substs in case the struct is generic
E
Eduard Burtescu 已提交
4556
pub fn lookup_field_type(tcx: &ctxt,
4557 4558
                         struct_id: DefId,
                         id: DefId,
4559
                         substs: &Substs)
4560
                      -> ty::t {
4561
    let t = if id.krate == ast::LOCAL_CRATE {
T
Tim Chevalier 已提交
4562
        node_id_to_type(tcx, id.node)
4563
    } else {
4564
        let mut tcache = tcx.tcache.borrow_mut();
4565 4566 4567 4568
        let pty = match tcache.entry(id) {
            Occupied(entry) => entry.into_mut(),
            Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
        };
4569
        pty.ty
4570
    };
4571
    t.subst(tcx, substs)
T
Tim Chevalier 已提交
4572 4573
}

4574
// Look up the list of field names and IDs for a given struct.
4575
// Fails if the id is not bound to a struct.
E
Eduard Burtescu 已提交
4576
pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
E
Eduard Burtescu 已提交
4577
    if did.krate == ast::LOCAL_CRATE {
4578
        let struct_fields = cx.struct_fields.borrow();
4579 4580 4581 4582 4583 4584
        match struct_fields.find(&did) {
            Some(fields) => (**fields).clone(),
            _ => {
                cx.sess.bug(
                    format!("ID not mapped to struct fields: {}",
                            cx.map.node_to_string(did.node)).as_slice());
E
Eduard Burtescu 已提交
4585
            }
4586
        }
E
Eduard Burtescu 已提交
4587 4588 4589
    } else {
        csearch::get_struct_fields(&cx.sess.cstore, did)
    }
T
Tim Chevalier 已提交
4590 4591
}

4592 4593 4594 4595 4596
pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
    let fields = lookup_struct_fields(cx, did);
    !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
}

4597 4598
// Returns a list of fields corresponding to the struct's items. trans uses
// this. Takes a list of substs with which to instantiate field types.
4599
pub fn struct_fields(cx: &ctxt, did: ast::DefId, substs: &Substs)
4600
                     -> Vec<field> {
4601
    lookup_struct_fields(cx, did).iter().map(|f| {
4602
       field {
4603
            name: f.name,
4604 4605
            mt: mt {
                ty: lookup_field_type(cx, did, f.id, substs),
4606
                mutbl: MutImmutable
4607 4608
            }
        }
4609
    }).collect()
T
Tim Chevalier 已提交
4610 4611
}

4612 4613 4614 4615 4616
// Returns a list of fields corresponding to the tuple's items. trans uses
// this.
pub fn tup_fields(v: &[t]) -> Vec<field> {
    v.iter().enumerate().map(|(i, &f)| {
       field {
4617
            name: token::intern(i.to_string().as_slice()),
4618 4619 4620 4621 4622 4623 4624 4625
            mt: mt {
                ty: f,
                mutbl: MutImmutable
            }
        }
    }).collect()
}

4626 4627 4628 4629 4630 4631 4632
pub struct UnboxedClosureUpvar {
    pub def: def::Def,
    pub span: Span,
    pub ty: t,
}

// Returns a list of `UnboxedClosureUpvar`s for each upvar.
4633
pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId, substs: &Substs)
4634 4635
                              -> Vec<UnboxedClosureUpvar> {
    if closure_id.krate == ast::LOCAL_CRATE {
4636
        let capture_mode = tcx.capture_modes.borrow().get_copy(&closure_id.node);
4637
        match tcx.freevars.borrow().find(&closure_id.node) {
4638
            None => vec![],
4639 4640 4641
            Some(ref freevars) => {
                freevars.iter().map(|freevar| {
                    let freevar_def_id = freevar.def.def_id();
4642 4643
                    let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
                    let mut freevar_ty = freevar_ty.subst(tcx, substs);
4644 4645 4646 4647 4648 4649 4650 4651 4652 4653
                    if capture_mode == ast::CaptureByRef {
                        let borrow = tcx.upvar_borrow_map.borrow().get_copy(&ty::UpvarId {
                            var_id: freevar_def_id.node,
                            closure_expr_id: closure_id.node
                        });
                        freevar_ty = mk_rptr(tcx, borrow.region, ty::mt {
                            ty: freevar_ty,
                            mutbl: borrow.kind.to_mutbl_lossy()
                        });
                    }
4654 4655 4656
                    UnboxedClosureUpvar {
                        def: freevar.def,
                        span: freevar.span,
4657
                        ty: freevar_ty
4658 4659 4660 4661 4662 4663 4664 4665 4666
                    }
                }).collect()
            }
        }
    } else {
        tcx.sess.bug("unimplemented cross-crate closure upvars")
    }
}

E
Eduard Burtescu 已提交
4667
pub fn is_binopable(cx: &ctxt, ty: t, op: ast::BinOp) -> bool {
A
Aaron Turon 已提交
4668
    #![allow(non_upper_case_globals)]
4669 4670
    static tycat_other: int = 0;
    static tycat_bool: int = 1;
4671 4672 4673
    static tycat_char: int = 2;
    static tycat_int: int = 3;
    static tycat_float: int = 4;
4674
    static tycat_raw_ptr: int = 6;
4675 4676 4677 4678 4679 4680 4681 4682 4683

    static opcat_add: int = 0;
    static opcat_sub: int = 1;
    static opcat_mult: int = 2;
    static opcat_shift: int = 3;
    static opcat_rel: int = 4;
    static opcat_eq: int = 5;
    static opcat_bit: int = 6;
    static opcat_logic: int = 7;
4684
    static opcat_mod: int = 8;
M
Marijn Haverbeke 已提交
4685

4686
    fn opcat(op: ast::BinOp) -> int {
4687
        match op {
4688 4689 4690 4691
          ast::BiAdd => opcat_add,
          ast::BiSub => opcat_sub,
          ast::BiMul => opcat_mult,
          ast::BiDiv => opcat_mult,
4692
          ast::BiRem => opcat_mod,
4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705
          ast::BiAnd => opcat_logic,
          ast::BiOr => opcat_logic,
          ast::BiBitXor => opcat_bit,
          ast::BiBitAnd => opcat_bit,
          ast::BiBitOr => opcat_bit,
          ast::BiShl => opcat_shift,
          ast::BiShr => opcat_shift,
          ast::BiEq => opcat_eq,
          ast::BiNe => opcat_eq,
          ast::BiLt => opcat_rel,
          ast::BiLe => opcat_rel,
          ast::BiGe => opcat_rel,
          ast::BiGt => opcat_rel
M
Marijn Haverbeke 已提交
4706 4707 4708
        }
    }

E
Eduard Burtescu 已提交
4709
    fn tycat(cx: &ctxt, ty: t) -> int {
S
Seo Sanghyeon 已提交
4710 4711 4712
        if type_is_simd(cx, ty) {
            return tycat(cx, simd_type(cx, ty))
        }
4713
        match get(ty).sty {
4714
          ty_char => tycat_char,
B
Brian Anderson 已提交
4715
          ty_bool => tycat_bool,
4716
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4717
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4718
          ty_ptr(_) => tycat_raw_ptr,
B
Brian Anderson 已提交
4719
          _ => tycat_other
M
Marijn Haverbeke 已提交
4720 4721 4722
        }
    }

4723 4724
    static t: bool = true;
    static f: bool = false;
4725

4726
    let tbl = [
4727 4728 4729 4730 4731 4732 4733 4734
    //           +, -, *, shift, rel, ==, bit, logic, mod
    /*other*/   [f, f, f, f,     f,   f,  f,   f,     f],
    /*bool*/    [f, f, f, f,     t,   t,  t,   t,     f],
    /*char*/    [f, f, f, f,     t,   t,  f,   f,     f],
    /*int*/     [t, t, t, t,     t,   t,  t,   f,     t],
    /*float*/   [t, t, t, f,     t,   t,  f,   f,     f],
    /*bot*/     [t, t, t, t,     t,   t,  t,   t,     t],
    /*raw ptr*/ [f, f, f, f,     t,   t,  f,   f,     f]];
B
Brian Anderson 已提交
4735

4736
    return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
4737 4738
}

4739
/// Returns an equivalent type with all the typedefs and self regions removed.
E
Eduard Burtescu 已提交
4740
pub fn normalize_ty(cx: &ctxt, t: t) -> t {
4741 4742
    let u = TypeNormalizer(cx).fold_ty(t);
    return u;
4743

4744
    struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
4745

4746
    impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
4747
        fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
4748

4749
        fn fold_ty(&mut self, t: ty::t) -> ty::t {
4750 4751 4752
            match self.tcx().normalized_cache.borrow().find_copy(&t) {
                None => {}
                Some(u) => return u
4753
            }
4754 4755 4756 4757

            let t_norm = ty_fold::super_fold_ty(self, t);
            self.tcx().normalized_cache.borrow_mut().insert(t, t_norm);
            return t_norm;
4758
        }
4759

4760
        fn fold_region(&mut self, _: ty::Region) -> ty::Region {
4761
            ty::ReStatic
4762 4763 4764
        }

        fn fold_substs(&mut self,
4765 4766 4767
                       substs: &subst::Substs)
                       -> subst::Substs {
            subst::Substs { regions: subst::ErasedRegions,
4768
                            types: substs.types.fold_with(self) }
4769
        }
4770

4771 4772 4773 4774 4775
        fn fold_sig(&mut self,
                    sig: &ty::FnSig)
                    -> ty::FnSig {
            // The binder-id is only relevant to bound regions, which
            // are erased at trans time.
4776 4777
            ty::FnSig {
                binder_id: ast::DUMMY_NODE_ID,
4778 4779
                inputs: sig.inputs.fold_with(self),
                output: sig.output.fold_with(self),
4780 4781
                variadic: sig.variadic,
            }
4782 4783
        }
    }
4784 4785
}

4786
// Returns the repeat count for a repeating vector expression.
4787
pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
4788 4789
    match const_eval::eval_const_expr_partial(tcx, count_expr) {
      Ok(ref const_val) => match *const_val {
4790
        const_eval::const_int(count) => if count < 0 {
4791 4792 4793 4794
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found negative integer");
            0
4795
        } else {
4796
            count as uint
4797
        },
4798
        const_eval::const_uint(count) => count as uint,
4799
        const_eval::const_float(count) => {
4800 4801 4802 4803
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found float");
            count as uint
4804 4805
        }
        const_eval::const_str(_) => {
4806 4807 4808 4809
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found string");
            0
4810
        }
4811
        const_eval::const_bool(_) => {
4812 4813 4814 4815
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found boolean");
            0
4816
        }
4817
        const_eval::const_binary(_) => {
4818 4819 4820 4821
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found binary array");
            0
4822
        }
J
Jakub Wieczorek 已提交
4823
        const_eval::const_nil => {
4824 4825 4826 4827
            tcx.sess.span_err(count_expr.span,
                              "expected positive integer for \
                               repeat count, found ()");
            0
J
Jakub Wieczorek 已提交
4828
        }
4829
      },
A
Alex Crichton 已提交
4830
      Err(..) => {
4831 4832 4833 4834
        tcx.sess.span_err(count_expr.span,
                          "expected constant integer for repeat count, \
                           found variable");
        0
4835
      }
4836 4837 4838
    }
}

4839 4840
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
4841 4842 4843
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
E
Eduard Burtescu 已提交
4844
pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
E
Eduard Burtescu 已提交
4845 4846
                                        bounds: &[Rc<TraitRef>],
                                        f: |Rc<TraitRef>| -> bool)
4847 4848 4849 4850 4851
                                        -> bool
{
    for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
        if !f(bound_trait_ref) {
            return false;
4852 4853 4854 4855
        }
    }
    return true;
}
4856

4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888
pub fn required_region_bounds(tcx: &ctxt,
                              region_bounds: &[ty::Region],
                              builtin_bounds: BuiltinBounds,
                              trait_bounds: &[Rc<TraitRef>])
                              -> Vec<ty::Region>
{
    /*!
     * Given a type which must meet the builtin bounds and trait
     * bounds, returns a set of lifetimes which the type must outlive.
     *
     * Requires that trait definitions have been processed.
     */

    let mut all_bounds = Vec::new();

    debug!("required_region_bounds(builtin_bounds={}, trait_bounds={})",
           builtin_bounds.repr(tcx),
           trait_bounds.repr(tcx));

    all_bounds.push_all(region_bounds);

    push_region_bounds([],
                       builtin_bounds,
                       &mut all_bounds);

    debug!("from builtin bounds: all_bounds={}", all_bounds.repr(tcx));

    each_bound_trait_and_supertraits(
        tcx,
        trait_bounds,
        |trait_ref| {
            let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
4889
            push_region_bounds(bounds.region_bounds.as_slice(),
4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911
                               bounds.builtin_bounds,
                               &mut all_bounds);
            debug!("from {}: bounds={} all_bounds={}",
                   trait_ref.repr(tcx),
                   bounds.repr(tcx),
                   all_bounds.repr(tcx));
            true
        });

    return all_bounds;

    fn push_region_bounds(region_bounds: &[ty::Region],
                          builtin_bounds: ty::BuiltinBounds,
                          all_bounds: &mut Vec<ty::Region>) {
        all_bounds.push_all(region_bounds.as_slice());

        if builtin_bounds.contains_elem(ty::BoundSend) {
            all_bounds.push(ty::ReStatic);
        }
    }
}

4912
pub fn get_tydesc_ty(tcx: &ctxt) -> Result<t, String> {
4913
    tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
4914
        tcx.intrinsic_defs.borrow().find_copy(&tydesc_lang_item)
A
Alex Crichton 已提交
4915
            .expect("Failed to resolve TyDesc")
4916
    })
P
Philipp Brüschweiler 已提交
4917 4918
}

E
Eduard Burtescu 已提交
4919
pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
4920
    lookup_locally_or_in_crate_store(
4921
        "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
E
Eduard Burtescu 已提交
4922
        || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
4923 4924
}

4925
/// Records a trait-to-implementation mapping.
E
Eduard Burtescu 已提交
4926 4927
pub fn record_trait_implementation(tcx: &ctxt,
                                   trait_def_id: DefId,
E
Eduard Burtescu 已提交
4928
                                   impl_def_id: DefId) {
E
Eduard Burtescu 已提交
4929 4930
    match tcx.trait_impls.borrow().find(&trait_def_id) {
        Some(impls_for_trait) => {
E
Eduard Burtescu 已提交
4931
            impls_for_trait.borrow_mut().push(impl_def_id);
E
Eduard Burtescu 已提交
4932
            return;
4933
        }
E
Eduard Burtescu 已提交
4934
        None => {}
4935
    }
E
Eduard Burtescu 已提交
4936
    tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
4937 4938 4939 4940
}

/// Populates the type context with all the implementations for the given type
/// if necessary.
E
Eduard Burtescu 已提交
4941
pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
4942
                                                      type_id: ast::DefId) {
4943
    if type_id.krate == LOCAL_CRATE {
4944 4945
        return
    }
4946 4947
    if tcx.populated_external_types.borrow().contains(&type_id) {
        return
4948 4949
    }

4950
    let mut inherent_impls = Vec::new();
E
Eduard Burtescu 已提交
4951
    csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
E
Eduard Burtescu 已提交
4952
            |impl_def_id| {
4953 4954
        let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
                                                 impl_def_id);
4955 4956

        // Record the trait->implementation mappings, if applicable.
E
Eduard Burtescu 已提交
4957
        let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
4958
        for trait_ref in associated_traits.iter() {
E
Eduard Burtescu 已提交
4959
            record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
4960 4961 4962 4963
        }

        // For any methods that use a default implementation, add them to
        // the map. This is a bit unfortunate.
4964 4965 4966 4967 4968 4969 4970 4971 4972 4973
        for impl_item_def_id in impl_items.iter() {
            let method_def_id = impl_item_def_id.def_id();
            match impl_or_trait_item(tcx, method_def_id) {
                MethodTraitItem(method) => {
                    for &source in method.provided_source.iter() {
                        tcx.provided_method_sources
                           .borrow_mut()
                           .insert(method_def_id, source);
                    }
                }
4974
                TypeTraitItem(_) => {}
4975 4976 4977
            }
        }

E
Eduard Burtescu 已提交
4978
        // Store the implementation info.
4979
        tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
E
Eduard Burtescu 已提交
4980

4981 4982
        // If this is an inherent implementation, record it.
        if associated_traits.is_none() {
4983
            inherent_impls.push(impl_def_id);
4984
        }
4985
    });
4986

4987
    tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
4988
    tcx.populated_external_types.borrow_mut().insert(type_id);
4989 4990 4991 4992 4993
}

/// Populates the type context with all the implementations for the given
/// trait if necessary.
pub fn populate_implementations_for_trait_if_necessary(
E
Eduard Burtescu 已提交
4994
        tcx: &ctxt,
4995
        trait_id: ast::DefId) {
4996
    if trait_id.krate == LOCAL_CRATE {
4997 4998
        return
    }
4999 5000
    if tcx.populated_external_traits.borrow().contains(&trait_id) {
        return
5001 5002
    }

E
Eduard Burtescu 已提交
5003
    csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
5004
            |implementation_def_id| {
5005
        let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
5006 5007

        // Record the trait->implementation mapping.
E
Eduard Burtescu 已提交
5008
        record_trait_implementation(tcx, trait_id, implementation_def_id);
5009 5010 5011

        // For any methods that use a default implementation, add them to
        // the map. This is a bit unfortunate.
5012 5013 5014 5015 5016 5017 5018 5019 5020 5021
        for impl_item_def_id in impl_items.iter() {
            let method_def_id = impl_item_def_id.def_id();
            match impl_or_trait_item(tcx, method_def_id) {
                MethodTraitItem(method) => {
                    for &source in method.provided_source.iter() {
                        tcx.provided_method_sources
                           .borrow_mut()
                           .insert(method_def_id, source);
                    }
                }
5022
                TypeTraitItem(_) => {}
5023 5024 5025 5026
            }
        }

        // Store the implementation info.
5027
        tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
5028
    });
5029

5030
    tcx.populated_external_traits.borrow_mut().insert(trait_id);
5031 5032
}

5033 5034
/// Given the def_id of an impl, return the def_id of the trait it implements.
/// If it implements no trait, return `None`.
E
Eduard Burtescu 已提交
5035
pub fn trait_id_of_impl(tcx: &ctxt,
5036
                        def_id: ast::DefId) -> Option<ast::DefId> {
5037
    let node = match tcx.map.find(def_id.node) {
5038 5039 5040 5041
        Some(node) => node,
        None => return None
    };
    match node {
5042
        ast_map::NodeItem(item) => {
5043
            match item.node {
5044
                ast::ItemImpl(_, Some(ref trait_ref), _, _) => {
5045 5046 5047 5048 5049 5050 5051
                    Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
                }
                _ => None
            }
        }
        _ => None
    }
5052 5053 5054 5055 5056 5057 5058
}

/// If the given def ID describes a method belonging to an impl, return the
/// ID of the impl that the method belongs to. Otherwise, return `None`.
pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
                       -> Option<ast::DefId> {
    if def_id.krate != LOCAL_CRATE {
5059 5060
        return match csearch::get_impl_or_trait_item(tcx,
                                                     def_id).container() {
5061 5062 5063 5064
            TraitContainer(_) => None,
            ImplContainer(def_id) => Some(def_id),
        };
    }
5065 5066 5067
    match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
        Some(trait_item) => {
            match trait_item.container() {
5068 5069 5070 5071 5072 5073
                TraitContainer(_) => None,
                ImplContainer(def_id) => Some(def_id),
            }
        }
        None => None
    }
5074 5075
}

5076
/// If the given def ID describes an item belonging to a trait (either a
5077 5078
/// default method or an implementation of a trait method), return the ID of
/// the trait that the method belongs to. Otherwise, return `None`.
5079
pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
5080
    if def_id.krate != LOCAL_CRATE {
5081
        return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
5082
    }
5083 5084 5085
    match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
        Some(impl_or_trait_item) => {
            match impl_or_trait_item.container() {
5086 5087
                TraitContainer(def_id) => Some(def_id),
                ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
5088 5089
            }
        }
5090
        None => None
5091
    }
5092
}
5093

5094
/// If the given def ID describes an item belonging to a trait, (either a
5095 5096 5097 5098 5099
/// default method or an implementation of a trait method), return the ID of
/// the method inside trait definition (this means that if the given def ID
/// is already that of the original trait method, then the return value is
/// the same).
/// Otherwise, return `None`.
5100 5101 5102
pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
                          -> Option<ImplOrTraitItemId> {
    let impl_item = match tcx.impl_or_trait_items.borrow().find(&def_id) {
E
Eduard Burtescu 已提交
5103
        Some(m) => m.clone(),
5104 5105
        None => return None,
    };
5106
    let name = impl_item.name();
5107
    match trait_of_item(tcx, def_id) {
5108
        Some(trait_did) => {
5109 5110
            let trait_items = ty::trait_items(tcx, trait_did);
            trait_items.iter()
5111
                .position(|m| m.name() == name)
5112
                .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
5113 5114
        }
        None => None
5115 5116
    }
}
A
Alex Crichton 已提交
5117 5118 5119

/// Creates a hash of the type `t` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic.
E
Eduard Burtescu 已提交
5120
pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
5121
    let mut state = sip::SipState::new();
5122 5123
    macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
    macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
5124

5125
    let region = |_state: &mut sip::SipState, r: Region| {
A
Alex Crichton 已提交
5126
        match r {
5127 5128 5129
            ReStatic => {}

            ReEmpty |
A
Alex Crichton 已提交
5130 5131 5132 5133 5134
            ReEarlyBound(..) |
            ReLateBound(..) |
            ReFree(..) |
            ReScope(..) |
            ReInfer(..) => {
A
Alex Crichton 已提交
5135
                tcx.sess.bug("non-static region found when hashing a type")
5136
            }
A
Alex Crichton 已提交
5137 5138
        }
    };
5139
    let did = |state: &mut sip::SipState, did: DefId| {
A
Alex Crichton 已提交
5140
        let h = if ast_util::is_local(did) {
5141
            svh.clone()
A
Alex Crichton 已提交
5142
        } else {
5143
            tcx.sess.cstore.get_crate_hash(did.krate)
A
Alex Crichton 已提交
5144
        };
5145
        h.as_str().hash(state);
5146
        did.node.hash(state);
A
Alex Crichton 已提交
5147
    };
5148 5149
    let mt = |state: &mut sip::SipState, mt: mt| {
        mt.mutbl.hash(state);
A
Alex Crichton 已提交
5150
    };
5151
    ty::walk_ty(t, |t| {
A
Alex Crichton 已提交
5152
        match ty::get(t).sty {
5153 5154 5155
            ty_nil => byte!(0),
            ty_bool => byte!(2),
            ty_char => byte!(3),
A
Alex Crichton 已提交
5156
            ty_int(i) => {
5157 5158
                byte!(4);
                hash!(i);
A
Alex Crichton 已提交
5159 5160
            }
            ty_uint(u) => {
5161 5162
                byte!(5);
                hash!(u);
A
Alex Crichton 已提交
5163 5164
            }
            ty_float(f) => {
5165 5166
                byte!(6);
                hash!(f);
A
Alex Crichton 已提交
5167
            }
5168
            ty_str => {
5169
                byte!(7);
A
Alex Crichton 已提交
5170 5171
            }
            ty_enum(d, _) => {
5172
                byte!(8);
M
Meyer S. Jacobs 已提交
5173
                did(&mut state, d);
A
Alex Crichton 已提交
5174
            }
5175
            ty_uniq(_) => {
E
Eduard Burtescu 已提交
5176
                byte!(9);
A
Alex Crichton 已提交
5177
            }
N
Nick Cameron 已提交
5178
            ty_vec(_, Some(n)) => {
E
Eduard Burtescu 已提交
5179
                byte!(10);
5180
                n.hash(&mut state);
5181
            }
N
Nick Cameron 已提交
5182
            ty_vec(_, None) => {
5183
                byte!(11);
A
Alex Crichton 已提交
5184 5185
            }
            ty_ptr(m) => {
5186
                byte!(12);
5187
                mt(&mut state, m);
A
Alex Crichton 已提交
5188 5189
            }
            ty_rptr(r, m) => {
5190
                byte!(13);
5191 5192
                region(&mut state, r);
                mt(&mut state, m);
A
Alex Crichton 已提交
5193 5194
            }
            ty_bare_fn(ref b) => {
5195
                byte!(14);
5196
                hash!(b.fn_style);
5197
                hash!(b.abi);
A
Alex Crichton 已提交
5198 5199
            }
            ty_closure(ref c) => {
5200
                byte!(15);
5201
                hash!(c.fn_style);
5202 5203
                hash!(c.onceness);
                hash!(c.bounds);
5204 5205 5206 5207 5208 5209 5210 5211
                match c.store {
                    UniqTraitStore => byte!(0),
                    RegionTraitStore(r, m) => {
                        byte!(1)
                        region(&mut state, r);
                        assert_eq!(m, ast::MutMutable);
                    }
                }
A
Alex Crichton 已提交
5212
            }
5213
            ty_trait(box TyTrait { def_id: d, bounds, .. }) => {
5214
                byte!(17);
5215
                did(&mut state, d);
5216
                hash!(bounds);
A
Alex Crichton 已提交
5217 5218
            }
            ty_struct(d, _) => {
5219
                byte!(18);
5220
                did(&mut state, d);
A
Alex Crichton 已提交
5221 5222
            }
            ty_tup(ref inner) => {
5223 5224
                byte!(19);
                hash!(inner.len());
A
Alex Crichton 已提交
5225 5226
            }
            ty_param(p) => {
5227 5228
                byte!(20);
                hash!(p.idx);
5229
                did(&mut state, p.def_id);
A
Alex Crichton 已提交
5230
            }
N
Nick Cameron 已提交
5231
            ty_open(_) => byte!(22),
A
Alex Crichton 已提交
5232
            ty_infer(_) => unreachable!(),
5233
            ty_err => byte!(23),
5234
            ty_unboxed_closure(d, r, _) => {
5235 5236
                byte!(24);
                did(&mut state, d);
5237
                region(&mut state, r);
5238
            }
A
Alex Crichton 已提交
5239
        }
5240
    });
A
Alex Crichton 已提交
5241

5242
    state.result()
A
Alex Crichton 已提交
5243
}
5244

5245
impl Variance {
5246
    pub fn to_string(self) -> &'static str {
5247 5248 5249 5250 5251 5252 5253 5254 5255
        match self {
            Covariant => "+",
            Contravariant => "-",
            Invariant => "o",
            Bivariant => "*",
        }
    }
}

5256 5257 5258 5259 5260 5261 5262 5263 5264 5265
pub fn empty_parameter_environment() -> ParameterEnvironment {
    /*!
     * Construct a parameter environment suitable for static contexts
     * or other contexts where there are no free type/lifetime
     * parameters in scope.
     */

    ty::ParameterEnvironment { free_substs: Substs::empty(),
                               bounds: VecPerParamSpace::empty(),
                               caller_obligations: VecPerParamSpace::empty(),
5266 5267
                               implicit_region_bound: ty::ReEmpty,
                               selection_cache: traits::SelectionCache::new(), }
5268 5269
}

5270
pub fn construct_parameter_environment(
E
Eduard Burtescu 已提交
5271
    tcx: &ctxt,
5272
    span: Span,
5273
    generics: &ty::Generics,
5274 5275 5276 5277 5278 5279 5280 5281 5282
    free_id: ast::NodeId)
    -> ParameterEnvironment
{
    /*! See `ParameterEnvironment` struct def'n for details */

    //
    // Construct the free substs.
    //

5283 5284 5285 5286
    // map T => T
    let mut types = VecPerParamSpace::empty();
    for &space in subst::ParamSpace::all().iter() {
        push_types_from_defs(tcx, &mut types, space,
5287
                             generics.types.get_slice(space));
5288
    }
5289 5290

    // map bound 'a => free 'a
5291 5292 5293
    let mut regions = VecPerParamSpace::empty();
    for &space in subst::ParamSpace::all().iter() {
        push_region_params(&mut regions, space, free_id,
5294
                           generics.regions.get_slice(space));
5295
    }
5296

5297
    let free_substs = Substs {
5298 5299
        types: types,
        regions: subst::NonerasedRegions(regions)
5300 5301 5302 5303 5304 5305
    };

    //
    // Compute the bounds on Self and the type parameters.
    //

5306 5307 5308
    let mut bounds = VecPerParamSpace::empty();
    for &space in subst::ParamSpace::all().iter() {
        push_bounds_from_defs(tcx, &mut bounds, space, &free_substs,
5309
                              generics.types.get_slice(space));
5310
    }
5311

5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323
    //
    // Compute region bounds. For now, these relations are stored in a
    // global table on the tcx, so just enter them there. I'm not
    // crazy about this scheme, but it's convenient, at least.
    //

    for &space in subst::ParamSpace::all().iter() {
        record_region_bounds_from_defs(tcx, space, &free_substs,
                                       generics.regions.get_slice(space));
    }


5324 5325
    debug!("construct_parameter_environment: free_id={} \
           free_subst={} \
5326
           bounds={}",
5327 5328
           free_id,
           free_substs.repr(tcx),
5329
           bounds.repr(tcx));
5330

5331 5332 5333
    let obligations = traits::obligations_for_generics(tcx, traits::ObligationCause::misc(span),
                                                       generics, &free_substs);

5334
    return ty::ParameterEnvironment {
5335
        free_substs: free_substs,
5336 5337
        bounds: bounds,
        implicit_region_bound: ty::ReScope(free_id),
5338
        caller_obligations: obligations,
5339
        selection_cache: traits::SelectionCache::new(),
5340 5341 5342 5343 5344
    };

    fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
                          space: subst::ParamSpace,
                          free_id: ast::NodeId,
5345
                          region_params: &[RegionParameterDef])
5346 5347 5348 5349 5350 5351 5352 5353 5354
    {
        for r in region_params.iter() {
            regions.push(space, ty::free_region_from_def(free_id, r));
        }
    }

    fn push_types_from_defs(tcx: &ty::ctxt,
                            types: &mut subst::VecPerParamSpace<ty::t>,
                            space: subst::ParamSpace,
5355
                            defs: &[TypeParameterDef]) {
5356
        for (i, def) in defs.iter().enumerate() {
5357 5358 5359 5360 5361
            debug!("construct_parameter_environment(): push_types_from_defs: \
                    space={} def={} index={}",
                   space,
                   def.repr(tcx),
                   i);
5362 5363 5364 5365 5366 5367 5368 5369 5370
            let ty = ty::mk_param(tcx, space, i, def.def_id);
            types.push(space, ty);
        }
    }

    fn push_bounds_from_defs(tcx: &ty::ctxt,
                             bounds: &mut subst::VecPerParamSpace<ParamBounds>,
                             space: subst::ParamSpace,
                             free_substs: &subst::Substs,
5371
                             defs: &[TypeParameterDef]) {
5372
        for def in defs.iter() {
5373
            let b = def.bounds.subst(tcx, free_substs);
5374 5375
            bounds.push(space, b);
        }
5376
    }
5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407

    fn record_region_bounds_from_defs(tcx: &ty::ctxt,
                                      space: subst::ParamSpace,
                                      free_substs: &subst::Substs,
                                      defs: &[RegionParameterDef]) {
        for (subst_region, def) in
            free_substs.regions().get_slice(space).iter().zip(
                defs.iter())
        {
            // For each region parameter 'subst...
            let bounds = def.bounds.subst(tcx, free_substs);
            for bound_region in bounds.iter() {
                // Which is declared with a bound like 'subst:'bound...
                match (subst_region, bound_region) {
                    (&ty::ReFree(subst_fr), &ty::ReFree(bound_fr)) => {
                        // Record that 'subst outlives 'bound. Or, put
                        // another way, 'bound <= 'subst.
                        tcx.region_maps.relate_free_regions(bound_fr, subst_fr);
                    },
                    _ => {
                        // All named regions are instantiated with free regions.
                        tcx.sess.bug(
                            format!("push_region_bounds_from_defs: \
                                     non free region: {} / {}",
                                    subst_region.repr(tcx),
                                    bound_region.repr(tcx)).as_slice());
                    }
                }
            }
        }
    }
5408 5409
}

5410 5411 5412 5413 5414 5415 5416 5417
impl BorrowKind {
    pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
        match m {
            ast::MutMutable => MutBorrow,
            ast::MutImmutable => ImmBorrow,
        }
    }

5418 5419 5420 5421 5422
    pub fn to_mutbl_lossy(self) -> ast::Mutability {
        /*!
         * Returns a mutability `m` such that an `&m T` pointer could
         * be used to obtain this borrow kind. Because borrow kinds
         * are richer than mutabilities, we sometimes have to pick a
5423
         * mutability that is stronger than necessary so that it at
5424 5425 5426 5427 5428 5429 5430
         * least *would permit* the borrow in question.
         */

        match self {
            MutBorrow => ast::MutMutable,
            ImmBorrow => ast::MutImmutable,

J
Joseph Crail 已提交
5431
            // We have no type corresponding to a unique imm borrow, so
5432 5433 5434 5435 5436 5437
            // use `&mut`. It gives all the capabilities of an `&uniq`
            // and hence is a safe "over approximation".
            UniqueImmBorrow => ast::MutMutable,
        }
    }

5438 5439 5440 5441 5442 5443 5444 5445
    pub fn to_user_str(&self) -> &'static str {
        match *self {
            MutBorrow => "mutable",
            ImmBorrow => "immutable",
            UniqueImmBorrow => "uniquely immutable",
        }
    }
}
5446

5447 5448
impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474
        self
    }

    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
        Ok(ty::node_id_to_type(self, id))
    }

    fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
        self.method_map.borrow().find(&method_call).map(|method| method.ty)
    }

    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
        &self.adjustments
    }

    fn is_method_call(&self, id: ast::NodeId) -> bool {
        self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
    }

    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
        self.region_maps.temporary_scope(rvalue_id)
    }

    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
        self.upvar_borrow_map.borrow().get_copy(&upvar_id)
    }
5475 5476

    fn capture_mode(&self, closure_expr_id: ast::NodeId)
5477
                    -> ast::CaptureClause {
5478 5479
        self.capture_modes.borrow().get_copy(&closure_expr_id)
    }
5480 5481 5482 5483 5484

    fn unboxed_closures<'a>(&'a self)
                        -> &'a RefCell<DefIdMap<UnboxedClosure>> {
        &self.unboxed_closures
    }
5485
}
5486 5487

/// The category of explicit self.
L
Luqman Aden 已提交
5488
#[deriving(Clone, Eq, PartialEq, Show)]
5489 5490 5491 5492 5493 5494 5495
pub enum ExplicitSelfCategory {
    StaticExplicitSelfCategory,
    ByValueExplicitSelfCategory,
    ByReferenceExplicitSelfCategory(Region, ast::Mutability),
    ByBoxExplicitSelfCategory,
}

5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506
/// Pushes all the lifetimes in the given type onto the given list. A
/// "lifetime in a type" is a lifetime specified by a reference or a lifetime
/// in a list of type substitutions. This does *not* traverse into nominal
/// types, nor does it resolve fictitious types.
pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
                                    typ: t) {
    walk_ty(typ, |typ| {
        match get(typ).sty {
            ty_rptr(region, _) => accumulator.push(region),
            ty_enum(_, ref substs) |
            ty_trait(box TyTrait {
5507
                ref substs,
5508 5509 5510
                ..
            }) |
            ty_struct(_, ref substs) => {
5511
                accum_substs(accumulator, substs);
5512 5513 5514 5515 5516 5517 5518
            }
            ty_closure(ref closure_ty) => {
                match closure_ty.store {
                    RegionTraitStore(region, _) => accumulator.push(region),
                    UniqTraitStore => {}
                }
            }
5519 5520 5521 5522
            ty_unboxed_closure(_, ref region, ref substs) => {
                accumulator.push(*region);
                accum_substs(accumulator, substs);
            }
5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536
            ty_nil |
            ty_bool |
            ty_char |
            ty_int(_) |
            ty_uint(_) |
            ty_float(_) |
            ty_uniq(_) |
            ty_str |
            ty_vec(_, _) |
            ty_ptr(_) |
            ty_bare_fn(_) |
            ty_tup(_) |
            ty_param(_) |
            ty_infer(_) |
N
Nick Cameron 已提交
5537
            ty_open(_) |
5538 5539
            ty_err => {}
        }
5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551
    });

    fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
        match substs.regions {
            subst::ErasedRegions => {}
            subst::NonerasedRegions(ref regions) => {
                for region in regions.iter() {
                    accumulator.push(*region)
                }
            }
        }
    }
5552
}
5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569

/// A free variable referred to in a function.
#[deriving(Encodable, Decodable)]
pub struct Freevar {
    /// The variable being accessed free.
    pub def: def::Def,

    // First span where it is accessed (there can be multiple).
    pub span: Span
}

pub type FreevarMap = NodeMap<Vec<Freevar>>;

pub type CaptureModeMap = NodeMap<ast::CaptureClause>;

pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T {
    match tcx.freevars.borrow().find(&fid) {
5570
        None => f(&[]),
5571 5572 5573
        Some(d) => f(d.as_slice())
    }
}