1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 The collect phase of type check has the job of visiting all items,
16 determining their type, and writing that type into the `tcx.tcache`
17 table. Despite its name, this table does not really operate as a
18 *cache*, at least not for the types of items defined within the
19 current crate: we assume that after the collect phase, the types of
20 all local items will be present in the table.
22 Unlike most of the types that are present in Rust, the types computed
23 for each item are in fact polytypes. In "layman's terms", this means
24 that they are generic types that may have type parameters (more
25 mathematically phrased, they are universally quantified over a set of
26 type parameters). Polytypes are represented by an instance of
27 `ty::ty_param_bounds_and_ty`. This combines the core type along with
28 a list of the bounds for each parameter. Type parameters themselves
29 are represented as `ty_param()` instances.
34 use metadata::csearch;
35 use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
36 use middle::ty::{ty_param_bounds_and_ty};
38 use middle::subst::Subst;
39 use middle::typeck::astconv::{AstConv, ty_of_arg};
40 use middle::typeck::astconv::{ast_ty_to_ty};
41 use middle::typeck::astconv;
42 use middle::typeck::rscope::*;
43 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
45 use util::ppaux::Repr;
49 use syntax::abi::AbiSet;
50 use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
53 use syntax::ast_util::{local_def, split_trait_methods};
54 use syntax::codemap::Span;
56 use syntax::parse::token::special_idents;
57 use syntax::parse::token;
58 use syntax::print::pprust::{path_to_str};
60 use syntax::opt_vec::OptVec;
62 struct CollectItemTypesVisitor {
66 impl visit::Visitor<()> for CollectItemTypesVisitor {
67 fn visit_item(&mut self, i: &ast::Item, _: ()) {
69 visit::walk_item(self, i, ());
71 fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
72 convert_foreign(self.ccx, i);
73 visit::walk_foreign_item(self, i, ());
77 pub fn collect_item_types(ccx: @CrateCtxt, krate: &ast::Crate) {
78 fn collect_intrinsic_type(ccx: &CrateCtxt,
79 lang_item: ast::DefId) {
80 let ty::ty_param_bounds_and_ty { ty: ty, .. } =
81 ccx.get_item_ty(lang_item);
82 let mut intrinsic_defs = ccx.tcx.intrinsic_defs.borrow_mut();
83 intrinsic_defs.get().insert(lang_item, ty);
86 match ccx.tcx.lang_items.ty_desc() {
87 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
89 match ccx.tcx.lang_items.opaque() {
90 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
93 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
94 visit::walk_crate(&mut visitor, krate, ());
98 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
101 impl ToTy for CrateCtxt {
102 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
103 ast_ty_to_ty(self, rs, ast_ty)
107 impl AstConv for CrateCtxt {
108 fn tcx(&self) -> ty::ctxt { self.tcx }
110 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
111 if id.krate != ast::LOCAL_CRATE {
112 return csearch::get_type(self.tcx, id)
115 match self.tcx.map.find(id.node) {
116 Some(ast_map::NodeItem(item)) => ty_of_item(self, item),
117 Some(ast_map::NodeForeignItem(foreign_item)) => {
118 let abis = self.tcx.map.get_foreign_abis(id.node);
119 ty_of_foreign_item(self, foreign_item, abis)
122 self.tcx.sess.bug(format!("unexpected sort of node \
123 in get_item_ty(): {:?}", x));
128 fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
129 get_trait_def(self, id)
132 fn ty_infer(&self, span: Span) -> ty::t {
133 self.tcx.sess.span_bug(span, "found `ty_infer` in unexpected place");
137 pub fn get_enum_variant_types(ccx: &CrateCtxt,
139 variants: &[ast::P<ast::Variant>],
140 generics: &ast::Generics) {
143 // Create a set of parameter types shared among all the variants.
144 for variant in variants.iter() {
145 // Nullary enum constructors get turned into constants; n-ary enum
146 // constructors get turned into functions.
147 let scope = variant.node.id;
148 let result_ty = match variant.node.kind {
149 ast::TupleVariantKind(ref args) if args.len() > 0 => {
150 let rs = ExplicitRscope;
151 let input_tys = args.map(|va| ccx.to_ty(&rs, va.ty));
152 ty::mk_ctor_fn(tcx, scope, input_tys, enum_ty)
155 ast::TupleVariantKind(_) => {
159 ast::StructVariantKind(struct_def) => {
160 let tpt = ty_param_bounds_and_ty {
161 generics: ty_generics(ccx, generics, 0),
165 convert_struct(ccx, struct_def, tpt, variant.node.id);
167 let input_tys = struct_def.fields.map(
168 |f| ty::node_id_to_type(ccx.tcx, f.node.id));
169 ty::mk_ctor_fn(tcx, scope, input_tys, enum_ty)
173 let tpt = ty_param_bounds_and_ty {
174 generics: ty_generics(ccx, generics, 0),
179 let mut tcache = tcx.tcache.borrow_mut();
180 tcache.get().insert(local_def(variant.node.id), tpt);
183 write_ty_to_tcx(tcx, variant.node.id, result_ty);
187 pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
189 match tcx.map.get(trait_id) {
190 ast_map::NodeItem(item) => {
192 ast::ItemTrait(ref generics, _, ref ms) => {
193 let trait_ty_generics = ty_generics(ccx, generics, 0);
195 // For each method, construct a suitable ty::Method and
196 // store it into the `tcx.methods` table:
198 let ty_method = @match m {
199 &ast::Required(ref m) => {
200 ty_method_of_trait_method(
201 ccx, trait_id, &trait_ty_generics,
202 &m.id, &m.ident, &m.explicit_self,
203 &m.generics, &m.purity, m.decl)
206 &ast::Provided(ref m) => {
207 ty_method_of_trait_method(
208 ccx, trait_id, &trait_ty_generics,
209 &m.id, &m.ident, &m.explicit_self,
210 &m.generics, &m.purity, m.decl)
214 if ty_method.explicit_self == ast::SelfStatic {
215 make_static_method_ty(ccx, trait_id, ty_method,
219 let mut methods = tcx.methods.borrow_mut();
220 methods.get().insert(ty_method.def_id, ty_method);
223 // Add an entry mapping
224 let method_def_ids = @ms.map(|m| {
226 &ast::Required(ref ty_method) => {
227 local_def(ty_method.id)
229 &ast::Provided(ref method) => {
235 let trait_def_id = local_def(trait_id);
236 let mut trait_method_def_ids = tcx.trait_method_def_ids
238 trait_method_def_ids.get().insert(trait_def_id,
241 _ => {} // Ignore things that aren't traits.
244 _ => { /* Ignore things that aren't traits */ }
247 fn make_static_method_ty(ccx: &CrateCtxt,
248 trait_id: ast::NodeId,
250 trait_ty_generics: &ty::Generics) {
253 // trait Trait<'a,'b,'c,a,b,c> {
254 // fn foo<'d,'e,'f,d,e,f>(...) -> Self;
257 // and we will create a function like
259 // fn foo<'a,'b,'c, // First the lifetime params from trait
260 // 'd,'e,'f, // Then lifetime params from `foo()`
261 // a,b,c, // Then type params from trait
262 // D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
263 // E,F,G // Then type params from `foo()`, offset by 1
266 // Note that `Self` is replaced with an explicit type
267 // parameter D that is sandwiched in between the trait params
268 // and the method params, and thus the indices of the method
269 // type parameters are offset by 1 (that is, the method
270 // parameters are mapped from d, e, f to E, F, and G). The
271 // choice of this ordering is somewhat arbitrary.
273 // Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
274 // This implies that the lifetime parameters that were inherited
275 // from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
276 // bound, since they appear in a trait bound.
278 // Also, this system is rather a hack that should be replaced
279 // with a more uniform treatment of Self (which is partly
282 // build up a subst that shifts all of the parameters over
283 // by one and substitute in a new type param for self
287 let dummy_defid = ast::DefId {krate: 0, node: 0};
289 // Represents [A',B',C']
290 let num_trait_bounds = trait_ty_generics.type_param_defs().len();
291 let non_shifted_trait_tps = vec::from_fn(num_trait_bounds, |i| {
292 ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
296 let self_param = ty::mk_param(tcx, num_trait_bounds,
299 // Represents [E',F',G']
300 let num_method_bounds = m.generics.type_param_defs().len();
301 let shifted_method_tps = vec::from_fn(num_method_bounds, |i| {
302 ty::mk_param(tcx, i + num_trait_bounds + 1,
303 m.generics.type_param_defs()[i].def_id)
306 // Convert the regions 'a, 'b, 'c defined on the trait into
307 // bound regions on the fn. Note that because these appear in the
308 // bound for `Self` they must be early bound.
309 let new_early_region_param_defs = trait_ty_generics.region_param_defs.clone();
311 trait_ty_generics.region_param_defs().iter().
313 map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.ident)).
316 // build up the substitution from
317 // 'a,'b,'c => 'a,'b,'c
321 let substs = substs {
322 regions: ty::NonerasedRegions(rps_from_trait),
323 self_ty: Some(self_param),
324 tps: non_shifted_trait_tps + shifted_method_tps
327 // create the type of `foo`, applying the substitution above
328 let ty = ty::subst(tcx,
330 ty::mk_bare_fn(tcx, m.fty.clone()));
332 // create the type parameter definitions for `foo`, applying
333 // the substitution to any traits that appear in their bounds.
335 // add in the type parameters from the trait
336 let mut new_type_param_defs = ~[];
337 let substd_type_param_defs =
338 trait_ty_generics.type_param_defs.subst(tcx, &substs);
339 new_type_param_defs.push_all(*substd_type_param_defs.borrow());
341 // add in the "self" type parameter
342 let self_trait_def = get_trait_def(ccx, local_def(trait_id));
343 let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
344 new_type_param_defs.push(ty::TypeParameterDef {
345 ident: special_idents::self_,
347 bounds: @ty::ParamBounds {
348 builtin_bounds: ty::EmptyBuiltinBounds(),
349 trait_bounds: ~[self_trait_ref]
354 // add in the type parameters from the method
355 let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
356 new_type_param_defs.push_all(*substd_type_param_defs.borrow());
358 debug!("static method {} type_param_defs={} ty={}, substs={}",
360 new_type_param_defs.repr(tcx),
364 let mut tcache = tcx.tcache.borrow_mut();
365 tcache.get().insert(m.def_id,
366 ty_param_bounds_and_ty {
367 generics: ty::Generics {
368 type_param_defs: Rc::new(new_type_param_defs),
369 region_param_defs: new_early_region_param_defs
375 fn ty_method_of_trait_method(this: &CrateCtxt,
376 trait_id: ast::NodeId,
377 trait_generics: &ty::Generics,
379 m_ident: &ast::Ident,
380 m_explicit_self: &ast::ExplicitSelf,
381 m_generics: &ast::Generics,
382 m_purity: &ast::Purity,
383 m_decl: &ast::FnDecl) -> ty::Method
385 let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
386 let fty = astconv::ty_of_method(this, *m_id, *m_purity, trait_self_ty,
387 *m_explicit_self, m_decl);
388 let num_trait_type_params = trait_generics.type_param_defs().len();
391 // FIXME(#5121) -- distinguish early vs late lifetime params
392 ty_generics(this, m_generics, num_trait_type_params),
394 m_explicit_self.node,
395 // assume public, because this is only invoked on trait methods
398 TraitContainer(local_def(trait_id)),
404 pub fn ensure_supertraits(ccx: &CrateCtxt,
407 ast_trait_refs: &[ast::TraitRef])
412 // Called only the first time trait_def_of_item is called.
413 // Supertraits are ensured at the same time.
415 let supertraits = tcx.supertraits.borrow();
416 assert!(!supertraits.get().contains_key(&local_def(id)));
419 let self_ty = ty::mk_self(ccx.tcx, local_def(id));
420 let mut ty_trait_refs: ~[@ty::TraitRef] = ~[];
421 let mut bounds = ty::EmptyBuiltinBounds();
422 for ast_trait_ref in ast_trait_refs.iter() {
423 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
424 // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
425 // builtin trait, so that the trait's node id appears in the tcx trait_ref
426 // map. This is only needed for metadata; see the similar fixme in encoder.rs.
427 let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
428 if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
430 // FIXME(#5527) Could have same trait multiple times
431 if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) {
432 // This means a trait inherited from the same supertrait more
434 tcx.sess.span_err(sp, "duplicate supertrait in trait declaration");
437 ty_trait_refs.push(trait_ref);
442 let mut supertraits = tcx.supertraits.borrow_mut();
443 supertraits.get().insert(local_def(id), @ty_trait_refs);
447 pub fn convert_field(ccx: &CrateCtxt,
448 struct_generics: &ty::Generics,
449 v: &ast::StructField) {
450 let tt = ccx.to_ty(&ExplicitRscope, v.node.ty);
451 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
452 /* add the field to the tcache */
453 let mut tcache = ccx.tcx.tcache.borrow_mut();
454 tcache.get().insert(local_def(v.node.id),
455 ty::ty_param_bounds_and_ty {
456 generics: struct_generics.clone(),
461 fn convert_methods(ccx: &CrateCtxt,
462 container: MethodContainer,
464 untransformed_rcvr_ty: ty::t,
465 rcvr_ty_generics: &ty::Generics,
466 rcvr_ast_generics: &ast::Generics,
467 rcvr_visibility: ast::Visibility)
471 let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
472 let m_ty_generics = ty_generics(ccx, &m.generics, num_rcvr_ty_params);
473 let mty = @ty_of_method(ccx,
476 untransformed_rcvr_ty,
479 let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
480 debug!("method {} (id {}) has type {}",
481 m.ident.repr(ccx.tcx),
485 let mut tcache = tcx.tcache.borrow_mut();
489 // n.b.: the type of a method is parameterized by both
490 // the parameters on the receiver and those on the method
492 ty_param_bounds_and_ty {
493 generics: ty::Generics {
494 type_param_defs: Rc::new(vec::append(
495 rcvr_ty_generics.type_param_defs().to_owned(),
496 m_ty_generics.type_param_defs())),
497 region_param_defs: rcvr_ty_generics.region_param_defs.clone(),
503 write_ty_to_tcx(tcx, m.id, fty);
505 let mut methods = tcx.methods.borrow_mut();
506 methods.get().insert(mty.def_id, mty);
509 fn ty_of_method(ccx: &CrateCtxt,
510 container: MethodContainer,
512 untransformed_rcvr_ty: ty::t,
513 rcvr_generics: &ast::Generics,
514 rcvr_visibility: ast::Visibility) -> ty::Method
516 let fty = astconv::ty_of_method(ccx, m.id, m.purity,
517 untransformed_rcvr_ty,
518 m.explicit_self, m.decl);
520 // if the method specifies a visibility, use that, otherwise
521 // inherit the visibility from the impl (so `foo` in `pub impl
522 // { fn foo(); }` is public, but private in `priv impl { fn
524 let method_vis = m.vis.inherit_from(rcvr_visibility);
526 let num_rcvr_type_params = rcvr_generics.ty_params.len();
529 // FIXME(#5121) -- distinguish early vs late lifetime params
530 ty_generics(ccx, &m.generics, num_rcvr_type_params),
532 m.explicit_self.node,
541 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
543 generics: &ast::Generics,
544 thing: &'static str) {
545 for ty_param in generics.ty_params.iter() {
546 if ty_param.bounds.len() > 0 {
547 ccx.tcx.sess.span_err(
549 format!("trait bounds are not allowed in {} definitions",
555 fn ensure_generics_abi(ccx: &CrateCtxt,
558 generics: &ast::Generics) {
559 if generics.ty_params.len() > 0 &&
560 !(abis.is_rust() || abis.is_intrinsic()) {
561 ccx.tcx.sess.span_err(span,
562 "foreign functions may not use type parameters");
566 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
568 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
570 // These don't define types.
571 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
572 ast::ItemEnum(ref enum_definition, ref generics) => {
573 ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
574 let tpt = ty_of_item(ccx, it);
575 write_ty_to_tcx(tcx, it.id, tpt.ty);
576 get_enum_variant_types(ccx,
578 enum_definition.variants,
581 ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
582 let i_ty_generics = ty_generics(ccx, generics, 0);
583 let selfty = ccx.to_ty(&ExplicitRscope, selfty);
584 write_ty_to_tcx(tcx, it.id, selfty);
587 let mut tcache = tcx.tcache.borrow_mut();
588 tcache.get().insert(local_def(it.id),
589 ty_param_bounds_and_ty {
590 generics: i_ty_generics.clone(),
594 // If there is a trait reference, treat the methods as always public.
595 // This is to work around some incorrect behavior in privacy checking:
596 // when the method belongs to a trait, it should acquire the privacy
597 // from the trait, not the impl. Forcing the visibility to be public
598 // makes things sorta work.
599 let parent_visibility = if opt_trait_ref.is_some() {
606 ImplContainer(local_def(it.id)),
613 for trait_ref in opt_trait_ref.iter() {
614 let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
616 // Prevent the builtin kind traits from being manually implemented.
617 if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
618 tcx.sess.span_err(it.span,
619 "cannot provide an explicit implementation \
620 for a builtin kind");
624 ast::ItemTrait(ref generics, _, ref trait_methods) => {
625 let trait_def = trait_def_of_item(ccx, it);
627 // Run convert_methods on the provided methods.
628 let (_, provided_methods) =
629 split_trait_methods(*trait_methods);
630 let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
632 TraitContainer(local_def(it.id)),
634 untransformed_rcvr_ty,
639 // We need to do this *after* converting methods, since
640 // convert_methods produces a tcache entry that is wrong for
641 // static trait methods. This is somewhat unfortunate.
642 ensure_trait_methods(ccx, it.id);
644 ast::ItemStruct(struct_def, ref generics) => {
645 ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
647 // Write the class type
648 let tpt = ty_of_item(ccx, it);
649 write_ty_to_tcx(tcx, it.id, tpt.ty);
652 let mut tcache = tcx.tcache.borrow_mut();
653 tcache.get().insert(local_def(it.id), tpt.clone());
656 convert_struct(ccx, struct_def, tpt, it.id);
658 ast::ItemTy(_, ref generics) => {
659 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
660 let tpt = ty_of_item(ccx, it);
661 write_ty_to_tcx(tcx, it.id, tpt.ty);
663 ast::ItemFn(_, _, abi, ref generics, _) => {
664 ensure_generics_abi(ccx, it.span, abi, generics);
665 let tpt = ty_of_item(ccx, it);
666 write_ty_to_tcx(tcx, it.id, tpt.ty);
669 // This call populates the type cache with the converted type
670 // of the item in passing. All we have to do here is to write
671 // it into the node type table.
672 let tpt = ty_of_item(ccx, it);
673 write_ty_to_tcx(tcx, it.id, tpt.ty);
678 pub fn convert_struct(ccx: &CrateCtxt,
679 struct_def: &ast::StructDef,
680 tpt: ty::ty_param_bounds_and_ty,
684 // Write the type of each of the members
685 for f in struct_def.fields.iter() {
686 convert_field(ccx, &tpt.generics, f);
688 let substs = mk_item_substs(ccx, &tpt.generics, None);
689 let selfty = ty::mk_struct(tcx, local_def(id), substs);
691 // If this struct is enum-like or tuple-like, create the type of its
693 match struct_def.ctor_id {
696 if struct_def.fields.len() == 0 {
698 write_ty_to_tcx(tcx, ctor_id, selfty);
701 let mut tcache = tcx.tcache.borrow_mut();
702 tcache.get().insert(local_def(ctor_id), tpt);
704 } else if struct_def.fields[0].node.kind == ast::UnnamedField {
707 let tcache = tcx.tcache.borrow();
708 struct_def.fields.map(
709 |field| tcache.get().get(
710 &local_def(field.node.id)).ty)
712 let ctor_fn_ty = ty::mk_ctor_fn(tcx, ctor_id, inputs, selfty);
713 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
715 let mut tcache = tcx.tcache.borrow_mut();
716 tcache.get().insert(local_def(ctor_id),
717 ty_param_bounds_and_ty {
718 generics: tpt.generics,
727 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
728 // As above, this call populates the type table with the converted
729 // type of the foreign item. We simply write it into the node type
732 // For reasons I cannot fully articulate, I do so hate the AST
733 // map, and I regard each time that I use it as a personal and
734 // moral failing, but at the moment it seems like the only
735 // convenient way to extract the ABI. - ndm
736 let abis = ccx.tcx.map.get_foreign_abis(i.id);
738 let tpt = ty_of_foreign_item(ccx, i, abis);
739 write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
741 let mut tcache = ccx.tcx.tcache.borrow_mut();
742 tcache.get().insert(local_def(i.id), tpt);
745 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
746 ast_trait_ref: &ast::TraitRef,
747 self_ty: ty::t) -> @ty::TraitRef
750 * Instantiates the path for the given trait reference, assuming that
751 * it's bound to a valid trait type. Returns the def_id for the defining
752 * trait. Fails if the type is a type other than a trait type.
755 // FIXME(#5121) -- distinguish early vs late lifetime params
756 let rscope = ExplicitRscope;
758 match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
759 ast::DefTrait(trait_did) => {
761 astconv::ast_path_to_trait_ref(
762 ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
764 let mut trait_refs = ccx.tcx.trait_refs.borrow_mut();
765 trait_refs.get().insert(ast_trait_ref.ref_id, trait_ref);
769 ccx.tcx.sess.span_fatal(
770 ast_trait_ref.path.span,
771 format!("`{}` is not a trait",
772 path_to_str(&ast_trait_ref.path)));
777 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
778 if trait_id.krate != ast::LOCAL_CRATE {
779 return ty::lookup_trait_def(ccx.tcx, trait_id)
782 match ccx.tcx.map.get(trait_id.node) {
783 ast_map::NodeItem(item) => trait_def_of_item(ccx, item),
784 _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
789 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
790 let def_id = local_def(it.id);
793 let trait_defs = tcx.trait_defs.borrow();
794 match trait_defs.get().find(&def_id) {
795 Some(&def) => return def,
801 ast::ItemTrait(ref generics, ref supertraits, _) => {
802 let self_ty = ty::mk_self(tcx, def_id);
803 let ty_generics = ty_generics(ccx, generics, 0);
804 let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
805 let bounds = ensure_supertraits(ccx, it.id, it.span, *supertraits);
806 let trait_ref = @ty::TraitRef {def_id: def_id,
808 let trait_def = @ty::TraitDef {generics: ty_generics,
810 trait_ref: trait_ref};
811 let mut trait_defs = tcx.trait_defs.borrow_mut();
812 trait_defs.get().insert(def_id, trait_def);
818 format!("trait_def_of_item invoked on {:?}", s));
823 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
824 -> ty::ty_param_bounds_and_ty {
825 let def_id = local_def(it.id);
828 let tcache = tcx.tcache.borrow();
829 match tcache.get().find(&def_id) {
830 Some(tpt) => return tpt.clone(),
835 ast::ItemStatic(t, _, _) => {
836 let typ = ccx.to_ty(&ExplicitRscope, t);
837 let tpt = no_params(typ);
839 let mut tcache = tcx.tcache.borrow_mut();
840 tcache.get().insert(local_def(it.id), tpt.clone());
843 ast::ItemFn(decl, purity, abi, ref generics, _) => {
844 let ty_generics = ty_generics(ccx, generics, 0);
845 let tofd = astconv::ty_of_bare_fn(ccx,
850 let tpt = ty_param_bounds_and_ty {
851 generics: ty::Generics {
852 type_param_defs: ty_generics.type_param_defs.clone(),
853 region_param_defs: Rc::new(~[]),
855 ty: ty::mk_bare_fn(ccx.tcx, tofd)
857 debug!("type of {} (id {}) is {}",
858 token::get_ident(it.ident),
860 ppaux::ty_to_str(tcx, tpt.ty));
862 let mut tcache = ccx.tcx.tcache.borrow_mut();
863 tcache.get().insert(local_def(it.id), tpt.clone());
866 ast::ItemTy(t, ref generics) => {
868 let mut tcache = tcx.tcache.borrow_mut();
869 match tcache.get().find(&local_def(it.id)) {
870 Some(tpt) => return tpt.clone(),
876 let ty = ccx.to_ty(&ExplicitRscope, t);
877 ty_param_bounds_and_ty {
878 generics: ty_generics(ccx, generics, 0),
883 let mut tcache = tcx.tcache.borrow_mut();
884 tcache.get().insert(local_def(it.id), tpt.clone());
887 ast::ItemEnum(_, ref generics) => {
888 // Create a new generic polytype.
889 let ty_generics = ty_generics(ccx, generics, 0);
890 let substs = mk_item_substs(ccx, &ty_generics, None);
891 let t = ty::mk_enum(tcx, local_def(it.id), substs);
892 let tpt = ty_param_bounds_and_ty {
893 generics: ty_generics,
897 let mut tcache = tcx.tcache.borrow_mut();
898 tcache.get().insert(local_def(it.id), tpt.clone());
901 ast::ItemTrait(..) => {
904 format!("invoked ty_of_item on trait"));
906 ast::ItemStruct(_, ref generics) => {
907 let ty_generics = ty_generics(ccx, generics, 0);
908 let substs = mk_item_substs(ccx, &ty_generics, None);
909 let t = ty::mk_struct(tcx, local_def(it.id), substs);
910 let tpt = ty_param_bounds_and_ty {
911 generics: ty_generics,
915 let mut tcache = tcx.tcache.borrow_mut();
916 tcache.get().insert(local_def(it.id), tpt.clone());
919 ast::ItemImpl(..) | ast::ItemMod(_) |
920 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
924 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
925 it: &ast::ForeignItem,
926 abis: AbiSet) -> ty::ty_param_bounds_and_ty
929 ast::ForeignItemFn(fn_decl, ref generics) => {
930 ty_of_foreign_fn_decl(ccx,
936 ast::ForeignItemStatic(t, _) => {
937 ty::ty_param_bounds_and_ty {
938 generics: ty::Generics {
939 type_param_defs: Rc::new(~[]),
940 region_param_defs: Rc::new(~[]),
942 ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
948 pub fn ty_generics(ccx: &CrateCtxt,
949 generics: &ast::Generics,
950 base_index: uint) -> ty::Generics {
951 return ty::Generics {
952 region_param_defs: Rc::new(generics.lifetimes.iter().map(|l| {
953 ty::RegionParameterDef { ident: l.ident,
954 def_id: local_def(l.id) }
956 type_param_defs: Rc::new(generics.ty_params.mapi_to_vec(|offset, param| {
957 let existing_def_opt = {
958 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
959 ty_param_defs.get().find(¶m.id).map(|def| *def)
961 match existing_def_opt {
964 let param_ty = ty::param_ty {idx: base_index + offset,
965 def_id: local_def(param.id)};
966 let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
967 let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
968 let def = ty::TypeParameterDef {
970 def_id: local_def(param.id),
974 debug!("def for param: {}", def.repr(ccx.tcx));
976 let mut ty_param_defs = ccx.tcx
979 ty_param_defs.get().insert(param.id, def);
988 param_ty: ty::param_ty,
989 ast_bounds: &OptVec<ast::TyParamBound>) -> ty::ParamBounds
992 * Translate the AST's notion of ty param bounds (which are an
993 * enum consisting of a newtyped Ty or a region) to ty's
994 * notion of ty param bounds, which can either be user-defined
995 * traits, or one of the two built-in traits (formerly known
996 * as kinds): Freeze and Send.
999 let mut param_bounds = ty::ParamBounds {
1000 builtin_bounds: ty::EmptyBuiltinBounds(),
1003 for ast_bound in ast_bounds.iter() {
1005 TraitTyParamBound(ref b) => {
1006 let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
1007 let trait_ref = instantiate_trait_ref(ccx, b, ty);
1008 if !ty::try_add_builtin_trait(
1009 ccx.tcx, trait_ref.def_id,
1010 &mut param_bounds.builtin_bounds)
1012 // Must be a user-defined trait
1013 param_bounds.trait_bounds.push(trait_ref);
1017 RegionTyParamBound => {
1018 param_bounds.builtin_bounds.add(ty::BoundStatic);
1027 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1030 ast_generics: &ast::Generics,
1032 -> ty::ty_param_bounds_and_ty {
1033 let ty_generics = ty_generics(ccx, ast_generics, 0);
1034 let rb = BindingRscope::new(def_id.node);
1035 let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, a, None) );
1036 let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
1038 let t_fn = ty::mk_bare_fn(
1042 purity: ast::UnsafeFn,
1043 sig: ty::FnSig {binder_id: def_id.node,
1046 variadic: decl.variadic}
1048 let tpt = ty_param_bounds_and_ty {
1049 generics: ty_generics,
1053 let mut tcache = ccx.tcx.tcache.borrow_mut();
1054 tcache.get().insert(def_id, tpt.clone());
1058 pub fn mk_item_substs(ccx: &CrateCtxt,
1059 ty_generics: &ty::Generics,
1060 self_ty: Option<ty::t>) -> ty::substs
1062 let params: ~[ty::t] =
1063 ty_generics.type_param_defs().iter().enumerate().map(
1064 |(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
1066 let regions: OptVec<ty::Region> =
1067 ty_generics.region_param_defs().iter().enumerate().map(
1068 |(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.ident)).collect();
1070 substs {regions: ty::NonerasedRegions(regions),