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). TypeSchemes are represented by an instance of
27 `ty::TypeScheme`. 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.
32 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
33 use metadata::csearch;
34 use middle::lang_items::SizedTraitLangItem;
36 use middle::resolve_lifetime;
38 use middle::subst::{Substs};
39 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
40 use middle::ty::{self, RegionEscape, Ty, TypeScheme};
41 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
45 use util::nodemap::{FnvHashMap, FnvHashSet};
47 use util::ppaux::{Repr,UserString};
55 use syntax::ast_util::{local_def, PostExpansionMethod};
56 use syntax::codemap::Span;
57 use syntax::parse::token::{special_idents};
58 use syntax::parse::token;
62 ///////////////////////////////////////////////////////////////////////////
65 pub fn collect_item_types(tcx: &ty::ctxt) {
66 let ccx = &CollectCtxt { tcx: tcx };
68 match ccx.tcx.lang_items.ty_desc() {
69 Some(id) => { collect_intrinsic_type(ccx, id); }
72 match ccx.tcx.lang_items.opaque() {
73 Some(id) => { collect_intrinsic_type(ccx, id); }
77 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
78 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
80 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
81 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
84 ///////////////////////////////////////////////////////////////////////////
86 struct CollectCtxt<'a,'tcx:'a> {
87 tcx: &'a ty::ctxt<'tcx>,
90 ///////////////////////////////////////////////////////////////////////////
91 // Zeroth phase: collect types of intrinsics
93 fn collect_intrinsic_type(ccx: &CollectCtxt,
94 lang_item: ast::DefId) {
95 let ty::TypeScheme { ty, .. } =
96 ccx.get_item_type_scheme(lang_item);
97 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
100 ///////////////////////////////////////////////////////////////////////////
101 // First phase: just collect *trait definitions* -- basically, the set
102 // of type parameters and supertraits. This is information we need to
103 // know later when parsing field defs.
105 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
106 ccx: &'a CollectCtxt<'a, 'tcx>
109 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
110 fn visit_item(&mut self, i: &ast::Item) {
112 ast::ItemTrait(..) => {
113 // computing the trait def also fills in the table
114 let _ = trait_def_of_item(self.ccx, i);
119 visit::walk_item(self, i);
123 ///////////////////////////////////////////////////////////////////////////
124 // Second phase: collection proper.
126 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
127 ccx: &'a CollectCtxt<'a, 'tcx>
130 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
131 fn visit_item(&mut self, i: &ast::Item) {
132 convert(self.ccx, i);
133 visit::walk_item(self, i);
135 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
136 convert_foreign(self.ccx, i);
137 visit::walk_foreign_item(self, i);
141 ///////////////////////////////////////////////////////////////////////////
142 // Utility types and common code for the above passes.
144 pub trait ToTy<'tcx> {
145 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
148 impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
149 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
150 ast_ty_to_ty(self, rs, ast_ty)
154 impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
155 fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
157 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
158 if id.krate != ast::LOCAL_CRATE {
159 return csearch::get_type(self.tcx, id)
162 match self.tcx.map.find(id.node) {
163 Some(ast_map::NodeItem(item)) => {
164 ty_of_item(self, &*item)
166 Some(ast_map::NodeForeignItem(foreign_item)) => {
167 let abi = self.tcx.map.get_foreign_abi(id.node);
168 ty_of_foreign_item(self, &*foreign_item, abi)
171 self.tcx.sess.bug(format!("unexpected sort of node \
172 in get_item_type_scheme(): {}",
178 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
179 get_trait_def(self, id)
182 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
183 span_err!(self.tcx.sess, span, E0121,
184 "the type placeholder `_` is not allowed within types on item signatures");
188 fn projected_ty(&self,
190 trait_ref: Rc<ty::TraitRef<'tcx>>,
191 item_name: ast::Name)
194 ty::mk_projection(self.tcx, trait_ref, item_name)
198 fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
200 variants: &[P<ast::Variant>],
201 generics: &ast::Generics) {
204 // Create a set of parameter types shared among all the variants.
205 for variant in variants.iter() {
206 let variant_def_id = local_def(variant.node.id);
208 // Nullary enum constructors get turned into constants; n-ary enum
209 // constructors get turned into functions.
210 let result_ty = match variant.node.kind {
211 ast::TupleVariantKind(ref args) if args.len() > 0 => {
212 let rs = ExplicitRscope;
213 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
214 ty::mk_ctor_fn(tcx, variant_def_id, input_tys[], enum_ty)
217 ast::TupleVariantKind(_) => {
221 ast::StructVariantKind(ref struct_def) => {
222 let scheme = TypeScheme {
223 generics: ty_generics_for_type_or_impl(ccx, generics),
227 convert_struct(ccx, &**struct_def, scheme, variant.node.id);
232 let scheme = TypeScheme {
233 generics: ty_generics_for_type_or_impl(ccx, generics),
237 tcx.tcache.borrow_mut().insert(variant_def_id, scheme);
239 write_ty_to_tcx(tcx, variant.node.id, result_ty);
243 fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
244 trait_id: ast::NodeId,
245 trait_def: &ty::TraitDef<'tcx>) {
247 if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
248 if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
249 // For each method, construct a suitable ty::Method and
250 // store it into the `tcx.impl_or_trait_items` table:
251 for trait_item in trait_items.iter() {
253 ast::RequiredMethod(_) |
254 ast::ProvidedMethod(_) => {
255 let ty_method = Rc::new(match *trait_item {
256 ast::RequiredMethod(ref m) => {
257 ty_method_of_trait_method(
270 ast::ProvidedMethod(ref m) => {
271 ty_method_of_trait_method(
278 m.pe_explicit_self(),
284 ast::TypeTraitItem(ref at) => {
285 tcx.sess.span_bug(at.ty_param.span,
286 "there shouldn't be a type trait item here")
290 debug!("ty_method_of_trait_method yielded {} for method {} of trait {}",
291 ty_method.repr(ccx.tcx),
292 trait_item.repr(ccx.tcx),
293 local_def(trait_id).repr(ccx.tcx));
295 make_method_ty(ccx, &*ty_method);
297 tcx.impl_or_trait_items
299 .insert(ty_method.def_id, ty::MethodTraitItem(ty_method));
301 ast::TypeTraitItem(ref ast_associated_type) => {
302 let trait_did = local_def(trait_id);
303 let associated_type = ty::AssociatedType {
304 name: ast_associated_type.ty_param.ident.name,
306 def_id: local_def(ast_associated_type.ty_param.id),
307 container: TraitContainer(trait_did),
310 let trait_item = ty::TypeTraitItem(Rc::new(associated_type));
311 tcx.impl_or_trait_items
313 .insert(associated_type.def_id, trait_item);
318 // Add an entry mapping
319 let trait_item_def_ids =
320 Rc::new(trait_items.iter().map(|ti| {
322 ast::RequiredMethod(ref ty_method) => {
323 ty::MethodTraitItemId(local_def(ty_method.id))
325 ast::ProvidedMethod(ref method) => {
326 ty::MethodTraitItemId(local_def(method.id))
328 ast::TypeTraitItem(ref typedef) => {
329 ty::TypeTraitItemId(local_def(typedef.ty_param.id))
334 let trait_def_id = local_def(trait_id);
335 tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids);
339 fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
340 ccx.tcx.tcache.borrow_mut().insert(
343 generics: m.generics.clone(),
344 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
347 fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
348 trait_id: ast::NodeId,
349 trait_generics: &ty::Generics<'tcx>,
350 _trait_items: &[ast::TraitItem],
353 m_explicit_self: &ast::ExplicitSelf,
355 m_generics: &ast::Generics,
356 m_unsafety: &ast::Unsafety,
357 m_decl: &ast::FnDecl)
358 -> ty::Method<'tcx> {
360 ty_generics_for_fn_or_method(
363 (*trait_generics).clone());
365 let (fty, explicit_self_category) = {
366 let trait_self_ty = ty::mk_self_type(ccx.tcx);
367 astconv::ty_of_method(ccx,
379 explicit_self_category,
380 // assume public, because this is only invoked on trait methods
383 TraitContainer(local_def(trait_id)),
389 fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
390 struct_generics: &ty::Generics<'tcx>,
391 v: &ast::StructField,
392 origin: ast::DefId) -> ty::field_ty {
393 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
394 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
395 /* add the field to the tcache */
396 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
398 generics: struct_generics.clone(),
403 ast::NamedField(ident, visibility) => {
406 id: local_def(v.node.id),
411 ast::UnnamedField(visibility) => {
413 name: special_idents::unnamed_field.name,
414 id: local_def(v.node.id),
422 fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
423 trait_def: &ty::TraitDef<'tcx>,
424 associated_type: &ast::AssociatedType)
426 let associated_type = Rc::new(ty::AssociatedType {
427 name: associated_type.ty_param.ident.name,
429 def_id: local_def(associated_type.ty_param.id),
430 container: TraitContainer(trait_def.trait_ref.def_id),
435 .insert(associated_type.def_id,
436 ty::TypeTraitItem(associated_type));
439 fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
440 container: ImplOrTraitItemContainer,
442 untransformed_rcvr_ty: Ty<'tcx>,
443 rcvr_ty_generics: &ty::Generics<'tcx>,
444 rcvr_visibility: ast::Visibility)
445 where I: Iterator<Item=&'i ast::Method> {
446 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
447 untransformed_rcvr_ty.repr(ccx.tcx),
448 rcvr_ty_generics.repr(ccx.tcx));
451 let mut seen_methods = FnvHashSet::new();
453 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
454 tcx.sess.span_err(m.span, "duplicate method in trait impl");
457 let m_def_id = local_def(m.id);
458 let mty = Rc::new(ty_of_method(ccx,
461 untransformed_rcvr_ty,
464 let fty = ty::mk_bare_fn(tcx, Some(m_def_id), tcx.mk_bare_fn(mty.fty.clone()));
465 debug!("method {} (id {}) has type {}",
466 m.pe_ident().repr(tcx),
469 tcx.tcache.borrow_mut().insert(
472 generics: mty.generics.clone(),
476 write_ty_to_tcx(tcx, m.id, fty);
478 debug!("writing method type: def_id={} mty={}",
479 mty.def_id, mty.repr(ccx.tcx));
481 tcx.impl_or_trait_items
483 .insert(mty.def_id, ty::MethodTraitItem(mty));
486 fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
487 container: ImplOrTraitItemContainer,
489 untransformed_rcvr_ty: Ty<'tcx>,
490 rcvr_ty_generics: &ty::Generics<'tcx>,
491 rcvr_visibility: ast::Visibility)
492 -> ty::Method<'tcx> {
494 ty_generics_for_fn_or_method(
497 (*rcvr_ty_generics).clone());
499 let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
501 untransformed_rcvr_ty,
502 m.pe_explicit_self(),
506 // if the method specifies a visibility, use that, otherwise
507 // inherit the visibility from the impl (so `foo` in `pub impl
508 // { fn foo(); }` is public, but private in `priv impl { fn
510 let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
512 ty::Method::new(m.pe_ident().name,
515 explicit_self_category,
523 fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
525 generics: &ast::Generics,
526 thing: &'static str) {
527 let mut warn = false;
529 for ty_param in generics.ty_params.iter() {
530 for bound in ty_param.bounds.iter() {
532 ast::TraitTyParamBound(..) => {
535 ast::RegionTyParamBound(..) => { }
541 // According to accepted RFC #XXX, we should
542 // eventually accept these, but it will not be
543 // part of this PR. Still, convert to warning to
544 // make bootstrapping easier.
545 span_warn!(ccx.tcx.sess, span, E0122,
546 "trait bounds are not (yet) enforced \
552 fn convert(ccx: &CollectCtxt, it: &ast::Item) {
554 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
556 // These don't define types.
557 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
558 ast::ItemEnum(ref enum_definition, ref generics) => {
559 let scheme = ty_of_item(ccx, it);
560 write_ty_to_tcx(tcx, it.id, scheme.ty);
561 get_enum_variant_types(ccx,
563 enum_definition.variants.as_slice(),
571 // Create generics from the generics specified in the impl head.
572 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
574 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
575 write_ty_to_tcx(tcx, it.id, selfty);
579 .insert(local_def(it.id),
581 generics: ty_generics.clone(),
585 // If there is a trait reference, treat the methods as always public.
586 // This is to work around some incorrect behavior in privacy checking:
587 // when the method belongs to a trait, it should acquire the privacy
588 // from the trait, not the impl. Forcing the visibility to be public
589 // makes things sorta work.
590 let parent_visibility = if opt_trait_ref.is_some() {
596 let mut methods = Vec::new();
597 for impl_item in impl_items.iter() {
599 ast::MethodImplItem(ref method) => {
600 let body_id = method.pe_body().id;
601 check_method_self_type(ccx,
602 &BindingRscope::new(),
604 method.pe_explicit_self(),
606 methods.push(&**method);
608 ast::TypeImplItem(ref typedef) => {
609 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
612 .insert(local_def(typedef.id),
614 generics: ty::Generics::empty(),
617 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
619 let associated_type = Rc::new(ty::AssociatedType {
620 name: typedef.ident.name,
622 def_id: local_def(typedef.id),
623 container: ty::ImplContainer(local_def(it.id)),
625 tcx.impl_or_trait_items
627 .insert(local_def(typedef.id),
628 ty::TypeTraitItem(associated_type));
634 ImplContainer(local_def(it.id)),
640 for trait_ref in opt_trait_ref.iter() {
641 astconv::instantiate_trait_ref(ccx,
648 ast::ItemTrait(_, _, _, ref trait_methods) => {
649 let trait_def = trait_def_of_item(ccx, it);
651 debug!("trait_def: ident={} trait_def={}",
652 it.ident.repr(ccx.tcx),
653 trait_def.repr(ccx.tcx));
655 for trait_method in trait_methods.iter() {
656 let self_type = ty::mk_self_type(tcx);
657 match *trait_method {
658 ast::RequiredMethod(ref type_method) => {
659 let rscope = BindingRscope::new();
660 check_method_self_type(ccx,
663 &type_method.explicit_self,
666 ast::ProvidedMethod(ref method) => {
667 check_method_self_type(ccx,
668 &BindingRscope::new(),
670 method.pe_explicit_self(),
673 ast::TypeTraitItem(ref associated_type) => {
674 convert_associated_type(ccx,
681 // Run convert_methods on the provided methods.
682 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
684 TraitContainer(local_def(it.id)),
685 trait_methods.iter().filter_map(|m| match *m {
686 ast::RequiredMethod(_) => None,
687 ast::ProvidedMethod(ref m) => Some(&**m),
688 ast::TypeTraitItem(_) => None,
690 untransformed_rcvr_ty,
694 // We need to do this *after* converting methods, since
695 // convert_methods produces a tcache entry that is wrong for
696 // static trait methods. This is somewhat unfortunate.
697 collect_trait_methods(ccx, it.id, &*trait_def);
699 ast::ItemStruct(ref struct_def, _) => {
700 // Write the class type.
701 let scheme = ty_of_item(ccx, it);
702 write_ty_to_tcx(tcx, it.id, scheme.ty);
704 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
706 convert_struct(ccx, &**struct_def, scheme, it.id);
708 ast::ItemTy(_, ref generics) => {
709 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
710 let tpt = ty_of_item(ccx, it);
711 write_ty_to_tcx(tcx, it.id, tpt.ty);
714 // This call populates the type cache with the converted type
715 // of the item in passing. All we have to do here is to write
716 // it into the node type table.
717 let scheme = ty_of_item(ccx, it);
718 write_ty_to_tcx(tcx, it.id, scheme.ty);
723 fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
724 struct_def: &ast::StructDef,
725 scheme: ty::TypeScheme<'tcx>,
729 // Write the type of each of the members and check for duplicate fields.
730 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap::new();
731 let field_tys = struct_def.fields.iter().map(|f| {
732 let result = convert_field(ccx, &scheme.generics, f, local_def(id));
734 if result.name != special_idents::unnamed_field.name {
735 let dup = match seen_fields.get(&result.name) {
737 span_err!(tcx.sess, f.span, E0124,
738 "field `{}` is already declared",
739 token::get_name(result.name));
740 span_note!(tcx.sess, *prev_span, "previously declared here");
745 // FIXME(#6393) this whole dup thing is just to satisfy
746 // the borrow checker :-(
748 seen_fields.insert(result.name, f.span);
755 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
757 let substs = mk_item_substs(ccx, &scheme.generics);
758 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
760 // If this struct is enum-like or tuple-like, create the type of its
762 match struct_def.ctor_id {
765 if struct_def.fields.len() == 0 {
767 write_ty_to_tcx(tcx, ctor_id, selfty);
769 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
770 } else if struct_def.fields[0].node.kind.is_unnamed() {
772 let inputs: Vec<_> = struct_def.fields.iter().map(
773 |field| (*tcx.tcache.borrow())[
774 local_def(field.node.id)].ty).collect();
775 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
779 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
780 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
782 generics: scheme.generics,
790 fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
791 // As above, this call populates the type table with the converted
792 // type of the foreign item. We simply write it into the node type
795 // For reasons I cannot fully articulate, I do so hate the AST
796 // map, and I regard each time that I use it as a personal and
797 // moral failing, but at the moment it seems like the only
798 // convenient way to extract the ABI. - ndm
799 let abi = ccx.tcx.map.get_foreign_abi(i.id);
801 let scheme = ty_of_foreign_item(ccx, i, abi);
802 write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
804 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
807 fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
808 trait_id: ast::DefId)
809 -> Rc<ty::TraitDef<'tcx>> {
810 if trait_id.krate != ast::LOCAL_CRATE {
811 return ty::lookup_trait_def(ccx.tcx, trait_id)
814 match ccx.tcx.map.get(trait_id.node) {
815 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
817 ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
823 fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
825 -> Rc<ty::TraitDef<'tcx>>
827 let def_id = local_def(it.id);
829 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
833 let (unsafety, generics, bounds, items) = match it.node {
834 ast::ItemTrait(unsafety,
838 (unsafety, generics, supertraits, items.as_slice())
843 format!("trait_def_of_item invoked on {}", s)[]);
847 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
849 let ty_generics = ty_generics_for_trait(ccx,
855 let self_param_ty = ty::ParamTy::for_self();
857 let bounds = compute_bounds(ccx,
858 self_param_ty.to_ty(ccx.tcx),
863 let associated_type_names: Vec<_> =
867 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
868 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
873 let trait_ref = Rc::new(ty::TraitRef {
878 let trait_def = Rc::new(ty::TraitDef {
880 generics: ty_generics,
882 trait_ref: trait_ref,
883 associated_type_names: associated_type_names,
885 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
889 fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
890 generics: &ast::Generics)
891 -> subst::Substs<'tcx>
893 // Creates a no-op substitution for the trait's type parameters.
898 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
904 // Start with the generics in the type parameters...
909 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
910 i as u32, def.ident.name))
913 // ...and also create the `Self` parameter.
914 let self_ty = ty::mk_self_type(ccx.tcx);
916 subst::Substs::new_trait(types, regions, self_ty)
920 fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
921 -> ty::TypeScheme<'tcx> {
922 let def_id = local_def(it.id);
924 if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
925 return scheme.clone();
928 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
929 let typ = ccx.to_ty(&ExplicitRscope, &**t);
930 let scheme = no_params(typ);
932 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
935 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
936 let ty_generics = ty_generics_for_fn_or_method(ccx,
938 ty::Generics::empty());
939 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
940 let scheme = TypeScheme {
941 generics: ty_generics,
942 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
944 debug!("type of {} (id {}) is {}",
945 token::get_ident(it.ident),
949 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
952 ast::ItemTy(ref t, ref generics) => {
953 match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
954 Some(scheme) => return scheme.clone(),
959 let ty = ccx.to_ty(&ExplicitRscope, &**t);
961 generics: ty_generics_for_type_or_impl(ccx, generics),
966 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
969 ast::ItemEnum(_, ref generics) => {
970 // Create a new generic polytype.
971 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
972 let substs = mk_item_substs(ccx, &ty_generics);
973 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
974 let scheme = TypeScheme {
975 generics: ty_generics,
979 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
982 ast::ItemTrait(..) => {
983 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
985 ast::ItemStruct(_, ref generics) => {
986 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
987 let substs = mk_item_substs(ccx, &ty_generics);
988 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
989 let scheme = TypeScheme {
990 generics: ty_generics,
994 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
997 ast::ItemImpl(..) | ast::ItemMod(_) |
998 ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
1002 fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1003 it: &ast::ForeignItem,
1004 abi: abi::Abi) -> ty::TypeScheme<'tcx>
1007 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1008 ty_of_foreign_fn_decl(ccx,
1014 ast::ForeignItemStatic(ref t, _) => {
1016 generics: ty::Generics::empty(),
1017 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1023 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1024 generics: &ast::Generics)
1025 -> ty::Generics<'tcx> {
1028 generics.lifetimes[],
1029 generics.ty_params[],
1030 ty::Generics::empty(),
1031 &generics.where_clause)
1034 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1035 trait_id: ast::NodeId,
1036 substs: &'tcx subst::Substs<'tcx>,
1037 ast_generics: &ast::Generics,
1038 trait_items: &[ast::TraitItem])
1039 -> ty::Generics<'tcx>
1041 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1042 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1047 ast_generics.lifetimes[],
1048 ast_generics.ty_params[],
1049 ty::Generics::empty(),
1050 &ast_generics.where_clause);
1052 // Add in the self type parameter.
1054 // Something of a hack: use the node id for the trait, also as
1055 // the node id for the Self type parameter.
1056 let param_id = trait_id;
1058 let self_trait_ref =
1059 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1062 let def = ty::TypeParameterDef {
1063 space: subst::SelfSpace,
1065 name: special_idents::type_self.name,
1066 def_id: local_def(param_id),
1067 bounds: ty::ParamBounds {
1068 region_bounds: vec!(),
1069 builtin_bounds: ty::empty_builtin_bounds(),
1070 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1071 projection_bounds: vec!(),
1076 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1078 generics.types.push(subst::SelfSpace, def);
1080 generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
1082 let assoc_predicates = predicates_for_associated_types(ccx,
1086 debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
1088 for assoc_predicate in assoc_predicates.into_iter() {
1089 generics.predicates.push(subst::TypeSpace, assoc_predicate);
1094 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1095 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1096 trait_items: &[ast::TraitItem])
1097 -> Vec<ty::Predicate<'tcx>>
1101 .flat_map(|trait_item| {
1102 let assoc_type_def = match *trait_item {
1103 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1104 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1105 return vec!().into_iter();
1109 let assoc_ty = ty::mk_projection(ccx.tcx,
1110 self_trait_ref.clone(),
1111 assoc_type_def.ident.name);
1113 let bounds = compute_bounds(ccx,
1115 assoc_type_def.bounds.as_slice(),
1116 SizedByDefault::Yes,
1117 assoc_type_def.span);
1119 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1125 fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1126 generics: &ast::Generics,
1127 base_generics: ty::Generics<'tcx>)
1128 -> ty::Generics<'tcx>
1130 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1134 generics.ty_params[],
1136 &generics.where_clause)
1139 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1140 fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1141 bounds: &mut ty::BuiltinBounds,
1142 ast_bounds: &[ast::TyParamBound],
1145 // Try to find an unbound in bounds.
1146 let mut unbound = None;
1147 for ab in ast_bounds.iter() {
1148 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1149 if unbound.is_none() {
1150 assert!(ptr.bound_lifetimes.is_empty());
1151 unbound = Some(ptr.trait_ref.clone());
1153 ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
1154 bound, only one is supported");
1159 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1162 // FIXME(#8559) currently requires the unbound to be built-in.
1163 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1165 Ok(kind_id) if trait_def_id != kind_id => {
1166 ccx.tcx.sess.span_warn(span,
1167 "default bound relaxed for a type parameter, but \
1168 this does nothing because the given bound is not \
1169 a default. Only `?Sized` is supported");
1170 ty::try_add_builtin_trait(ccx.tcx,
1177 _ if kind_id.is_ok() => {
1178 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1180 // No lang item for Sized, so we can't add it as a bound.
1185 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1186 space: subst::ParamSpace,
1187 lifetime_defs: &[ast::LifetimeDef],
1188 types: &[ast::TyParam],
1189 base_generics: ty::Generics<'tcx>,
1190 where_clause: &ast::WhereClause)
1191 -> ty::Generics<'tcx>
1193 let mut result = base_generics;
1195 for (i, l) in lifetime_defs.iter().enumerate() {
1196 let bounds = l.bounds.iter()
1197 .map(|l| ast_region_to_region(ccx.tcx, l))
1199 let def = ty::RegionParameterDef { name: l.lifetime.name,
1202 def_id: local_def(l.lifetime.id),
1204 debug!("ty_generics: def for region param: {}", def);
1205 result.regions.push(space, def);
1208 assert!(result.types.is_empty_in(space));
1210 // Now create the real type parameters.
1211 for (i, param) in types.iter().enumerate() {
1212 let def = get_or_create_type_parameter_def(ccx,
1216 debug!("ty_generics: def for type param: {}, {}",
1219 result.types.push(space, def);
1222 // Just for fun, also push the bounds from the type parameters
1223 // into the predicates list. This is currently kind of non-DRY.
1224 create_predicates(ccx.tcx, &mut result, space);
1226 // Add the bounds not associated with a type parameter
1227 for predicate in where_clause.predicates.iter() {
1229 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1230 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1232 for bound in bound_pred.bounds.iter() {
1234 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1235 let mut projections = Vec::new();
1237 let trait_ref = astconv::instantiate_poly_trait_ref(
1245 result.predicates.push(space, trait_ref.as_predicate());
1247 for projection in projections.iter() {
1248 result.predicates.push(space, projection.as_predicate());
1252 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1253 let region = ast_region_to_region(ccx.tcx, lifetime);
1254 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1255 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1261 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1262 let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
1263 for bound in region_pred.bounds.iter() {
1264 let r2 = ast_region_to_region(ccx.tcx, bound);
1265 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1266 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1270 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1272 ccx.tcx.sess.span_bug(eq_pred.span,
1273 "Equality constraints are not yet \
1274 implemented (#20041)")
1281 fn create_predicates<'tcx>(
1282 tcx: &ty::ctxt<'tcx>,
1283 result: &mut ty::Generics<'tcx>,
1284 space: subst::ParamSpace)
1286 for type_param_def in result.types.get_slice(space).iter() {
1287 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1288 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds).into_iter() {
1289 result.predicates.push(space, predicate);
1293 for region_param_def in result.regions.get_slice(space).iter() {
1294 let region = region_param_def.to_early_bound_region();
1295 for &bound_region in region_param_def.bounds.iter() {
1296 // account for new binder introduced in the predicate below; no need
1297 // to shift `region` because it is never a late-bound region
1298 let bound_region = ty_fold::shift_region(bound_region, 1);
1299 result.predicates.push(
1301 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1307 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1308 space: subst::ParamSpace,
1309 param: &ast::TyParam,
1311 -> ty::TypeParameterDef<'tcx>
1313 match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
1314 Some(d) => { return (*d).clone(); }
1318 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1319 let bounds = compute_bounds(ccx,
1320 param_ty.to_ty(ccx.tcx),
1322 SizedByDefault::Yes,
1324 let default = match param.default {
1327 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1328 let cur_idx = index;
1330 ty::walk_ty(ty, |t| {
1332 ty::ty_param(p) => if p.idx > cur_idx {
1333 span_err!(ccx.tcx.sess, path.span, E0128,
1334 "type parameters with a default cannot use \
1335 forward declared identifiers");
1345 let def = ty::TypeParameterDef {
1348 name: param.ident.name,
1349 def_id: local_def(param.id),
1354 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1359 enum SizedByDefault { Yes, No }
1361 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1362 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1363 /// built-in trait (formerly known as kind): Send.
1364 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1365 param_ty: ty::Ty<'tcx>,
1366 ast_bounds: &[ast::TyParamBound],
1367 sized_by_default: SizedByDefault,
1369 -> ty::ParamBounds<'tcx>
1371 let mut param_bounds = conv_param_bounds(ccx,
1376 if let SizedByDefault::Yes = sized_by_default {
1377 add_unsized_bound(ccx,
1378 &mut param_bounds.builtin_bounds,
1382 check_bounds_compatible(ccx.tcx,
1388 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1393 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1395 param_bounds: &ty::ParamBounds<'tcx>,
1397 // Currently the only bound which is incompatible with other bounds is
1399 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1400 ty::each_bound_trait_and_supertraits(
1402 param_bounds.trait_bounds[],
1404 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1405 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1406 span_err!(tcx.sess, span, E0129,
1407 "incompatible bounds on `{}`, \
1408 bound `{}` does not allow unsized type",
1409 param_ty.user_string(tcx),
1410 trait_ref.user_string(tcx));
1417 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1419 param_ty: ty::Ty<'tcx>,
1420 ast_bounds: &[ast::TyParamBound])
1421 -> ty::ParamBounds<'tcx>
1423 let astconv::PartitionedBounds { builtin_bounds,
1426 astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
1428 let mut projection_bounds = Vec::new();
1430 let trait_bounds: Vec<ty::PolyTraitRef> =
1431 trait_bounds.into_iter()
1433 astconv::instantiate_poly_trait_ref(ccx,
1437 &mut projection_bounds)
1440 let region_bounds: Vec<ty::Region> =
1441 region_bounds.into_iter()
1442 .map(|r| ast_region_to_region(ccx.tcx, r))
1445 region_bounds: region_bounds,
1446 builtin_bounds: builtin_bounds,
1447 trait_bounds: trait_bounds,
1448 projection_bounds: projection_bounds,
1452 fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1455 ast_generics: &ast::Generics,
1457 -> ty::TypeScheme<'tcx> {
1458 for i in decl.inputs.iter() {
1459 match (*i).pat.node {
1460 ast::PatIdent(_, _, _) => (),
1461 ast::PatWild(ast::PatWildSingle) => (),
1463 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1464 "patterns aren't allowed in foreign function declarations");
1469 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1471 ty::Generics::empty());
1472 let rb = BindingRscope::new();
1473 let input_tys = decl.inputs
1475 .map(|a| ty_of_arg(ccx, &rb, a, None))
1478 let output = match decl.output {
1479 ast::Return(ref ty) =>
1480 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1485 let t_fn = ty::mk_bare_fn(
1488 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1490 unsafety: ast::Unsafety::Unsafe,
1491 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1493 variadic: decl.variadic}),
1495 let scheme = TypeScheme {
1496 generics: ty_generics_for_fn_or_method,
1500 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1504 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1505 ty_generics: &ty::Generics<'tcx>)
1506 -> subst::Substs<'tcx>
1509 ty_generics.types.map(
1510 |def| ty::mk_param_from_def(ccx.tcx, def));
1513 ty_generics.regions.map(
1514 |def| def.to_early_bound_region());
1516 subst::Substs::new(types, regions)
1519 /// Verifies that the explicit self type of a method matches the impl
1520 /// or trait. This is a bit weird but basically because right now we
1521 /// don't handle the general case, but instead map it to one of
1522 /// several pre-defined options using various heuristics, this method
1523 /// comes back to check after the fact that explicit type the user
1524 /// wrote actually matches what the pre-defined option said.
1525 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1526 ccx: &CollectCtxt<'a, 'tcx>,
1528 required_type: Ty<'tcx>,
1529 explicit_self: &ast::ExplicitSelf,
1530 body_id: ast::NodeId)
1532 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1533 let typ = ccx.to_ty(rs, &**ast_type);
1534 let base_type = match typ.sty {
1535 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1536 ty::ty_uniq(typ) => typ,
1540 let body_scope = region::CodeExtent::from_node_id(body_id);
1542 // "Required type" comes from the trait definition. It may
1543 // contain late-bound regions from the method, but not the
1544 // trait (since traits only have early-bound region
1546 assert!(!base_type.has_regions_escaping_depth(1));
1547 let required_type_free =
1548 liberate_early_bound_regions(
1549 ccx.tcx, body_scope,
1550 &ty::liberate_late_bound_regions(
1551 ccx.tcx, body_scope, &ty::Binder(required_type)));
1553 // The "base type" comes from the impl. It too may have late-bound
1554 // regions from the method.
1555 assert!(!base_type.has_regions_escaping_depth(1));
1556 let base_type_free =
1557 liberate_early_bound_regions(
1558 ccx.tcx, body_scope,
1559 &ty::liberate_late_bound_regions(
1560 ccx.tcx, body_scope, &ty::Binder(base_type)));
1562 debug!("required_type={} required_type_free={} \
1563 base_type={} base_type_free={}",
1564 required_type.repr(ccx.tcx),
1565 required_type_free.repr(ccx.tcx),
1566 base_type.repr(ccx.tcx),
1567 base_type_free.repr(ccx.tcx));
1568 let infcx = infer::new_infer_ctxt(ccx.tcx);
1569 drop(::require_same_types(ccx.tcx,
1576 format!("mismatched self type: expected `{}`",
1577 ppaux::ty_to_string(ccx.tcx, required_type))
1579 infcx.resolve_regions_and_report_errors(body_id);
1582 fn liberate_early_bound_regions<'tcx,T>(
1583 tcx: &ty::ctxt<'tcx>,
1584 scope: region::CodeExtent,
1587 where T : TypeFoldable<'tcx> + Repr<'tcx>
1590 * Convert early-bound regions into free regions; normally this is done by
1591 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1592 * method-self-type check is kind of hacky and done very early in the process,
1593 * before we really have a `ParameterEnvironment` to check.
1596 ty_fold::fold_regions(tcx, value, |region, _| {
1598 ty::ReEarlyBound(id, _, _, name) => {
1599 let def_id = local_def(id);
1600 ty::ReFree(ty::FreeRegion { scope: scope,
1601 bound_region: ty::BrNamed(def_id, name) })