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};
44 use {CrateCtxt, no_params, write_ty_to_tcx};
45 use util::nodemap::{FnvHashMap, FnvHashSet};
47 use util::ppaux::{Repr,UserString};
54 use syntax::ast_util::{local_def, PostExpansionMethod};
55 use syntax::codemap::Span;
56 use syntax::parse::token::{special_idents};
57 use syntax::parse::token;
61 ///////////////////////////////////////////////////////////////////////////
64 pub fn collect_item_types(ccx: &CrateCtxt) {
65 fn collect_intrinsic_type(ccx: &CrateCtxt,
66 lang_item: ast::DefId) {
67 let ty::TypeScheme { ty, .. } =
68 ccx.get_item_type_scheme(lang_item);
69 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
72 match ccx.tcx.lang_items.ty_desc() {
73 Some(id) => { collect_intrinsic_type(ccx, id); }
76 match ccx.tcx.lang_items.opaque() {
77 Some(id) => { collect_intrinsic_type(ccx, id); }
81 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
82 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
84 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
85 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
88 ///////////////////////////////////////////////////////////////////////////
89 // First phase: just collect *trait definitions* -- basically, the set
90 // of type parameters and supertraits. This is information we need to
91 // know later when parsing field defs.
93 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
94 ccx: &'a CrateCtxt<'a, 'tcx>
97 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
98 fn visit_item(&mut self, i: &ast::Item) {
100 ast::ItemTrait(..) => {
101 // computing the trait def also fills in the table
102 let _ = trait_def_of_item(self.ccx, i);
107 visit::walk_item(self, i);
111 ///////////////////////////////////////////////////////////////////////////
112 // Second phase: collection proper.
114 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
115 ccx: &'a CrateCtxt<'a, 'tcx>
118 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
119 fn visit_item(&mut self, i: &ast::Item) {
120 convert(self.ccx, i);
121 visit::walk_item(self, i);
123 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
124 convert_foreign(self.ccx, i);
125 visit::walk_foreign_item(self, i);
129 ///////////////////////////////////////////////////////////////////////////
130 // Utility types and common code for the above passes.
132 pub trait ToTy<'tcx> {
133 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
136 impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> {
137 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
138 ast_ty_to_ty(self, rs, ast_ty)
142 impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
143 fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
145 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
146 if id.krate != ast::LOCAL_CRATE {
147 return csearch::get_type(self.tcx, id)
150 match self.tcx.map.find(id.node) {
151 Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
152 Some(ast_map::NodeForeignItem(foreign_item)) => {
153 let abi = self.tcx.map.get_foreign_abi(id.node);
154 ty_of_foreign_item(self, &*foreign_item, abi)
157 self.tcx.sess.bug(format!("unexpected sort of node \
158 in get_item_type_scheme(): {}",
164 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
165 get_trait_def(self, id)
168 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
169 span_err!(self.tcx.sess, span, E0121,
170 "the type placeholder `_` is not allowed within types on item signatures");
174 fn projected_ty(&self,
176 trait_ref: Rc<ty::TraitRef<'tcx>>,
177 item_name: ast::Name)
180 ty::mk_projection(self.tcx, trait_ref, item_name)
184 pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
186 variants: &[P<ast::Variant>],
187 generics: &ast::Generics) {
190 // Create a set of parameter types shared among all the variants.
191 for variant in variants.iter() {
192 let variant_def_id = local_def(variant.node.id);
194 // Nullary enum constructors get turned into constants; n-ary enum
195 // constructors get turned into functions.
196 let result_ty = match variant.node.kind {
197 ast::TupleVariantKind(ref args) if args.len() > 0 => {
198 let rs = ExplicitRscope;
199 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
200 ty::mk_ctor_fn(tcx, variant_def_id, input_tys[], enum_ty)
203 ast::TupleVariantKind(_) => {
207 ast::StructVariantKind(ref struct_def) => {
208 let scheme = TypeScheme {
209 generics: ty_generics_for_type_or_impl(ccx, generics),
213 convert_struct(ccx, &**struct_def, scheme, variant.node.id);
218 let scheme = TypeScheme {
219 generics: ty_generics_for_type_or_impl(ccx, generics),
223 tcx.tcache.borrow_mut().insert(variant_def_id, scheme);
225 write_ty_to_tcx(tcx, variant.node.id, result_ty);
229 fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
230 trait_id: ast::NodeId,
231 trait_def: &ty::TraitDef<'tcx>) {
233 if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
234 if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
235 // For each method, construct a suitable ty::Method and
236 // store it into the `tcx.impl_or_trait_items` table:
237 for trait_item in trait_items.iter() {
239 ast::RequiredMethod(_) |
240 ast::ProvidedMethod(_) => {
241 let ty_method = Rc::new(match *trait_item {
242 ast::RequiredMethod(ref m) => {
243 ty_method_of_trait_method(
256 ast::ProvidedMethod(ref m) => {
257 ty_method_of_trait_method(
264 m.pe_explicit_self(),
270 ast::TypeTraitItem(ref at) => {
271 tcx.sess.span_bug(at.ty_param.span,
272 "there shouldn't be a type trait item here")
276 debug!("ty_method_of_trait_method yielded {} for method {} of trait {}",
277 ty_method.repr(ccx.tcx),
278 trait_item.repr(ccx.tcx),
279 local_def(trait_id).repr(ccx.tcx));
281 make_method_ty(ccx, &*ty_method);
283 tcx.impl_or_trait_items
285 .insert(ty_method.def_id, ty::MethodTraitItem(ty_method));
287 ast::TypeTraitItem(ref ast_associated_type) => {
288 let trait_did = local_def(trait_id);
289 let associated_type = ty::AssociatedType {
290 name: ast_associated_type.ty_param.ident.name,
292 def_id: local_def(ast_associated_type.ty_param.id),
293 container: TraitContainer(trait_did),
296 let trait_item = ty::TypeTraitItem(Rc::new(associated_type));
297 tcx.impl_or_trait_items
299 .insert(associated_type.def_id, trait_item);
304 // Add an entry mapping
305 let trait_item_def_ids =
306 Rc::new(trait_items.iter().map(|ti| {
308 ast::RequiredMethod(ref ty_method) => {
309 ty::MethodTraitItemId(local_def(ty_method.id))
311 ast::ProvidedMethod(ref method) => {
312 ty::MethodTraitItemId(local_def(method.id))
314 ast::TypeTraitItem(ref typedef) => {
315 ty::TypeTraitItemId(local_def(typedef.ty_param.id))
320 let trait_def_id = local_def(trait_id);
321 tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids);
325 fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
326 ccx.tcx.tcache.borrow_mut().insert(
329 generics: m.generics.clone(),
330 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
333 fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
334 trait_id: ast::NodeId,
335 trait_generics: &ty::Generics<'tcx>,
336 _trait_items: &[ast::TraitItem],
339 m_explicit_self: &ast::ExplicitSelf,
341 m_generics: &ast::Generics,
342 m_unsafety: &ast::Unsafety,
343 m_decl: &ast::FnDecl)
344 -> ty::Method<'tcx> {
346 ty_generics_for_fn_or_method(
349 (*trait_generics).clone());
351 let (fty, explicit_self_category) = {
352 let trait_self_ty = ty::mk_self_type(ccx.tcx);
353 astconv::ty_of_method(ccx,
365 explicit_self_category,
366 // assume public, because this is only invoked on trait methods
369 TraitContainer(local_def(trait_id)),
375 pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
376 struct_generics: &ty::Generics<'tcx>,
377 v: &ast::StructField,
378 origin: ast::DefId) -> ty::field_ty {
379 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
380 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
381 /* add the field to the tcache */
382 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
384 generics: struct_generics.clone(),
389 ast::NamedField(ident, visibility) => {
392 id: local_def(v.node.id),
397 ast::UnnamedField(visibility) => {
399 name: special_idents::unnamed_field.name,
400 id: local_def(v.node.id),
408 fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
409 trait_def: &ty::TraitDef<'tcx>,
410 associated_type: &ast::AssociatedType)
412 let associated_type = Rc::new(ty::AssociatedType {
413 name: associated_type.ty_param.ident.name,
415 def_id: local_def(associated_type.ty_param.id),
416 container: TraitContainer(trait_def.trait_ref.def_id),
421 .insert(associated_type.def_id,
422 ty::TypeTraitItem(associated_type));
425 fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
426 container: ImplOrTraitItemContainer,
428 untransformed_rcvr_ty: Ty<'tcx>,
429 rcvr_ty_generics: &ty::Generics<'tcx>,
430 rcvr_visibility: ast::Visibility)
431 where I: Iterator<Item=&'i ast::Method> {
432 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
433 untransformed_rcvr_ty.repr(ccx.tcx),
434 rcvr_ty_generics.repr(ccx.tcx));
437 let mut seen_methods = FnvHashSet::new();
439 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
440 tcx.sess.span_err(m.span, "duplicate method in trait impl");
443 let m_def_id = local_def(m.id);
444 let mty = Rc::new(ty_of_method(ccx,
447 untransformed_rcvr_ty,
450 let fty = ty::mk_bare_fn(tcx, Some(m_def_id), tcx.mk_bare_fn(mty.fty.clone()));
451 debug!("method {} (id {}) has type {}",
452 m.pe_ident().repr(tcx),
455 tcx.tcache.borrow_mut().insert(
458 generics: mty.generics.clone(),
462 write_ty_to_tcx(tcx, m.id, fty);
464 debug!("writing method type: def_id={} mty={}",
465 mty.def_id, mty.repr(ccx.tcx));
467 tcx.impl_or_trait_items
469 .insert(mty.def_id, ty::MethodTraitItem(mty));
472 fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
473 container: ImplOrTraitItemContainer,
475 untransformed_rcvr_ty: Ty<'tcx>,
476 rcvr_ty_generics: &ty::Generics<'tcx>,
477 rcvr_visibility: ast::Visibility)
478 -> ty::Method<'tcx> {
480 ty_generics_for_fn_or_method(
483 (*rcvr_ty_generics).clone());
485 let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
487 untransformed_rcvr_ty,
488 m.pe_explicit_self(),
492 // if the method specifies a visibility, use that, otherwise
493 // inherit the visibility from the impl (so `foo` in `pub impl
494 // { fn foo(); }` is public, but private in `priv impl { fn
496 let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
498 ty::Method::new(m.pe_ident().name,
501 explicit_self_category,
509 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
511 generics: &ast::Generics,
512 thing: &'static str) {
513 let mut warn = false;
515 for ty_param in generics.ty_params.iter() {
516 for bound in ty_param.bounds.iter() {
518 ast::TraitTyParamBound(..) => {
521 ast::RegionTyParamBound(..) => { }
527 // According to accepted RFC #XXX, we should
528 // eventually accept these, but it will not be
529 // part of this PR. Still, convert to warning to
530 // make bootstrapping easier.
531 span_warn!(ccx.tcx.sess, span, E0122,
532 "trait bounds are not (yet) enforced \
538 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
540 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
542 // These don't define types.
543 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
544 ast::ItemEnum(ref enum_definition, ref generics) => {
545 let scheme = ty_of_item(ccx, it);
546 write_ty_to_tcx(tcx, it.id, scheme.ty);
547 get_enum_variant_types(ccx,
549 enum_definition.variants.as_slice(),
557 // Create generics from the generics specified in the impl head.
558 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
560 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
561 write_ty_to_tcx(tcx, it.id, selfty);
565 .insert(local_def(it.id),
567 generics: ty_generics.clone(),
571 // If there is a trait reference, treat the methods as always public.
572 // This is to work around some incorrect behavior in privacy checking:
573 // when the method belongs to a trait, it should acquire the privacy
574 // from the trait, not the impl. Forcing the visibility to be public
575 // makes things sorta work.
576 let parent_visibility = if opt_trait_ref.is_some() {
582 let mut methods = Vec::new();
583 for impl_item in impl_items.iter() {
585 ast::MethodImplItem(ref method) => {
586 let body_id = method.pe_body().id;
587 check_method_self_type(ccx,
588 &BindingRscope::new(),
590 method.pe_explicit_self(),
592 methods.push(&**method);
594 ast::TypeImplItem(ref typedef) => {
595 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
598 .insert(local_def(typedef.id),
600 generics: ty::Generics::empty(),
603 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
605 let associated_type = Rc::new(ty::AssociatedType {
606 name: typedef.ident.name,
608 def_id: local_def(typedef.id),
609 container: ty::ImplContainer(local_def(it.id)),
611 tcx.impl_or_trait_items
613 .insert(local_def(typedef.id),
614 ty::TypeTraitItem(associated_type));
620 ImplContainer(local_def(it.id)),
626 for trait_ref in opt_trait_ref.iter() {
627 astconv::instantiate_trait_ref(ccx,
634 ast::ItemTrait(_, _, _, ref trait_methods) => {
635 let trait_def = trait_def_of_item(ccx, it);
637 debug!("trait_def: ident={} trait_def={}",
638 it.ident.repr(ccx.tcx),
639 trait_def.repr(ccx.tcx()));
641 for trait_method in trait_methods.iter() {
642 let self_type = ty::mk_self_type(tcx);
643 match *trait_method {
644 ast::RequiredMethod(ref type_method) => {
645 let rscope = BindingRscope::new();
646 check_method_self_type(ccx,
649 &type_method.explicit_self,
652 ast::ProvidedMethod(ref method) => {
653 check_method_self_type(ccx,
654 &BindingRscope::new(),
656 method.pe_explicit_self(),
659 ast::TypeTraitItem(ref associated_type) => {
660 convert_associated_type(ccx,
667 // Run convert_methods on the provided methods.
668 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
670 TraitContainer(local_def(it.id)),
671 trait_methods.iter().filter_map(|m| match *m {
672 ast::RequiredMethod(_) => None,
673 ast::ProvidedMethod(ref m) => Some(&**m),
674 ast::TypeTraitItem(_) => None,
676 untransformed_rcvr_ty,
680 // We need to do this *after* converting methods, since
681 // convert_methods produces a tcache entry that is wrong for
682 // static trait methods. This is somewhat unfortunate.
683 collect_trait_methods(ccx, it.id, &*trait_def);
685 ast::ItemStruct(ref struct_def, _) => {
686 // Write the class type.
687 let scheme = ty_of_item(ccx, it);
688 write_ty_to_tcx(tcx, it.id, scheme.ty);
690 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
692 convert_struct(ccx, &**struct_def, scheme, it.id);
694 ast::ItemTy(_, ref generics) => {
695 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
696 let tpt = ty_of_item(ccx, it);
697 write_ty_to_tcx(tcx, it.id, tpt.ty);
700 // This call populates the type cache with the converted type
701 // of the item in passing. All we have to do here is to write
702 // it into the node type table.
703 let scheme = ty_of_item(ccx, it);
704 write_ty_to_tcx(tcx, it.id, scheme.ty);
709 pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
710 struct_def: &ast::StructDef,
711 scheme: ty::TypeScheme<'tcx>,
715 // Write the type of each of the members and check for duplicate fields.
716 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap::new();
717 let field_tys = struct_def.fields.iter().map(|f| {
718 let result = convert_field(ccx, &scheme.generics, f, local_def(id));
720 if result.name != special_idents::unnamed_field.name {
721 let dup = match seen_fields.get(&result.name) {
723 span_err!(tcx.sess, f.span, E0124,
724 "field `{}` is already declared",
725 token::get_name(result.name));
726 span_note!(tcx.sess, *prev_span, "previously declared here");
731 // FIXME(#6393) this whole dup thing is just to satisfy
732 // the borrow checker :-(
734 seen_fields.insert(result.name, f.span);
741 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
743 let substs = mk_item_substs(ccx, &scheme.generics);
744 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
746 // If this struct is enum-like or tuple-like, create the type of its
748 match struct_def.ctor_id {
751 if struct_def.fields.len() == 0 {
753 write_ty_to_tcx(tcx, ctor_id, selfty);
755 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
756 } else if struct_def.fields[0].node.kind.is_unnamed() {
758 let inputs: Vec<_> = struct_def.fields.iter().map(
759 |field| (*tcx.tcache.borrow())[
760 local_def(field.node.id)].ty).collect();
761 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
765 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
766 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
768 generics: scheme.generics,
776 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
777 // As above, this call populates the type table with the converted
778 // type of the foreign item. We simply write it into the node type
781 // For reasons I cannot fully articulate, I do so hate the AST
782 // map, and I regard each time that I use it as a personal and
783 // moral failing, but at the moment it seems like the only
784 // convenient way to extract the ABI. - ndm
785 let abi = ccx.tcx.map.get_foreign_abi(i.id);
787 let scheme = ty_of_foreign_item(ccx, i, abi);
788 write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
790 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
793 fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
794 trait_id: ast::DefId)
795 -> Rc<ty::TraitDef<'tcx>> {
796 if trait_id.krate != ast::LOCAL_CRATE {
797 return ty::lookup_trait_def(ccx.tcx, trait_id)
800 match ccx.tcx.map.get(trait_id.node) {
801 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
803 ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
809 pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
811 -> Rc<ty::TraitDef<'tcx>>
813 let def_id = local_def(it.id);
815 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
819 let (unsafety, generics, bounds, items) = match it.node {
820 ast::ItemTrait(unsafety,
824 (unsafety, generics, supertraits, items.as_slice())
829 format!("trait_def_of_item invoked on {}", s)[]);
833 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
835 let ty_generics = ty_generics_for_trait(ccx,
841 let self_param_ty = ty::ParamTy::for_self();
843 let bounds = compute_bounds(ccx,
844 self_param_ty.to_ty(ccx.tcx),
849 let associated_type_names: Vec<_> =
853 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
854 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
859 let trait_ref = Rc::new(ty::TraitRef {
864 let trait_def = Rc::new(ty::TraitDef {
866 generics: ty_generics,
868 trait_ref: trait_ref,
869 associated_type_names: associated_type_names,
871 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
875 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
876 generics: &ast::Generics)
877 -> subst::Substs<'tcx>
879 // Creates a no-op substitution for the trait's type parameters.
884 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
890 // Start with the generics in the type parameters...
895 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
896 i as u32, def.ident.name))
899 // ...and also create the `Self` parameter.
900 let self_ty = ty::mk_self_type(ccx.tcx);
902 subst::Substs::new_trait(types, regions, self_ty)
906 pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
907 -> ty::TypeScheme<'tcx> {
908 let def_id = local_def(it.id);
910 if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
911 return scheme.clone();
914 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
915 let typ = ccx.to_ty(&ExplicitRscope, &**t);
916 let scheme = no_params(typ);
918 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
921 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
922 let ty_generics = ty_generics_for_fn_or_method(ccx,
924 ty::Generics::empty());
925 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
926 let scheme = TypeScheme {
927 generics: ty_generics,
928 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
930 debug!("type of {} (id {}) is {}",
931 token::get_ident(it.ident),
935 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
938 ast::ItemTy(ref t, ref generics) => {
939 match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
940 Some(scheme) => return scheme.clone(),
945 let ty = ccx.to_ty(&ExplicitRscope, &**t);
947 generics: ty_generics_for_type_or_impl(ccx, generics),
952 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
955 ast::ItemEnum(_, ref generics) => {
956 // Create a new generic polytype.
957 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
958 let substs = mk_item_substs(ccx, &ty_generics);
959 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
960 let scheme = TypeScheme {
961 generics: ty_generics,
965 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
968 ast::ItemTrait(..) => {
969 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
971 ast::ItemStruct(_, ref generics) => {
972 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
973 let substs = mk_item_substs(ccx, &ty_generics);
974 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
975 let scheme = TypeScheme {
976 generics: ty_generics,
980 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
983 ast::ItemImpl(..) | ast::ItemMod(_) |
984 ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
988 pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
989 it: &ast::ForeignItem,
990 abi: abi::Abi) -> ty::TypeScheme<'tcx>
993 ast::ForeignItemFn(ref fn_decl, ref generics) => {
994 ty_of_foreign_fn_decl(ccx,
1000 ast::ForeignItemStatic(ref t, _) => {
1002 generics: ty::Generics::empty(),
1003 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1009 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1010 generics: &ast::Generics)
1011 -> ty::Generics<'tcx> {
1014 generics.lifetimes[],
1015 generics.ty_params[],
1016 ty::Generics::empty(),
1017 &generics.where_clause)
1020 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1021 trait_id: ast::NodeId,
1022 substs: &'tcx subst::Substs<'tcx>,
1023 ast_generics: &ast::Generics,
1024 trait_items: &[ast::TraitItem])
1025 -> ty::Generics<'tcx>
1027 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1028 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1033 ast_generics.lifetimes[],
1034 ast_generics.ty_params[],
1035 ty::Generics::empty(),
1036 &ast_generics.where_clause);
1038 // Add in the self type parameter.
1040 // Something of a hack: use the node id for the trait, also as
1041 // the node id for the Self type parameter.
1042 let param_id = trait_id;
1044 let self_trait_ref =
1045 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1048 let def = ty::TypeParameterDef {
1049 space: subst::SelfSpace,
1051 name: special_idents::type_self.name,
1052 def_id: local_def(param_id),
1053 bounds: ty::ParamBounds {
1054 region_bounds: vec!(),
1055 builtin_bounds: ty::empty_builtin_bounds(),
1056 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1057 projection_bounds: vec!(),
1062 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1064 generics.types.push(subst::SelfSpace, def);
1066 generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
1068 let assoc_predicates = predicates_for_associated_types(ccx,
1072 debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
1074 for assoc_predicate in assoc_predicates.into_iter() {
1075 generics.predicates.push(subst::TypeSpace, assoc_predicate);
1080 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1081 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1082 trait_items: &[ast::TraitItem])
1083 -> Vec<ty::Predicate<'tcx>>
1087 .flat_map(|trait_item| {
1088 let assoc_type_def = match *trait_item {
1089 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1090 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1091 return vec!().into_iter();
1095 let assoc_ty = ty::mk_projection(ccx.tcx,
1096 self_trait_ref.clone(),
1097 assoc_type_def.ident.name);
1099 let bounds = compute_bounds(ccx,
1101 assoc_type_def.bounds.as_slice(),
1102 SizedByDefault::Yes,
1103 assoc_type_def.span);
1105 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1111 fn ty_generics_for_fn_or_method<'tcx,AC>(
1113 generics: &ast::Generics,
1114 base_generics: ty::Generics<'tcx>)
1115 -> ty::Generics<'tcx>
1116 where AC: AstConv<'tcx> {
1117 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1121 generics.ty_params[],
1123 &generics.where_clause)
1126 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1127 fn add_unsized_bound<'tcx,AC>(this: &AC,
1128 bounds: &mut ty::BuiltinBounds,
1129 ast_bounds: &[ast::TyParamBound],
1131 where AC: AstConv<'tcx> {
1132 // Try to find an unbound in bounds.
1133 let mut unbound = None;
1134 for ab in ast_bounds.iter() {
1135 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1136 if unbound.is_none() {
1137 assert!(ptr.bound_lifetimes.is_empty());
1138 unbound = Some(ptr.trait_ref.clone());
1140 this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \
1141 bound, only one is supported");
1146 let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
1149 // FIXME(#8559) currently requires the unbound to be built-in.
1150 let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
1152 Ok(kind_id) if trait_def_id != kind_id => {
1153 this.tcx().sess.span_warn(span,
1154 "default bound relaxed for a type parameter, but \
1155 this does nothing because the given bound is not \
1156 a default. Only `?Sized` is supported");
1157 ty::try_add_builtin_trait(this.tcx(),
1164 _ if kind_id.is_ok() => {
1165 ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
1167 // No lang item for Sized, so we can't add it as a bound.
1172 fn ty_generics<'tcx,AC>(this: &AC,
1173 space: subst::ParamSpace,
1174 lifetime_defs: &[ast::LifetimeDef],
1175 types: &[ast::TyParam],
1176 base_generics: ty::Generics<'tcx>,
1177 where_clause: &ast::WhereClause)
1178 -> ty::Generics<'tcx>
1179 where AC: AstConv<'tcx>
1181 let mut result = base_generics;
1183 for (i, l) in lifetime_defs.iter().enumerate() {
1184 let bounds = l.bounds.iter()
1185 .map(|l| ast_region_to_region(this.tcx(), l))
1187 let def = ty::RegionParameterDef { name: l.lifetime.name,
1190 def_id: local_def(l.lifetime.id),
1192 debug!("ty_generics: def for region param: {}", def);
1193 result.regions.push(space, def);
1196 assert!(result.types.is_empty_in(space));
1198 // Now create the real type parameters.
1199 for (i, param) in types.iter().enumerate() {
1200 let def = get_or_create_type_parameter_def(this,
1204 debug!("ty_generics: def for type param: {}, {}",
1205 def.repr(this.tcx()),
1207 result.types.push(space, def);
1210 // Just for fun, also push the bounds from the type parameters
1211 // into the predicates list. This is currently kind of non-DRY.
1212 create_predicates(this.tcx(), &mut result, space);
1214 // Add the bounds not associated with a type parameter
1215 for predicate in where_clause.predicates.iter() {
1217 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1218 let ty = ast_ty_to_ty(this, &ExplicitRscope, &*bound_pred.bounded_ty);
1220 for bound in bound_pred.bounds.iter() {
1222 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1223 let mut projections = Vec::new();
1225 let trait_ref = astconv::instantiate_poly_trait_ref(
1233 result.predicates.push(space, trait_ref.as_predicate());
1235 for projection in projections.iter() {
1236 result.predicates.push(space, projection.as_predicate());
1240 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1241 let region = ast_region_to_region(this.tcx(), lifetime);
1242 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1243 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1249 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1250 let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime);
1251 for bound in region_pred.bounds.iter() {
1252 let r2 = ast_region_to_region(this.tcx(), bound);
1253 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1254 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1258 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1260 this.tcx().sess.span_bug(eq_pred.span,
1261 "Equality constraints are not yet \
1262 implemented (#20041)")
1269 fn create_predicates<'tcx>(
1270 tcx: &ty::ctxt<'tcx>,
1271 result: &mut ty::Generics<'tcx>,
1272 space: subst::ParamSpace)
1274 for type_param_def in result.types.get_slice(space).iter() {
1275 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1276 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds).into_iter() {
1277 result.predicates.push(space, predicate);
1281 for region_param_def in result.regions.get_slice(space).iter() {
1282 let region = region_param_def.to_early_bound_region();
1283 for &bound_region in region_param_def.bounds.iter() {
1284 // account for new binder introduced in the predicate below; no need
1285 // to shift `region` because it is never a late-bound region
1286 let bound_region = ty_fold::shift_region(bound_region, 1);
1287 result.predicates.push(
1289 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1295 fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
1296 space: subst::ParamSpace,
1297 param: &ast::TyParam,
1299 -> ty::TypeParameterDef<'tcx>
1300 where AC: AstConv<'tcx>
1302 match this.tcx().ty_param_defs.borrow().get(¶m.id) {
1303 Some(d) => { return (*d).clone(); }
1307 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1308 let bounds = compute_bounds(this,
1309 param_ty.to_ty(this.tcx()),
1311 SizedByDefault::Yes,
1313 let default = match param.default {
1316 let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
1317 let cur_idx = index;
1319 ty::walk_ty(ty, |t| {
1321 ty::ty_param(p) => if p.idx > cur_idx {
1322 span_err!(this.tcx().sess, path.span, E0128,
1323 "type parameters with a default cannot use \
1324 forward declared identifiers");
1334 let def = ty::TypeParameterDef {
1337 name: param.ident.name,
1338 def_id: local_def(param.id),
1343 this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
1348 enum SizedByDefault { Yes, No }
1350 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1351 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1352 /// built-in trait (formerly known as kind): Send.
1353 fn compute_bounds<'tcx,AC>(this: &AC,
1354 param_ty: ty::Ty<'tcx>,
1355 ast_bounds: &[ast::TyParamBound],
1356 sized_by_default: SizedByDefault,
1358 -> ty::ParamBounds<'tcx>
1359 where AC: AstConv<'tcx>
1361 let mut param_bounds = conv_param_bounds(this,
1366 if let SizedByDefault::Yes = sized_by_default {
1367 add_unsized_bound(this,
1368 &mut param_bounds.builtin_bounds,
1372 check_bounds_compatible(this.tcx(),
1378 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1383 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1385 param_bounds: &ty::ParamBounds<'tcx>,
1387 // Currently the only bound which is incompatible with other bounds is
1389 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1390 ty::each_bound_trait_and_supertraits(
1392 param_bounds.trait_bounds[],
1394 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1395 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1396 span_err!(tcx.sess, span, E0129,
1397 "incompatible bounds on `{}`, \
1398 bound `{}` does not allow unsized type",
1399 param_ty.user_string(tcx),
1400 trait_ref.user_string(tcx));
1407 fn conv_param_bounds<'tcx,AC>(this: &AC,
1409 param_ty: ty::Ty<'tcx>,
1410 ast_bounds: &[ast::TyParamBound])
1411 -> ty::ParamBounds<'tcx>
1412 where AC: AstConv<'tcx>
1414 let astconv::PartitionedBounds { builtin_bounds,
1417 astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
1419 let mut projection_bounds = Vec::new();
1421 let trait_bounds: Vec<ty::PolyTraitRef> =
1422 trait_bounds.into_iter()
1424 astconv::instantiate_poly_trait_ref(this,
1428 &mut projection_bounds)
1431 let region_bounds: Vec<ty::Region> =
1432 region_bounds.into_iter()
1433 .map(|r| ast_region_to_region(this.tcx(), r))
1436 region_bounds: region_bounds,
1437 builtin_bounds: builtin_bounds,
1438 trait_bounds: trait_bounds,
1439 projection_bounds: projection_bounds,
1443 pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1446 ast_generics: &ast::Generics,
1448 -> ty::TypeScheme<'tcx> {
1449 for i in decl.inputs.iter() {
1450 match (*i).pat.node {
1451 ast::PatIdent(_, _, _) => (),
1452 ast::PatWild(ast::PatWildSingle) => (),
1454 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1455 "patterns aren't allowed in foreign function declarations");
1460 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1462 ty::Generics::empty());
1463 let rb = BindingRscope::new();
1464 let input_tys = decl.inputs
1466 .map(|a| ty_of_arg(ccx, &rb, a, None))
1469 let output = match decl.output {
1470 ast::Return(ref ty) =>
1471 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1476 let t_fn = ty::mk_bare_fn(
1479 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1481 unsafety: ast::Unsafety::Unsafe,
1482 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1484 variadic: decl.variadic}),
1486 let scheme = TypeScheme {
1487 generics: ty_generics_for_fn_or_method,
1491 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1495 pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1496 ty_generics: &ty::Generics<'tcx>)
1497 -> subst::Substs<'tcx>
1500 ty_generics.types.map(
1501 |def| ty::mk_param_from_def(ccx.tcx, def));
1504 ty_generics.regions.map(
1505 |def| def.to_early_bound_region());
1507 subst::Substs::new(types, regions)
1510 /// Verifies that the explicit self type of a method matches the impl
1511 /// or trait. This is a bit weird but basically because right now we
1512 /// don't handle the general case, but instead map it to one of
1513 /// several pre-defined options using various heuristics, this method
1514 /// comes back to check after the fact that explicit type the user
1515 /// wrote actually matches what the pre-defined option said.
1516 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1517 crate_context: &CrateCtxt<'a, 'tcx>,
1519 required_type: Ty<'tcx>,
1520 explicit_self: &ast::ExplicitSelf,
1521 body_id: ast::NodeId)
1523 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1524 let typ = crate_context.to_ty(rs, &**ast_type);
1525 let base_type = match typ.sty {
1526 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1527 ty::ty_uniq(typ) => typ,
1531 let body_scope = region::CodeExtent::from_node_id(body_id);
1533 // "Required type" comes from the trait definition. It may
1534 // contain late-bound regions from the method, but not the
1535 // trait (since traits only have early-bound region
1537 assert!(!base_type.has_regions_escaping_depth(1));
1538 let required_type_free =
1539 liberate_early_bound_regions(
1540 crate_context.tcx, body_scope,
1541 &ty::liberate_late_bound_regions(
1542 crate_context.tcx, body_scope, &ty::Binder(required_type)));
1544 // The "base type" comes from the impl. It too may have late-bound
1545 // regions from the method.
1546 assert!(!base_type.has_regions_escaping_depth(1));
1547 let base_type_free =
1548 liberate_early_bound_regions(
1549 crate_context.tcx, body_scope,
1550 &ty::liberate_late_bound_regions(
1551 crate_context.tcx, body_scope, &ty::Binder(base_type)));
1553 debug!("required_type={} required_type_free={} \
1554 base_type={} base_type_free={}",
1555 required_type.repr(crate_context.tcx),
1556 required_type_free.repr(crate_context.tcx),
1557 base_type.repr(crate_context.tcx),
1558 base_type_free.repr(crate_context.tcx));
1559 let infcx = infer::new_infer_ctxt(crate_context.tcx);
1560 drop(::require_same_types(crate_context.tcx,
1567 format!("mismatched self type: expected `{}`",
1568 ppaux::ty_to_string(crate_context.tcx, required_type))
1570 infcx.resolve_regions_and_report_errors(body_id);
1573 fn liberate_early_bound_regions<'tcx,T>(
1574 tcx: &ty::ctxt<'tcx>,
1575 scope: region::CodeExtent,
1578 where T : TypeFoldable<'tcx> + Repr<'tcx>
1581 * Convert early-bound regions into free regions; normally this is done by
1582 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1583 * method-self-type check is kind of hacky and done very early in the process,
1584 * before we really have a `ParameterEnvironment` to check.
1587 ty_fold::fold_regions(tcx, value, |region, _| {
1589 ty::ReEarlyBound(id, _, _, name) => {
1590 let def_id = local_def(id);
1591 ty::ReFree(ty::FreeRegion { scope: scope,
1592 bound_region: ty::BrNamed(def_id, name) })