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::Polytype`. This combines the core type along with a list of the
28 bounds for each parameter. Type parameters themselves are represented
29 as `ty_param()` instances.
34 use metadata::csearch;
36 use middle::lang_items::SizedTraitLangItem;
37 use middle::resolve_lifetime;
39 use middle::subst::{Substs};
40 use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
41 use middle::ty::{Polytype};
43 use middle::typeck::astconv::{AstConv, ty_of_arg};
44 use middle::typeck::astconv::{ast_ty_to_ty};
45 use middle::typeck::astconv;
46 use middle::typeck::rscope::*;
47 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
49 use util::ppaux::Repr;
51 use std::collections::{HashMap, HashSet};
56 use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound};
57 use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
60 use syntax::ast_util::{local_def, split_trait_methods};
61 use syntax::codemap::Span;
63 use syntax::owned_slice::OwnedSlice;
64 use syntax::parse::token::special_idents;
65 use syntax::parse::token;
66 use syntax::print::pprust::{path_to_str};
69 struct CollectItemTypesVisitor<'a> {
70 ccx: &'a CrateCtxt<'a>
73 impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
74 fn visit_item(&mut self, i: &ast::Item, _: ()) {
76 visit::walk_item(self, i, ());
78 fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
79 convert_foreign(self.ccx, i);
80 visit::walk_foreign_item(self, i, ());
84 pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
85 fn collect_intrinsic_type(ccx: &CrateCtxt,
86 lang_item: ast::DefId) {
87 let ty::Polytype { ty: ty, .. } =
88 ccx.get_item_ty(lang_item);
89 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
92 match ccx.tcx.lang_items.ty_desc() {
93 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
95 match ccx.tcx.lang_items.opaque() {
96 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
99 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
100 visit::walk_crate(&mut visitor, krate, ());
104 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
107 impl<'a> ToTy for CrateCtxt<'a> {
108 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
109 ast_ty_to_ty(self, rs, ast_ty)
113 impl<'a> AstConv for CrateCtxt<'a> {
114 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
116 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
117 if id.krate != ast::LOCAL_CRATE {
118 return csearch::get_type(self.tcx, id)
121 match self.tcx.map.find(id.node) {
122 Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
123 Some(ast_map::NodeForeignItem(foreign_item)) => {
124 let abi = self.tcx.map.get_foreign_abi(id.node);
125 ty_of_foreign_item(self, &*foreign_item, abi)
128 self.tcx.sess.bug(format!("unexpected sort of node \
129 in get_item_ty(): {:?}",
135 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
136 get_trait_def(self, id)
139 fn ty_infer(&self, span: Span) -> ty::t {
140 self.tcx.sess.span_err(span, "the type placeholder `_` is not \
141 allowed within types on item \
147 pub fn get_enum_variant_types(ccx: &CrateCtxt,
149 variants: &[ast::P<ast::Variant>],
150 generics: &ast::Generics) {
153 // Create a set of parameter types shared among all the variants.
154 for variant in variants.iter() {
155 // Nullary enum constructors get turned into constants; n-ary enum
156 // constructors get turned into functions.
157 let scope = variant.node.id;
158 let result_ty = match variant.node.kind {
159 ast::TupleVariantKind(ref args) if args.len() > 0 => {
160 let rs = ExplicitRscope;
161 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
162 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
165 ast::TupleVariantKind(_) => {
169 ast::StructVariantKind(struct_def) => {
171 generics: ty_generics_for_type(ccx, generics),
175 convert_struct(ccx, &*struct_def, pty, variant.node.id);
177 let input_tys: Vec<_> = struct_def.fields.iter().map(
178 |f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
179 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
184 generics: ty_generics_for_type(ccx, generics),
188 tcx.tcache.borrow_mut().insert(local_def(variant.node.id), pty);
190 write_ty_to_tcx(tcx, variant.node.id, result_ty);
194 pub fn ensure_trait_methods(ccx: &CrateCtxt,
195 trait_id: ast::NodeId,
196 trait_def: &ty::TraitDef) {
198 match tcx.map.get(trait_id) {
199 ast_map::NodeItem(item) => {
201 ast::ItemTrait(_, _, _, ref ms) => {
202 // For each method, construct a suitable ty::Method and
203 // store it into the `tcx.methods` table:
205 let ty_method = Rc::new(match m {
206 &ast::Required(ref m) => {
207 ty_method_of_trait_method(
208 ccx, trait_id, &trait_def.generics,
209 &m.id, &m.ident, &m.explicit_self,
210 &m.generics, &m.fn_style, &*m.decl)
213 &ast::Provided(ref m) => {
214 ty_method_of_trait_method(
215 ccx, trait_id, &trait_def.generics,
216 &m.id, &m.ident, &m.explicit_self,
217 &m.generics, &m.fn_style, &*m.decl)
221 if ty_method.explicit_self == ast::SelfStatic {
222 make_static_method_ty(ccx, &*ty_method);
225 tcx.methods.borrow_mut().insert(ty_method.def_id,
229 // Add an entry mapping
230 let method_def_ids = Rc::new(ms.iter().map(|m| {
232 &ast::Required(ref ty_method) => {
233 local_def(ty_method.id)
235 &ast::Provided(ref method) => {
241 let trait_def_id = local_def(trait_id);
242 tcx.trait_method_def_ids.borrow_mut()
243 .insert(trait_def_id, method_def_ids);
245 _ => {} // Ignore things that aren't traits.
248 _ => { /* Ignore things that aren't traits */ }
251 fn make_static_method_ty(ccx: &CrateCtxt, m: &ty::Method) {
252 ccx.tcx.tcache.borrow_mut().insert(
255 generics: m.generics.clone(),
256 ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
259 fn ty_method_of_trait_method(this: &CrateCtxt,
260 trait_id: ast::NodeId,
261 trait_generics: &ty::Generics,
263 m_ident: &ast::Ident,
264 m_explicit_self: &ast::ExplicitSelf,
265 m_generics: &ast::Generics,
266 m_fn_style: &ast::FnStyle,
267 m_decl: &ast::FnDecl) -> ty::Method
269 let trait_self_ty = ty::mk_self_type(this.tcx, local_def(trait_id));
270 let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty,
271 *m_explicit_self, m_decl);
273 ty_generics_for_fn_or_method(this,
275 (*trait_generics).clone());
280 m_explicit_self.node,
281 // assume public, because this is only invoked on trait methods
284 TraitContainer(local_def(trait_id)),
290 pub fn convert_field(ccx: &CrateCtxt,
291 struct_generics: &ty::Generics,
292 v: &ast::StructField,
293 origin: ast::DefId) -> ty::field_ty {
294 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
295 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
296 /* add the field to the tcache */
297 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
299 generics: struct_generics.clone(),
304 ast::NamedField(ident, visibility) => {
307 id: local_def(v.node.id),
312 ast::UnnamedField(visibility) => {
314 name: special_idents::unnamed_field.name,
315 id: local_def(v.node.id),
323 fn convert_methods(ccx: &CrateCtxt,
324 container: MethodContainer,
325 ms: &[Gc<ast::Method>],
326 untransformed_rcvr_ty: ty::t,
327 rcvr_ty_generics: &ty::Generics,
328 rcvr_visibility: ast::Visibility)
331 let mut seen_methods = HashSet::new();
333 if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
334 tcx.sess.span_err(m.span, "duplicate method in trait impl");
337 let mty = Rc::new(ty_of_method(ccx,
340 untransformed_rcvr_ty,
343 let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
344 debug!("method {} (id {}) has type {}",
345 m.ident.repr(ccx.tcx),
348 tcx.tcache.borrow_mut().insert(
351 generics: mty.generics.clone(),
355 write_ty_to_tcx(tcx, m.id, fty);
357 tcx.methods.borrow_mut().insert(mty.def_id, mty);
360 fn ty_of_method(ccx: &CrateCtxt,
361 container: MethodContainer,
363 untransformed_rcvr_ty: ty::t,
364 rcvr_ty_generics: &ty::Generics,
365 rcvr_visibility: ast::Visibility)
368 let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
369 untransformed_rcvr_ty,
370 m.explicit_self, &*m.decl);
372 // if the method specifies a visibility, use that, otherwise
373 // inherit the visibility from the impl (so `foo` in `pub impl
374 // { fn foo(); }` is public, but private in `priv impl { fn
376 let method_vis = m.vis.inherit_from(rcvr_visibility);
379 ty_generics_for_fn_or_method(ccx, &m.generics,
380 (*rcvr_ty_generics).clone());
381 ty::Method::new(m.ident,
384 m.explicit_self.node,
392 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
394 generics: &ast::Generics,
395 thing: &'static str) {
396 for ty_param in generics.ty_params.iter() {
397 if ty_param.bounds.len() > 0 {
398 ccx.tcx.sess.span_err(
400 format!("trait bounds are not allowed in {} definitions",
406 fn ensure_generics_abi(ccx: &CrateCtxt,
409 generics: &ast::Generics) {
410 if generics.ty_params.len() > 0 &&
411 !(abi == abi::Rust || abi == abi::RustIntrinsic) {
412 ccx.tcx.sess.span_err(span,
413 "foreign functions may not use type parameters");
417 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
419 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
421 // These don't define types.
422 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
423 ast::ItemEnum(ref enum_definition, ref generics) => {
424 ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
425 let pty = ty_of_item(ccx, it);
426 write_ty_to_tcx(tcx, it.id, pty.ty);
427 get_enum_variant_types(ccx,
429 enum_definition.variants.as_slice(),
432 ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
433 let ty_generics = ty_generics_for_type(ccx, generics);
434 let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
435 write_ty_to_tcx(tcx, it.id, selfty);
437 tcx.tcache.borrow_mut().insert(local_def(it.id),
439 generics: ty_generics.clone(),
442 // If there is a trait reference, treat the methods as always public.
443 // This is to work around some incorrect behavior in privacy checking:
444 // when the method belongs to a trait, it should acquire the privacy
445 // from the trait, not the impl. Forcing the visibility to be public
446 // makes things sorta work.
447 let parent_visibility = if opt_trait_ref.is_some() {
454 ImplContainer(local_def(it.id)),
460 for trait_ref in opt_trait_ref.iter() {
461 instantiate_trait_ref(ccx, trait_ref, selfty);
464 ast::ItemTrait(_, _, _, ref trait_methods) => {
465 let trait_def = trait_def_of_item(ccx, it);
467 // Run convert_methods on the provided methods.
468 let (_, provided_methods) =
469 split_trait_methods(trait_methods.as_slice());
470 let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id));
472 TraitContainer(local_def(it.id)),
473 provided_methods.as_slice(),
474 untransformed_rcvr_ty,
478 // We need to do this *after* converting methods, since
479 // convert_methods produces a tcache entry that is wrong for
480 // static trait methods. This is somewhat unfortunate.
481 ensure_trait_methods(ccx, it.id, &*trait_def);
483 ast::ItemStruct(struct_def, ref generics) => {
484 ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
486 // Write the class type.
487 let pty = ty_of_item(ccx, it);
488 write_ty_to_tcx(tcx, it.id, pty.ty);
490 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
492 // Write the super-struct type, if it exists.
493 match struct_def.super_struct {
495 let supserty = ccx.to_ty(&ExplicitRscope, &*ty);
496 write_ty_to_tcx(tcx, it.id, supserty);
501 convert_struct(ccx, &*struct_def, pty, it.id);
503 ast::ItemTy(_, ref generics) => {
504 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
505 let pty = ty_of_item(ccx, it);
506 write_ty_to_tcx(tcx, it.id, pty.ty);
508 ast::ItemFn(_, _, abi, ref generics, _) => {
509 ensure_generics_abi(ccx, it.span, abi, generics);
510 let pty = ty_of_item(ccx, it);
511 write_ty_to_tcx(tcx, it.id, pty.ty);
514 // This call populates the type cache with the converted type
515 // of the item in passing. All we have to do here is to write
516 // it into the node type table.
517 let pty = ty_of_item(ccx, it);
518 write_ty_to_tcx(tcx, it.id, pty.ty);
523 pub fn convert_struct(ccx: &CrateCtxt,
524 struct_def: &ast::StructDef,
529 // Write the type of each of the members and check for duplicate fields.
530 let mut seen_fields: HashMap<ast::Name, Span> = HashMap::new();
531 let field_tys = struct_def.fields.iter().map(|f| {
532 let result = convert_field(ccx, &pty.generics, f, local_def(id));
534 if result.name != special_idents::unnamed_field.name {
535 let dup = match seen_fields.find(&result.name) {
539 format!("field `{}` is already declared",
540 token::get_name(result.name)).as_slice());
541 tcx.sess.span_note(*prev_span,
542 "previously declared here");
547 // FIXME(#6393) this whole dup thing is just to satisfy
548 // the borrow checker :-(
550 seen_fields.insert(result.name, f.span);
557 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
559 let super_struct = match struct_def.super_struct {
560 Some(t) => match t.node {
561 ast::TyPath(_, _, path_id) => {
562 let def_map = tcx.def_map.borrow();
563 match def_map.find(&path_id) {
564 Some(&def::DefStruct(def_id)) => {
565 // FIXME(#12511) Check for cycles in the inheritance hierarchy.
566 // Check super-struct is virtual.
567 match tcx.map.find(def_id.node) {
568 Some(ast_map::NodeItem(i)) => match i.node {
569 ast::ItemStruct(struct_def, _) => {
570 if !struct_def.is_virtual {
571 tcx.sess.span_err(t.span,
572 "struct inheritance is only \
573 allowed from virtual structs");
590 tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);
592 let substs = mk_item_substs(ccx, &pty.generics);
593 let selfty = ty::mk_struct(tcx, local_def(id), substs);
595 // If this struct is enum-like or tuple-like, create the type of its
597 match struct_def.ctor_id {
600 if struct_def.fields.len() == 0 {
602 write_ty_to_tcx(tcx, ctor_id, selfty);
604 tcx.tcache.borrow_mut().insert(local_def(ctor_id), pty);
605 } else if struct_def.fields.get(0).node.kind.is_unnamed() {
607 let inputs: Vec<_> = struct_def.fields.iter().map(
608 |field| tcx.tcache.borrow().get(
609 &local_def(field.node.id)).ty).collect();
610 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
614 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
615 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
617 generics: pty.generics,
625 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
626 // As above, this call populates the type table with the converted
627 // type of the foreign item. We simply write it into the node type
630 // For reasons I cannot fully articulate, I do so hate the AST
631 // map, and I regard each time that I use it as a personal and
632 // moral failing, but at the moment it seems like the only
633 // convenient way to extract the ABI. - ndm
634 let abi = ccx.tcx.map.get_foreign_abi(i.id);
636 let pty = ty_of_foreign_item(ccx, i, abi);
637 write_ty_to_tcx(ccx.tcx, i.id, pty.ty);
639 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
642 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
643 ast_trait_ref: &ast::TraitRef,
644 self_ty: ty::t) -> Rc<ty::TraitRef> {
646 * Instantiates the path for the given trait reference, assuming that
647 * it's bound to a valid trait type. Returns the def_id for the defining
648 * trait. Fails if the type is a type other than a trait type.
651 // FIXME(#5121) -- distinguish early vs late lifetime params
652 let rscope = ExplicitRscope;
654 match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
655 def::DefTrait(trait_did) => {
657 astconv::ast_path_to_trait_ref(
658 ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
660 ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
665 ccx.tcx.sess.span_fatal(
666 ast_trait_ref.path.span,
667 format!("`{}` is not a trait",
668 path_to_str(&ast_trait_ref.path)).as_slice());
673 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
674 if trait_id.krate != ast::LOCAL_CRATE {
675 return ty::lookup_trait_def(ccx.tcx, trait_id)
678 match ccx.tcx.map.get(trait_id.node) {
679 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
681 ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
682 trait_id.node).as_slice())
687 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
688 let def_id = local_def(it.id);
690 match tcx.trait_defs.borrow().find(&def_id) {
691 Some(def) => return def.clone(),
695 let (generics, sized, supertraits) = match it.node {
696 ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
697 (generics, sized, supertraits)
702 format!("trait_def_of_item invoked on {:?}", s).as_slice());
706 let substs = mk_trait_substs(ccx, it.id, generics);
708 let ty_generics = ty_generics_for_trait(ccx,
714 ensure_supertraits(ccx, it.id, it.span, supertraits, sized);
716 let substs = mk_item_substs(ccx, &ty_generics);
717 let trait_def = Rc::new(ty::TraitDef {
718 generics: ty_generics,
719 bounds: builtin_bounds,
720 trait_ref: Rc::new(ty::TraitRef {
725 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
729 fn mk_trait_substs(ccx: &CrateCtxt,
730 trait_id: ast::NodeId,
731 generics: &ast::Generics)
734 // Creates a no-op substitution for the trait's type parameters.
739 .map(|(i, def)| ty::ReEarlyBound(def.id,
748 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
749 i, local_def(def.id)))
753 ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
755 subst::Substs::new_trait(types, regions, self_ty)
758 fn ensure_supertraits(ccx: &CrateCtxt,
761 ast_trait_refs: &Vec<ast::TraitRef>,
767 // Called only the first time trait_def_of_item is called.
768 // Supertraits are ensured at the same time.
769 assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
771 let self_ty = ty::mk_self_type(ccx.tcx, local_def(id));
772 let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
773 let mut bounds = ty::empty_builtin_bounds();
774 for ast_trait_ref in ast_trait_refs.iter() {
775 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
777 // FIXME(#8559): Need to instantiate the trait_ref whether
778 // or not it's a builtin trait, so that the trait's node
779 // id appears in the tcx trait_ref map. This is only
780 // needed for metadata; see the similar fixme in
783 let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
784 if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
786 // FIXME(#5527) Could have same trait multiple times
787 if ty_trait_refs.iter().any(
788 |other_trait| other_trait.def_id == trait_ref.def_id)
790 // This means a trait inherited from the same
791 // supertrait more than once.
792 tcx.sess.span_err(sp, "duplicate supertrait in \
796 ty_trait_refs.push(trait_ref);
801 if sized == ast::StaticSize {
802 match tcx.lang_items.require(SizedTraitLangItem) {
804 ty::try_add_builtin_trait(tcx, def_id, &mut bounds);
806 Err(s) => tcx.sess.err(s.as_slice()),
810 tcx.supertraits.borrow_mut().insert(local_def(id),
811 Rc::new(ty_trait_refs));
816 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
818 let def_id = local_def(it.id);
820 match tcx.tcache.borrow().find(&def_id) {
821 Some(pty) => return pty.clone(),
825 ast::ItemStatic(t, _, _) => {
826 let typ = ccx.to_ty(&ExplicitRscope, &*t);
827 let pty = no_params(typ);
829 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
832 ast::ItemFn(decl, fn_style, abi, ref generics, _) => {
833 let ty_generics = ty_generics_for_fn_or_method(ccx, generics,
834 ty::Generics::empty());
835 let tofd = astconv::ty_of_bare_fn(ccx,
841 generics: ty_generics,
842 ty: ty::mk_bare_fn(ccx.tcx, tofd)
844 debug!("type of {} (id {}) is {}",
845 token::get_ident(it.ident),
847 ppaux::ty_to_str(tcx, pty.ty));
849 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
852 ast::ItemTy(t, ref generics) => {
853 match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
854 Some(pty) => return pty.clone(),
859 let ty = ccx.to_ty(&ExplicitRscope, &*t);
861 generics: ty_generics_for_type(ccx, generics),
866 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
869 ast::ItemEnum(_, ref generics) => {
870 // Create a new generic polytype.
871 let ty_generics = ty_generics_for_type(ccx, generics);
872 let substs = mk_item_substs(ccx, &ty_generics);
873 let t = ty::mk_enum(tcx, local_def(it.id), substs);
875 generics: ty_generics,
879 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
882 ast::ItemTrait(..) => {
883 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
885 ast::ItemStruct(_, ref generics) => {
886 let ty_generics = ty_generics_for_type(ccx, generics);
887 let substs = mk_item_substs(ccx, &ty_generics);
888 let t = ty::mk_struct(tcx, local_def(it.id), substs);
890 generics: ty_generics,
894 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
897 ast::ItemImpl(..) | ast::ItemMod(_) |
898 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
902 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
903 it: &ast::ForeignItem,
904 abi: abi::Abi) -> ty::Polytype
907 ast::ForeignItemFn(fn_decl, ref generics) => {
908 ty_of_foreign_fn_decl(ccx,
914 ast::ForeignItemStatic(t, _) => {
916 generics: ty::Generics::empty(),
917 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &*t)
923 fn ty_generics_for_type(ccx: &CrateCtxt,
924 generics: &ast::Generics)
927 ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
928 &generics.ty_params, ty::Generics::empty())
931 fn ty_generics_for_trait(ccx: &CrateCtxt,
932 trait_id: ast::NodeId,
933 substs: &subst::Substs,
934 generics: &ast::Generics)
937 let mut generics = ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
938 &generics.ty_params, ty::Generics::empty());
940 // Something of a hack: use the node id for the trait, also as
941 // the node id for the Self type parameter.
942 let param_id = trait_id;
945 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
946 substs: (*substs).clone() });
948 let def = ty::TypeParameterDef {
949 space: subst::SelfSpace,
951 ident: special_idents::type_self,
952 def_id: local_def(param_id),
953 bounds: Rc::new(ty::ParamBounds {
954 builtin_bounds: ty::empty_builtin_bounds(),
955 trait_bounds: vec!(self_trait_ref),
960 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
962 generics.types.push(subst::SelfSpace, def);
967 fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
968 generics: &ast::Generics,
969 base_generics: ty::Generics)
972 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
973 ty_generics(ccx, subst::FnSpace, &early_lifetimes,
974 &generics.ty_params, base_generics)
977 fn ty_generics(ccx: &CrateCtxt,
978 space: subst::ParamSpace,
979 lifetimes: &Vec<ast::Lifetime>,
980 types: &OwnedSlice<ast::TyParam>,
981 base_generics: ty::Generics)
984 let mut result = base_generics;
986 for (i, l) in lifetimes.iter().enumerate() {
987 result.regions.push(space,
988 ty::RegionParameterDef { name: l.name,
991 def_id: local_def(l.id) });
994 for (i, param) in types.iter().enumerate() {
995 let def = get_or_create_type_parameter_def(ccx, space, param, i);
996 debug!("def for param: {}", def.repr(ccx.tcx));
997 result.types.push(space, def);
1002 fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
1003 space: subst::ParamSpace,
1004 param: &ast::TyParam,
1006 -> ty::TypeParameterDef
1008 match ccx.tcx.ty_param_defs.borrow().find(¶m.id) {
1009 Some(d) => { return (*d).clone(); }
1013 let param_ty = ty::ParamTy {space: space,
1015 def_id: local_def(param.id)};
1016 let bounds = Rc::new(compute_bounds(ccx,
1022 let default = param.default.map(|path| {
1023 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
1024 let cur_idx = param_ty.idx;
1026 ty::walk_ty(ty, |t| {
1027 match ty::get(t).sty {
1028 ty::ty_param(p) => if p.idx > cur_idx {
1029 ccx.tcx.sess.span_err(
1031 "type parameters with a default cannot use \
1032 forward declared identifiers")
1041 let def = ty::TypeParameterDef {
1045 def_id: local_def(param.id),
1050 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1057 param_ty: ty::ParamTy,
1058 ast_bounds: &OwnedSlice<ast::TyParamBound>,
1061 span: Span) -> ty::ParamBounds
1064 * Translate the AST's notion of ty param bounds (which are an
1065 * enum consisting of a newtyped Ty or a region) to ty's
1066 * notion of ty param bounds, which can either be user-defined
1067 * traits, or the built-in trait (formerly known as kind): Send.
1070 let mut param_bounds = ty::ParamBounds {
1071 builtin_bounds: ty::empty_builtin_bounds(),
1072 trait_bounds: Vec::new()
1074 for ast_bound in ast_bounds.iter() {
1076 TraitTyParamBound(ref b) => {
1077 let ty = ty::mk_param(ccx.tcx, param_ty.space,
1078 param_ty.idx, param_ty.def_id);
1079 let trait_ref = instantiate_trait_ref(ccx, b, ty);
1080 if !ty::try_add_builtin_trait(
1081 ccx.tcx, trait_ref.def_id,
1082 &mut param_bounds.builtin_bounds) {
1083 // Must be a user-defined trait
1084 param_bounds.trait_bounds.push(trait_ref);
1088 StaticRegionTyParamBound => {
1089 param_bounds.builtin_bounds.add(ty::BoundStatic);
1092 UnboxedFnTyParamBound(ref unboxed_function) => {
1093 let rscope = ExplicitRscope;
1094 let self_ty = ty::mk_param(ccx.tcx,
1099 astconv::trait_ref_for_unboxed_function(ccx,
1103 param_bounds.trait_bounds.push(Rc::new(trait_ref));
1106 OtherRegionTyParamBound(span) => {
1107 if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
1108 ccx.tcx.sess.span_err(
1110 "only the 'static lifetime is accepted here.");
1116 if sized == ast::StaticSize {
1117 match ccx.tcx.lang_items.require(SizedTraitLangItem) {
1118 Ok(def_id) => { ty::try_add_builtin_trait(ccx.tcx,
1120 &mut param_bounds.builtin_bounds); },
1121 // Fixme(13367) after `type` makes it into the snapshot, we can check this properly
1122 Err(_s) => {}, //ccx.tcx.sess.err(s),
1126 check_bounds_compatible(ccx.tcx, ¶m_bounds, ident, span);
1131 fn check_bounds_compatible(tcx: &ty::ctxt,
1132 param_bounds: &ty::ParamBounds,
1135 // Currently the only bound which is incompatible with other bounds is
1137 if !param_bounds.builtin_bounds.contains_elem(ty::BoundSized) {
1138 ty::each_bound_trait_and_supertraits(tcx,
1139 param_bounds.trait_bounds.as_slice(),
1141 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
1142 if trait_def.bounds.contains_elem(ty::BoundSized) {
1143 tcx.sess.span_err(span,
1144 format!("incompatible bounds on type parameter {}, \
1145 bound {} does not allow unsized type",
1146 token::get_ident(ident),
1147 ppaux::trait_ref_to_str(tcx,
1148 &*trait_ref)).as_slice());
1156 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1159 ast_generics: &ast::Generics,
1163 for i in decl.inputs.iter() {
1164 match (*i).pat.node {
1165 ast::PatIdent(_, _, _) => (),
1167 _ => ccx.tcx.sess.span_err((*i).pat.span,
1168 "patterns aren't allowed in foreign function declarations")
1172 let ty_generics_for_fn_or_method =
1173 ty_generics_for_fn_or_method(ccx, ast_generics,
1174 ty::Generics::empty());
1175 let rb = BindingRscope::new(def_id.node);
1176 let input_tys = decl.inputs
1178 .map(|a| ty_of_arg(ccx, &rb, a, None))
1181 let output_ty = ast_ty_to_ty(ccx, &rb, &*decl.output);
1183 let t_fn = ty::mk_bare_fn(
1187 fn_style: ast::UnsafeFn,
1188 sig: ty::FnSig {binder_id: def_id.node,
1191 variadic: decl.variadic}
1193 let pty = Polytype {
1194 generics: ty_generics_for_fn_or_method,
1198 ccx.tcx.tcache.borrow_mut().insert(def_id, pty.clone());
1202 pub fn mk_item_substs(ccx: &CrateCtxt,
1203 ty_generics: &ty::Generics)
1207 ty_generics.types.map(
1208 |def| ty::mk_param_from_def(ccx.tcx, def));
1211 ty_generics.regions.map(
1212 |def| ty::ReEarlyBound(def.def_id.node, def.space,
1213 def.index, def.name));
1215 subst::Substs::new(types, regions)