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, ImplOrTraitItemContainer, TraitContainer};
41 use middle::ty::{Polytype};
43 use middle::ty_fold::TypeFolder;
44 use middle::typeck::astconv::{AstConv, ty_of_arg};
45 use middle::typeck::astconv::{ast_ty_to_ty, ast_region_to_region};
46 use middle::typeck::astconv;
47 use middle::typeck::infer;
48 use middle::typeck::rscope::*;
49 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
52 use util::ppaux::{Repr,UserString};
54 use std::collections::{HashMap, HashSet};
60 use syntax::ast_util::{local_def, PostExpansionMethod};
61 use syntax::codemap::Span;
62 use syntax::parse::token::{special_idents};
63 use syntax::parse::token;
64 use syntax::print::pprust::{path_to_string};
68 ///////////////////////////////////////////////////////////////////////////
71 pub fn collect_item_types(ccx: &CrateCtxt) {
72 fn collect_intrinsic_type(ccx: &CrateCtxt,
73 lang_item: ast::DefId) {
74 let ty::Polytype { ty: ty, .. } =
75 ccx.get_item_ty(lang_item);
76 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
79 match ccx.tcx.lang_items.ty_desc() {
80 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
82 match ccx.tcx.lang_items.opaque() {
83 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
86 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
87 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
89 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
90 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
93 ///////////////////////////////////////////////////////////////////////////
94 // First phase: just collect *trait definitions* -- basically, the set
95 // of type parameters and supertraits. This is information we need to
96 // know later when parsing field defs.
98 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
99 ccx: &'a CrateCtxt<'a, 'tcx>
102 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
103 fn visit_item(&mut self, i: &ast::Item) {
105 ast::ItemTrait(..) => {
106 // computing the trait def also fills in the table
107 let _ = trait_def_of_item(self.ccx, i);
112 visit::walk_item(self, i);
116 ///////////////////////////////////////////////////////////////////////////
117 // Second phase: collection proper.
119 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
120 ccx: &'a CrateCtxt<'a, 'tcx>
123 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
124 fn visit_item(&mut self, i: &ast::Item) {
125 convert(self.ccx, i);
126 visit::walk_item(self, i);
128 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
129 convert_foreign(self.ccx, i);
130 visit::walk_foreign_item(self, i);
134 ///////////////////////////////////////////////////////////////////////////
135 // Utility types and common code for the above passes.
138 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
141 impl<'a,'tcx> ToTy for ImplCtxt<'a,'tcx> {
142 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
143 ast_ty_to_ty(self, rs, ast_ty)
147 impl<'a,'tcx> ToTy for CrateCtxt<'a,'tcx> {
148 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
149 ast_ty_to_ty(self, rs, ast_ty)
153 impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
154 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
156 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
157 if id.krate != ast::LOCAL_CRATE {
158 return csearch::get_type(self.tcx, id)
161 match self.tcx.map.find(id.node) {
162 Some(ast_map::NodeItem(item)) => ty_of_item(self, &*item),
163 Some(ast_map::NodeForeignItem(foreign_item)) => {
164 let abi = self.tcx.map.get_foreign_abi(id.node);
165 ty_of_foreign_item(self, &*foreign_item, abi)
167 Some(ast_map::NodeTraitItem(trait_item)) => {
168 ty_of_trait_item(self, &*trait_item)
171 self.tcx.sess.bug(format!("unexpected sort of node \
172 in get_item_ty(): {:?}",
178 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
179 get_trait_def(self, id)
182 fn ty_infer(&self, span: Span) -> ty::t {
183 span_err!(self.tcx.sess, span, E0121,
184 "the type placeholder `_` is not allowed within types on item signatures.");
188 fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
193 fn associated_type_binding(&self,
199 self.tcx().sess.span_err(span, "associated types may not be \
205 pub fn get_enum_variant_types(ccx: &CrateCtxt,
207 variants: &[P<ast::Variant>],
208 generics: &ast::Generics) {
211 // Create a set of parameter types shared among all the variants.
212 for variant in variants.iter() {
213 // Nullary enum constructors get turned into constants; n-ary enum
214 // constructors get turned into functions.
215 let scope = variant.node.id;
216 let result_ty = match variant.node.kind {
217 ast::TupleVariantKind(ref args) if args.len() > 0 => {
218 let rs = ExplicitRscope;
219 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
220 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
223 ast::TupleVariantKind(_) => {
227 ast::StructVariantKind(ref struct_def) => {
229 generics: ty_generics_for_type(
232 DontCreateTypeParametersForAssociatedTypes),
236 convert_struct(ccx, &**struct_def, pty, variant.node.id);
238 let input_tys: Vec<_> = struct_def.fields.iter().map(
239 |f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
240 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
245 generics: ty_generics_for_type(
248 DontCreateTypeParametersForAssociatedTypes),
252 tcx.tcache.borrow_mut().insert(local_def(variant.node.id), pty);
254 write_ty_to_tcx(tcx, variant.node.id, result_ty);
258 fn collect_trait_methods(ccx: &CrateCtxt,
259 trait_id: ast::NodeId,
260 trait_def: &ty::TraitDef) {
262 match tcx.map.get(trait_id) {
263 ast_map::NodeItem(item) => {
265 ast::ItemTrait(_, _, _, ref trait_items) => {
266 // For each method, construct a suitable ty::Method and
267 // store it into the `tcx.impl_or_trait_items` table:
268 for trait_item in trait_items.iter() {
270 ast::RequiredMethod(_) |
271 ast::ProvidedMethod(_) => {
272 let ty_method = Rc::new(match *trait_item {
273 ast::RequiredMethod(ref m) => {
274 ty_method_of_trait_method(
278 trait_items.as_slice(),
287 ast::ProvidedMethod(ref m) => {
288 ty_method_of_trait_method(
292 trait_items.as_slice(),
295 m.pe_explicit_self(),
301 ast::TypeTraitItem(ref at) => {
302 tcx.sess.span_bug(at.span,
309 if ty_method.explicit_self ==
310 ty::StaticExplicitSelfCategory {
311 make_static_method_ty(ccx, &*ty_method);
314 tcx.impl_or_trait_items
316 .insert(ty_method.def_id,
317 ty::MethodTraitItem(ty_method));
319 ast::TypeTraitItem(ref ast_associated_type) => {
320 let trait_did = local_def(trait_id);
321 let associated_type = ty::AssociatedType {
322 ident: ast_associated_type.ident,
324 def_id: local_def(ast_associated_type.id),
325 container: TraitContainer(trait_did),
328 let trait_item = ty::TypeTraitItem(Rc::new(
330 tcx.impl_or_trait_items
332 .insert(associated_type.def_id,
338 // Add an entry mapping
339 let trait_item_def_ids =
340 Rc::new(trait_items.iter()
343 ast::RequiredMethod(ref ty_method) => {
344 ty::MethodTraitItemId(local_def(
347 ast::ProvidedMethod(ref method) => {
348 ty::MethodTraitItemId(local_def(
351 ast::TypeTraitItem(ref typedef) => {
352 ty::TypeTraitItemId(local_def(typedef.id))
357 let trait_def_id = local_def(trait_id);
358 tcx.trait_item_def_ids.borrow_mut()
359 .insert(trait_def_id, trait_item_def_ids);
361 _ => {} // Ignore things that aren't traits.
364 _ => { /* Ignore things that aren't traits */ }
367 fn make_static_method_ty(ccx: &CrateCtxt, m: &ty::Method) {
368 ccx.tcx.tcache.borrow_mut().insert(
371 generics: m.generics.clone(),
372 ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
375 fn ty_method_of_trait_method(ccx: &CrateCtxt,
376 trait_id: ast::NodeId,
377 trait_generics: &ty::Generics,
378 trait_items: &[ast::TraitItem],
380 m_ident: &ast::Ident,
381 m_explicit_self: &ast::ExplicitSelf,
383 m_generics: &ast::Generics,
384 m_fn_style: &ast::FnStyle,
385 m_decl: &ast::FnDecl)
388 ty_generics_for_fn_or_method(
391 (*trait_generics).clone(),
392 DontCreateTypeParametersForAssociatedTypes);
394 let (fty, explicit_self_category) = {
395 let tmcx = TraitMethodCtxt {
397 trait_id: local_def(trait_id),
398 trait_items: trait_items.as_slice(),
399 method_generics: &ty_generics,
401 let trait_self_ty = ty::mk_self_type(tmcx.tcx(),
402 local_def(trait_id));
403 astconv::ty_of_method(&tmcx,
416 explicit_self_category,
417 // assume public, because this is only invoked on trait methods
420 TraitContainer(local_def(trait_id)),
426 pub fn convert_field(ccx: &CrateCtxt,
427 struct_generics: &ty::Generics,
428 v: &ast::StructField,
429 origin: ast::DefId) -> ty::field_ty {
430 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
431 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
432 /* add the field to the tcache */
433 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
435 generics: struct_generics.clone(),
440 ast::NamedField(ident, visibility) => {
443 id: local_def(v.node.id),
448 ast::UnnamedField(visibility) => {
450 name: special_idents::unnamed_field.name,
451 id: local_def(v.node.id),
459 fn convert_associated_type(ccx: &CrateCtxt,
460 trait_def: &ty::TraitDef,
461 associated_type: &ast::AssociatedType)
463 // Find the type parameter ID corresponding to this
465 let type_parameter_def = trait_def.generics
467 .get_slice(subst::TypeSpace)
470 def.def_id == local_def(associated_type.id)
472 let type_parameter_def = match type_parameter_def {
473 Some(type_parameter_def) => type_parameter_def,
475 ccx.tcx().sess.span_bug(associated_type.span,
476 "`convert_associated_type()` didn't find \
477 a type parameter ID corresponding to \
481 let param_type = ty::mk_param(ccx.tcx,
483 type_parameter_def.index,
484 local_def(associated_type.id));
485 ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id),
487 generics: ty::Generics::empty(),
490 write_ty_to_tcx(ccx.tcx, associated_type.id, param_type);
492 let associated_type = Rc::new(ty::AssociatedType {
493 ident: associated_type.ident,
495 def_id: local_def(associated_type.id),
496 container: TraitContainer(trait_def.trait_ref.def_id),
501 .insert(associated_type.def_id,
502 ty::TypeTraitItem(associated_type));
505 generics: ty::Generics::empty(),
510 enum ConvertMethodContext<'a> {
511 /// Used when converting implementation methods.
512 ImplConvertMethodContext,
513 /// Used when converting method signatures. The def ID is the def ID of
514 /// the trait we're translating.
515 TraitConvertMethodContext(ast::DefId, &'a [ast::TraitItem]),
518 fn convert_methods<'a,I>(ccx: &CrateCtxt,
519 convert_method_context: ConvertMethodContext,
520 container: ImplOrTraitItemContainer,
522 untransformed_rcvr_ty: ty::t,
523 rcvr_ty_generics: &ty::Generics,
524 rcvr_visibility: ast::Visibility)
525 where I: Iterator<&'a ast::Method> {
526 debug!("convert_methods(untransformed_rcvr_ty={}, \
527 rcvr_ty_generics={})",
528 untransformed_rcvr_ty.repr(ccx.tcx),
529 rcvr_ty_generics.repr(ccx.tcx));
532 let mut seen_methods = HashSet::new();
534 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
535 tcx.sess.span_err(m.span, "duplicate method in trait impl");
538 let mty = Rc::new(ty_of_method(ccx,
539 convert_method_context,
542 untransformed_rcvr_ty,
545 let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
546 debug!("method {} (id {}) has type {}",
547 m.pe_ident().repr(tcx),
550 tcx.tcache.borrow_mut().insert(
553 generics: mty.generics.clone(),
557 write_ty_to_tcx(tcx, m.id, fty);
559 debug!("writing method type: def_id={} mty={}",
560 mty.def_id, mty.repr(ccx.tcx));
562 tcx.impl_or_trait_items
564 .insert(mty.def_id, ty::MethodTraitItem(mty));
567 fn ty_of_method(ccx: &CrateCtxt,
568 convert_method_context: ConvertMethodContext,
569 container: ImplOrTraitItemContainer,
571 untransformed_rcvr_ty: ty::t,
572 rcvr_ty_generics: &ty::Generics,
573 rcvr_visibility: ast::Visibility)
575 // FIXME(pcwalton): Hack until we have syntax in stage0 for snapshots.
576 let real_abi = match container {
577 ty::TraitContainer(trait_id) => {
578 if ccx.tcx.lang_items.fn_trait() == Some(trait_id) ||
579 ccx.tcx.lang_items.fn_mut_trait() == Some(trait_id) ||
580 ccx.tcx.lang_items.fn_once_trait() == Some(trait_id) {
590 ty_generics_for_fn_or_method(
593 (*rcvr_ty_generics).clone(),
594 CreateTypeParametersForAssociatedTypes);
596 let (fty, explicit_self_category) = match convert_method_context {
597 ImplConvertMethodContext => {
598 let imcx = ImplMethodCtxt {
600 method_generics: &m_ty_generics,
602 astconv::ty_of_method(&imcx,
605 untransformed_rcvr_ty,
606 m.pe_explicit_self(),
610 TraitConvertMethodContext(trait_id, trait_items) => {
611 let tmcx = TraitMethodCtxt {
614 trait_items: trait_items,
615 method_generics: &m_ty_generics,
617 astconv::ty_of_method(&tmcx,
620 untransformed_rcvr_ty,
621 m.pe_explicit_self(),
627 // if the method specifies a visibility, use that, otherwise
628 // inherit the visibility from the impl (so `foo` in `pub impl
629 // { fn foo(); }` is public, but private in `priv impl { fn
631 let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
633 ty::Method::new(m.pe_ident(),
636 explicit_self_category,
644 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
646 generics: &ast::Generics,
647 thing: &'static str) {
648 for ty_param in generics.ty_params.iter() {
649 let bounds = ty_param.bounds.iter();
650 let mut bounds = bounds.chain(ty_param.unbound.iter());
651 for bound in bounds {
653 ast::TraitTyParamBound(..) | ast::UnboxedFnTyParamBound(..) => {
654 // According to accepted RFC #XXX, we should
655 // eventually accept these, but it will not be
656 // part of this PR. Still, convert to warning to
657 // make bootstrapping easier.
658 span_warn!(ccx.tcx.sess, span, E0122,
659 "trait bounds are not (yet) enforced \
663 ast::RegionTyParamBound(..) => { }
669 fn is_associated_type_valid_for_param(ty: ty::t,
670 trait_id: ast::DefId,
671 generics: &ty::Generics)
673 match ty::get(ty).sty {
674 ty::ty_param(param_ty) => {
675 let type_parameter = generics.types.get(param_ty.space,
677 for trait_bound in type_parameter.bounds.trait_bounds.iter() {
678 if trait_bound.def_id == trait_id {
689 fn find_associated_type_in_generics(tcx: &ty::ctxt,
692 associated_type_id: ast::DefId,
693 generics: &ty::Generics)
697 tcx.sess.span_bug(span,
698 "find_associated_type_in_generics(): no self \
704 match ty::get(ty).sty {
705 ty::ty_param(ref param_ty) => {
706 /*let type_parameter = generics.types.get(param_ty.space,
708 let param_id = type_parameter.def_id;*/
709 let param_id = param_ty.def_id;
710 for type_parameter in generics.types.iter() {
711 if type_parameter.def_id == associated_type_id
712 && type_parameter.associated_with == Some(param_id) {
713 return ty::mk_param_from_def(tcx, type_parameter)
717 tcx.sess.span_bug(span,
718 "find_associated_type_in_generics(): didn't \
719 find associated type anywhere in the generics \
723 tcx.sess.span_bug(span,
724 "find_associated_type_in_generics(): self type \
731 fn type_is_self(ty: ty::t) -> bool {
732 match ty::get(ty).sty {
733 ty::ty_param(ref param_ty) if param_ty.is_self() => true,
738 struct ImplCtxt<'a,'tcx:'a> {
739 ccx: &'a CrateCtxt<'a,'tcx>,
740 opt_trait_ref_id: Option<ast::DefId>,
741 impl_items: &'a [ast::ImplItem],
742 impl_generics: &'a ty::Generics,
745 impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
746 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
750 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
751 self.ccx.get_item_ty(id)
754 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
755 self.ccx.get_trait_def(id)
758 fn ty_infer(&self, span: Span) -> ty::t {
759 self.ccx.ty_infer(span)
762 fn associated_types_of_trait_are_valid(&self,
764 trait_id: ast::DefId)
766 // OK if the trait with the associated type is the trait we're
768 match self.opt_trait_ref_id {
769 Some(trait_ref_id) if trait_ref_id == trait_id => {
770 if type_is_self(ty) {
777 // OK if the trait with the associated type is one of the traits in
779 is_associated_type_valid_for_param(ty, trait_id, self.impl_generics)
782 fn associated_type_binding(&self,
785 trait_id: ast::DefId,
786 associated_type_id: ast::DefId)
788 ensure_associated_types(self, trait_id);
789 let associated_type_ids = ty::associated_types_for_trait(self.ccx.tcx,
791 match self.opt_trait_ref_id {
792 Some(trait_ref_id) if trait_ref_id == trait_id => {
793 // It's an associated type on the trait that we're
795 let associated_type_id =
796 associated_type_ids.iter()
798 id.def_id == associated_type_id
800 .expect("associated_type_binding(): \
801 expected associated type ID \
803 let associated_type =
804 ty::impl_or_trait_item(self.ccx.tcx,
805 associated_type_id.def_id);
806 for impl_item in self.impl_items.iter() {
808 ast::MethodImplItem(_) => {}
809 ast::TypeImplItem(ref typedef) => {
810 if associated_type.ident().name == typedef.ident
812 return self.ccx.to_ty(&ExplicitRscope,
822 "ImplCtxt::associated_type_binding(): didn't \
823 find associated type")
828 // OK then, it should be an associated type on one of the traits in
830 find_associated_type_in_generics(self.ccx.tcx,
838 struct FnCtxt<'a,'tcx:'a> {
839 ccx: &'a CrateCtxt<'a,'tcx>,
840 generics: &'a ty::Generics,
843 impl<'a,'tcx> AstConv<'tcx> for FnCtxt<'a,'tcx> {
844 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
848 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
849 self.ccx.get_item_ty(id)
852 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
853 self.ccx.get_trait_def(id)
856 fn ty_infer(&self, span: Span) -> ty::t {
857 self.ccx.ty_infer(span)
860 fn associated_types_of_trait_are_valid(&self,
862 trait_id: ast::DefId)
864 // OK if the trait with the associated type is one of the traits in
866 is_associated_type_valid_for_param(ty, trait_id, self.generics)
869 fn associated_type_binding(&self,
873 associated_type_id: ast::DefId)
875 debug!("collect::FnCtxt::associated_type_binding()");
877 // The ID should map to an associated type on one of the traits in
879 find_associated_type_in_generics(self.ccx.tcx,
887 struct ImplMethodCtxt<'a,'tcx:'a> {
888 ccx: &'a CrateCtxt<'a,'tcx>,
889 method_generics: &'a ty::Generics,
892 impl<'a,'tcx> AstConv<'tcx> for ImplMethodCtxt<'a,'tcx> {
893 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
897 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
898 self.ccx.get_item_ty(id)
901 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
902 self.ccx.get_trait_def(id)
905 fn ty_infer(&self, span: Span) -> ty::t {
906 self.ccx.ty_infer(span)
909 fn associated_types_of_trait_are_valid(&self,
911 trait_id: ast::DefId)
913 is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
916 fn associated_type_binding(&self,
920 associated_type_id: ast::DefId)
922 debug!("collect::ImplMethodCtxt::associated_type_binding()");
924 // The ID should map to an associated type on one of the traits in
926 find_associated_type_in_generics(self.ccx.tcx,
930 self.method_generics)
934 struct TraitMethodCtxt<'a,'tcx:'a> {
935 ccx: &'a CrateCtxt<'a,'tcx>,
936 trait_id: ast::DefId,
937 trait_items: &'a [ast::TraitItem],
938 method_generics: &'a ty::Generics,
941 impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
942 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
946 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
947 self.ccx.get_item_ty(id)
950 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
951 self.ccx.get_trait_def(id)
954 fn ty_infer(&self, span: Span) -> ty::t {
955 self.ccx.ty_infer(span)
958 fn associated_types_of_trait_are_valid(&self,
960 trait_id: ast::DefId)
962 // OK if the trait with the associated type is this trait.
963 if self.trait_id == trait_id && type_is_self(ty) {
967 // OK if the trait with the associated type is one of the traits in
969 is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
972 fn associated_type_binding(&self,
975 trait_id: ast::DefId,
976 associated_type_id: ast::DefId)
978 debug!("collect::TraitMethodCtxt::associated_type_binding()");
980 // If this is one of our own associated types, return it.
981 if trait_id == self.trait_id {
983 for item in self.trait_items.iter() {
985 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
986 ast::TypeTraitItem(ref item) => {
987 if local_def(item.id) == associated_type_id {
988 return ty::mk_param(self.tcx(),
1001 "TraitMethodCtxt::associated_type_binding(): \
1002 didn't find associated type anywhere in the item \
1006 // The ID should map to an associated type on one of the traits in
1008 find_associated_type_in_generics(self.ccx.tcx,
1012 self.method_generics)
1016 struct GenericsCtxt<'a,AC:'a> {
1018 associated_types_generics: &'a ty::Generics,
1021 impl<'a,'tcx,AC:AstConv<'tcx>> AstConv<'tcx> for GenericsCtxt<'a,AC> {
1022 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
1026 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1027 self.chain.get_item_ty(id)
1030 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1031 self.chain.get_trait_def(id)
1034 fn ty_infer(&self, span: Span) -> ty::t {
1035 self.chain.ty_infer(span)
1038 fn associated_types_of_trait_are_valid(&self,
1040 trait_id: ast::DefId)
1042 // OK if the trait with the associated type is one of the traits in
1044 is_associated_type_valid_for_param(ty,
1046 self.associated_types_generics)
1049 fn associated_type_binding(&self,
1053 associated_type_id: ast::DefId)
1055 debug!("collect::GenericsCtxt::associated_type_binding()");
1057 // The ID should map to an associated type on one of the traits in
1059 find_associated_type_in_generics(self.chain.tcx(),
1063 self.associated_types_generics)
1067 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
1069 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
1071 // These don't define types.
1072 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
1073 ast::ItemEnum(ref enum_definition, ref generics) => {
1074 let pty = ty_of_item(ccx, it);
1075 write_ty_to_tcx(tcx, it.id, pty.ty);
1076 get_enum_variant_types(ccx,
1078 enum_definition.variants.as_slice(),
1081 ast::ItemImpl(ref generics,
1084 ref impl_items) => {
1085 // Create generics from the generics specified in the impl head.
1086 let ty_generics = ty_generics_for_type(
1089 CreateTypeParametersForAssociatedTypes);
1091 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
1092 write_ty_to_tcx(tcx, it.id, selfty);
1096 .insert(local_def(it.id),
1098 generics: ty_generics.clone(),
1102 // If there is a trait reference, treat the methods as always public.
1103 // This is to work around some incorrect behavior in privacy checking:
1104 // when the method belongs to a trait, it should acquire the privacy
1105 // from the trait, not the impl. Forcing the visibility to be public
1106 // makes things sorta work.
1107 let parent_visibility = if opt_trait_ref.is_some() {
1113 let icx = ImplCtxt {
1115 opt_trait_ref_id: match *opt_trait_ref {
1117 Some(ref ast_trait_ref) => {
1118 Some(lookup_def_tcx(tcx,
1119 ast_trait_ref.path.span,
1120 ast_trait_ref.ref_id).def_id())
1123 impl_items: impl_items.as_slice(),
1124 impl_generics: &ty_generics,
1127 let mut methods = Vec::new();
1128 for impl_item in impl_items.iter() {
1130 ast::MethodImplItem(ref method) => {
1131 check_method_self_type(ccx,
1132 &BindingRscope::new(method.id),
1134 method.pe_explicit_self());
1135 methods.push(&**method);
1137 ast::TypeImplItem(ref typedef) => {
1138 let typ = icx.to_ty(&ExplicitRscope, &*typedef.typ);
1141 .insert(local_def(typedef.id),
1143 generics: ty::Generics::empty(),
1146 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
1148 let associated_type = Rc::new(ty::AssociatedType {
1149 ident: typedef.ident,
1151 def_id: local_def(typedef.id),
1152 container: ty::ImplContainer(local_def(it.id)),
1154 tcx.impl_or_trait_items
1156 .insert(local_def(typedef.id),
1157 ty::TypeTraitItem(associated_type));
1162 convert_methods(ccx,
1163 ImplConvertMethodContext,
1164 ImplContainer(local_def(it.id)),
1165 methods.into_iter(),
1170 for trait_ref in opt_trait_ref.iter() {
1171 instantiate_trait_ref(&icx, trait_ref, selfty, None);
1174 ast::ItemTrait(_, _, _, ref trait_methods) => {
1175 let trait_def = trait_def_of_item(ccx, it);
1177 debug!("trait_def: ident={} trait_def={}",
1178 it.ident.repr(ccx.tcx),
1179 trait_def.repr(ccx.tcx()));
1181 for trait_method in trait_methods.iter() {
1182 let self_type = ty::mk_param(ccx.tcx,
1186 match *trait_method {
1187 ast::RequiredMethod(ref type_method) => {
1188 let rscope = BindingRscope::new(type_method.id);
1189 check_method_self_type(ccx,
1192 &type_method.explicit_self)
1194 ast::ProvidedMethod(ref method) => {
1195 check_method_self_type(ccx,
1196 &BindingRscope::new(method.id),
1198 method.pe_explicit_self())
1200 ast::TypeTraitItem(ref associated_type) => {
1201 convert_associated_type(ccx,
1203 &**associated_type);
1208 // Run convert_methods on the provided methods.
1209 let untransformed_rcvr_ty = ty::mk_self_type(tcx,
1211 let convert_method_context =
1212 TraitConvertMethodContext(local_def(it.id),
1213 trait_methods.as_slice());
1214 convert_methods(ccx,
1215 convert_method_context,
1216 TraitContainer(local_def(it.id)),
1217 trait_methods.iter().filter_map(|m| match *m {
1218 ast::RequiredMethod(_) => None,
1219 ast::ProvidedMethod(ref m) => Some(&**m),
1220 ast::TypeTraitItem(_) => None,
1222 untransformed_rcvr_ty,
1223 &trait_def.generics,
1226 // We need to do this *after* converting methods, since
1227 // convert_methods produces a tcache entry that is wrong for
1228 // static trait methods. This is somewhat unfortunate.
1229 collect_trait_methods(ccx, it.id, &*trait_def);
1231 ast::ItemStruct(ref struct_def, _) => {
1232 // Write the class type.
1233 let pty = ty_of_item(ccx, it);
1234 write_ty_to_tcx(tcx, it.id, pty.ty);
1236 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1238 // Write the super-struct type, if it exists.
1239 match struct_def.super_struct {
1241 let supserty = ccx.to_ty(&ExplicitRscope, &**ty);
1242 write_ty_to_tcx(tcx, it.id, supserty);
1247 convert_struct(ccx, &**struct_def, pty, it.id);
1249 ast::ItemTy(_, ref generics) => {
1250 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
1251 let tpt = ty_of_item(ccx, it);
1252 write_ty_to_tcx(tcx, it.id, tpt.ty);
1255 // This call populates the type cache with the converted type
1256 // of the item in passing. All we have to do here is to write
1257 // it into the node type table.
1258 let pty = ty_of_item(ccx, it);
1259 write_ty_to_tcx(tcx, it.id, pty.ty);
1264 pub fn convert_struct(ccx: &CrateCtxt,
1265 struct_def: &ast::StructDef,
1270 // Write the type of each of the members and check for duplicate fields.
1271 let mut seen_fields: HashMap<ast::Name, Span> = HashMap::new();
1272 let field_tys = struct_def.fields.iter().map(|f| {
1273 let result = convert_field(ccx, &pty.generics, f, local_def(id));
1275 if result.name != special_idents::unnamed_field.name {
1276 let dup = match seen_fields.find(&result.name) {
1277 Some(prev_span) => {
1278 span_err!(tcx.sess, f.span, E0124,
1279 "field `{}` is already declared",
1280 token::get_name(result.name));
1281 span_note!(tcx.sess, *prev_span, "previously declared here");
1286 // FIXME(#6393) this whole dup thing is just to satisfy
1287 // the borrow checker :-(
1289 seen_fields.insert(result.name, f.span);
1296 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1298 let super_struct = match struct_def.super_struct {
1299 Some(ref t) => match t.node {
1300 ast::TyPath(_, _, path_id) => {
1301 let def_map = tcx.def_map.borrow();
1302 match def_map.find(&path_id) {
1303 Some(&def::DefStruct(def_id)) => {
1304 // FIXME(#12511) Check for cycles in the inheritance hierarchy.
1305 // Check super-struct is virtual.
1306 match tcx.map.find(def_id.node) {
1307 Some(ast_map::NodeItem(i)) => match i.node {
1308 ast::ItemStruct(ref struct_def, _) => {
1309 if !struct_def.is_virtual {
1310 span_err!(tcx.sess, t.span, E0126,
1311 "struct inheritance is only \
1312 allowed from virtual structs");
1329 tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);
1331 let substs = mk_item_substs(ccx, &pty.generics);
1332 let selfty = ty::mk_struct(tcx, local_def(id), substs);
1334 // If this struct is enum-like or tuple-like, create the type of its
1336 match struct_def.ctor_id {
1339 if struct_def.fields.len() == 0 {
1341 write_ty_to_tcx(tcx, ctor_id, selfty);
1343 tcx.tcache.borrow_mut().insert(local_def(ctor_id), pty);
1344 } else if struct_def.fields.get(0).node.kind.is_unnamed() {
1346 let inputs: Vec<_> = struct_def.fields.iter().map(
1347 |field| tcx.tcache.borrow().get(
1348 &local_def(field.node.id)).ty).collect();
1349 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
1353 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1354 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
1356 generics: pty.generics,
1364 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
1365 // As above, this call populates the type table with the converted
1366 // type of the foreign item. We simply write it into the node type
1369 // For reasons I cannot fully articulate, I do so hate the AST
1370 // map, and I regard each time that I use it as a personal and
1371 // moral failing, but at the moment it seems like the only
1372 // convenient way to extract the ABI. - ndm
1373 let abi = ccx.tcx.map.get_foreign_abi(i.id);
1375 let pty = ty_of_foreign_item(ccx, i, abi);
1376 write_ty_to_tcx(ccx.tcx, i.id, pty.ty);
1378 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
1381 pub fn instantiate_trait_ref<'tcx,AC>(this: &AC,
1382 ast_trait_ref: &ast::TraitRef,
1384 associated_type: Option<ty::t>)
1386 where AC: AstConv<'tcx> {
1388 * Instantiates the path for the given trait reference, assuming that
1389 * it's bound to a valid trait type. Returns the def_id for the defining
1390 * trait. Fails if the type is a type other than a trait type.
1393 // FIXME(#5121) -- distinguish early vs late lifetime params
1394 let rscope = ExplicitRscope;
1396 match lookup_def_tcx(this.tcx(),
1397 ast_trait_ref.path.span,
1398 ast_trait_ref.ref_id) {
1399 def::DefTrait(trait_did) => {
1401 astconv::ast_path_to_trait_ref(this,
1406 &ast_trait_ref.path);
1408 this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
1413 this.tcx().sess.span_fatal(
1414 ast_trait_ref.path.span,
1415 format!("`{}` is not a trait",
1416 path_to_string(&ast_trait_ref.path)).as_slice());
1421 pub fn instantiate_unboxed_fn_ty<'tcx,AC>(this: &AC,
1422 unboxed_function: &ast::UnboxedFnTy,
1423 param_ty: ty::ParamTy)
1425 where AC: AstConv<'tcx> {
1426 let rscope = ExplicitRscope;
1427 let param_ty = param_ty.to_ty(this.tcx());
1428 Rc::new(astconv::trait_ref_for_unboxed_function(this,
1430 unboxed_function.kind,
1431 &*unboxed_function.decl,
1435 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
1436 if trait_id.krate != ast::LOCAL_CRATE {
1437 return ty::lookup_trait_def(ccx.tcx, trait_id)
1440 match ccx.tcx.map.get(trait_id.node) {
1441 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
1443 ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
1444 trait_id.node).as_slice())
1449 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
1450 let def_id = local_def(it.id);
1452 match tcx.trait_defs.borrow().find(&def_id) {
1453 Some(def) => return def.clone(),
1457 let (generics, unbound, bounds, items) = match it.node {
1458 ast::ItemTrait(ref generics,
1462 (generics, unbound, supertraits, items.as_slice())
1467 format!("trait_def_of_item invoked on {:?}", s).as_slice());
1471 let substs = mk_trait_substs(ccx, it.id, generics, items);
1473 let ty_generics = ty_generics_for_trait(ccx,
1479 let self_param_ty = ty::ParamTy::for_self(def_id);
1481 let bounds = compute_bounds(ccx, token::SELF_KEYWORD_NAME, self_param_ty,
1482 bounds.as_slice(), unbound, it.span,
1483 &generics.where_clause);
1485 let substs = mk_item_substs(ccx, &ty_generics);
1486 let trait_def = Rc::new(ty::TraitDef {
1487 generics: ty_generics,
1489 trait_ref: Rc::new(ty::TraitRef {
1494 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
1498 fn mk_trait_substs(ccx: &CrateCtxt,
1499 trait_id: ast::NodeId,
1500 generics: &ast::Generics,
1501 items: &[ast::TraitItem])
1503 // Creates a no-op substitution for the trait's type parameters.
1508 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
1514 // Start with the generics in the type parameters...
1515 let mut types: Vec<_> =
1519 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
1520 i, local_def(def.id)))
1523 // ...and add generics synthesized from the associated types.
1524 for item in items.iter() {
1526 ast::TypeTraitItem(ref trait_item) => {
1527 let index = types.len();
1528 types.push(ty::mk_param(ccx.tcx,
1531 local_def(trait_item.id)))
1533 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
1538 ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
1540 subst::Substs::new_trait(types, regions, self_ty)
1544 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
1546 let def_id = local_def(it.id);
1548 match tcx.tcache.borrow().find(&def_id) {
1549 Some(pty) => return pty.clone(),
1553 ast::ItemStatic(ref t, _, _) => {
1554 let typ = ccx.to_ty(&ExplicitRscope, &**t);
1555 let pty = no_params(typ);
1557 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1560 ast::ItemFn(ref decl, fn_style, abi, ref generics, _) => {
1561 let ty_generics = ty_generics_for_fn_or_method(
1564 ty::Generics::empty(),
1565 CreateTypeParametersForAssociatedTypes);
1569 generics: &ty_generics,
1571 astconv::ty_of_bare_fn(&fcx,
1577 let pty = Polytype {
1578 generics: ty_generics,
1579 ty: ty::mk_bare_fn(ccx.tcx, tofd)
1581 debug!("type of {} (id {}) is {}",
1582 token::get_ident(it.ident),
1586 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1589 ast::ItemTy(ref t, ref generics) => {
1590 match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
1591 Some(pty) => return pty.clone(),
1596 let ty = ccx.to_ty(&ExplicitRscope, &**t);
1598 generics: ty_generics_for_type(
1601 DontCreateTypeParametersForAssociatedTypes),
1606 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1609 ast::ItemEnum(_, ref generics) => {
1610 // Create a new generic polytype.
1611 let ty_generics = ty_generics_for_type(
1614 DontCreateTypeParametersForAssociatedTypes);
1615 let substs = mk_item_substs(ccx, &ty_generics);
1616 let t = ty::mk_enum(tcx, local_def(it.id), substs);
1617 let pty = Polytype {
1618 generics: ty_generics,
1622 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1625 ast::ItemTrait(..) => {
1626 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
1628 ast::ItemStruct(_, ref generics) => {
1629 let ty_generics = ty_generics_for_type(
1632 DontCreateTypeParametersForAssociatedTypes);
1633 let substs = mk_item_substs(ccx, &ty_generics);
1634 let t = ty::mk_struct(tcx, local_def(it.id), substs);
1635 let pty = Polytype {
1636 generics: ty_generics,
1640 tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
1643 ast::ItemImpl(..) | ast::ItemMod(_) |
1644 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
1648 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
1649 it: &ast::ForeignItem,
1650 abi: abi::Abi) -> ty::Polytype
1653 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1654 ty_of_foreign_fn_decl(ccx,
1660 ast::ForeignItemStatic(ref t, _) => {
1662 generics: ty::Generics::empty(),
1663 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1669 fn ty_of_trait_item(ccx: &CrateCtxt, trait_item: &ast::TraitItem)
1672 ast::RequiredMethod(ref m) => {
1673 ccx.tcx.sess.span_bug(m.span,
1674 "ty_of_trait_item() on required method")
1676 ast::ProvidedMethod(ref m) => {
1677 ccx.tcx.sess.span_bug(m.span,
1678 "ty_of_trait_item() on provided method")
1680 ast::TypeTraitItem(ref associated_type) => {
1681 let parent = ccx.tcx.map.get_parent(associated_type.id);
1682 let trait_def = match ccx.tcx.map.get(parent) {
1683 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
1685 ccx.tcx.sess.span_bug(associated_type.span,
1686 "associated type's parent wasn't \
1690 convert_associated_type(ccx, &*trait_def, &**associated_type)
1695 fn ty_generics_for_type(ccx: &CrateCtxt,
1696 generics: &ast::Generics,
1697 create_type_parameters_for_associated_types:
1698 CreateTypeParametersForAssociatedTypesFlag)
1702 generics.lifetimes.as_slice(),
1703 generics.ty_params.as_slice(),
1704 ty::Generics::empty(),
1705 &generics.where_clause,
1706 create_type_parameters_for_associated_types)
1709 fn ty_generics_for_trait(ccx: &CrateCtxt,
1710 trait_id: ast::NodeId,
1711 substs: &subst::Substs,
1712 generics: &ast::Generics,
1713 items: &[ast::TraitItem])
1718 generics.lifetimes.as_slice(),
1719 generics.ty_params.as_slice(),
1720 ty::Generics::empty(),
1721 &generics.where_clause,
1722 DontCreateTypeParametersForAssociatedTypes);
1724 // Add in type parameters for any associated types.
1725 for item in items.iter() {
1727 ast::TypeTraitItem(ref associated_type) => {
1728 let def = ty::TypeParameterDef {
1729 space: subst::TypeSpace,
1730 index: generics.types.len(subst::TypeSpace),
1731 ident: associated_type.ident,
1732 def_id: local_def(associated_type.id),
1733 bounds: ty::ParamBounds {
1734 builtin_bounds: ty::empty_builtin_bounds(),
1735 trait_bounds: Vec::new(),
1736 region_bounds: Vec::new(),
1738 associated_with: Some(local_def(trait_id)),
1741 ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.id,
1743 generics.types.push(subst::TypeSpace, def);
1745 ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
1749 // Add in the self type parameter.
1751 // Something of a hack: use the node id for the trait, also as
1752 // the node id for the Self type parameter.
1753 let param_id = trait_id;
1755 let self_trait_ref =
1756 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1757 substs: (*substs).clone() });
1759 let def = ty::TypeParameterDef {
1760 space: subst::SelfSpace,
1762 ident: special_idents::type_self,
1763 def_id: local_def(param_id),
1764 bounds: ty::ParamBounds {
1765 region_bounds: vec!(),
1766 builtin_bounds: ty::empty_builtin_bounds(),
1767 trait_bounds: vec!(self_trait_ref),
1769 associated_with: None,
1773 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1775 generics.types.push(subst::SelfSpace, def);
1780 fn ty_generics_for_fn_or_method<'tcx,AC>(
1782 generics: &ast::Generics,
1783 base_generics: ty::Generics,
1784 create_type_parameters_for_associated_types:
1785 CreateTypeParametersForAssociatedTypesFlag)
1787 where AC: AstConv<'tcx> {
1788 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1791 early_lifetimes.as_slice(),
1792 generics.ty_params.as_slice(),
1794 &generics.where_clause,
1795 create_type_parameters_for_associated_types)
1798 // Add the Sized bound, unless the type parameter is marked as `Sized?`.
1799 fn add_unsized_bound<'tcx,AC>(this: &AC,
1800 unbound: &Option<ast::TyParamBound>,
1801 bounds: &mut ty::BuiltinBounds,
1804 where AC: AstConv<'tcx> {
1805 let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
1807 &Some(ast::TraitTyParamBound(ref tpb)) => {
1808 // FIXME(#8559) currently requires the unbound to be built-in.
1809 let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
1811 Ok(kind_id) if trait_def_id != kind_id => {
1812 this.tcx().sess.span_warn(span,
1813 format!("default bound relaxed \
1814 for a {}, but this \
1815 does nothing because \
1816 the given bound is not \
1821 ty::try_add_builtin_trait(this.tcx(),
1828 _ if kind_id.is_ok() => {
1829 ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
1831 // No lang item for Sized, so we can't add it as a bound.
1836 #[deriving(Clone, PartialEq, Eq)]
1837 enum CreateTypeParametersForAssociatedTypesFlag {
1838 DontCreateTypeParametersForAssociatedTypes,
1839 CreateTypeParametersForAssociatedTypes,
1842 fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
1843 where AC: AstConv<'tcx> {
1844 if this.tcx().trait_associated_types.borrow().contains_key(&trait_id) {
1848 if trait_id.krate == ast::LOCAL_CRATE {
1849 match this.tcx().map.find(trait_id.node) {
1850 Some(ast_map::NodeItem(item)) => {
1852 ast::ItemTrait(_, _, _, ref trait_items) => {
1853 let mut result = Vec::new();
1855 for trait_item in trait_items.iter() {
1857 ast::RequiredMethod(_) |
1858 ast::ProvidedMethod(_) => {}
1859 ast::TypeTraitItem(ref associated_type) => {
1860 let info = ty::AssociatedTypeInfo {
1861 def_id: local_def(associated_type.id),
1863 ident: associated_type.ident,
1871 .trait_associated_types
1873 .insert(trait_id, Rc::new(result));
1877 this.tcx().sess.bug("ensure_associated_types() \
1878 called on non-trait")
1883 this.tcx().sess.bug("ensure_associated_types() called on \
1890 // Cross-crate case.
1891 let mut result = Vec::new();
1893 let trait_items = ty::trait_items(this.tcx(), trait_id);
1894 for trait_item in trait_items.iter() {
1896 ty::MethodTraitItem(_) => {}
1897 ty::TypeTraitItem(ref associated_type) => {
1898 let info = ty::AssociatedTypeInfo {
1899 def_id: associated_type.def_id,
1901 ident: associated_type.ident
1908 this.tcx().trait_associated_types.borrow_mut().insert(trait_id,
1912 fn ty_generics<'tcx,AC>(this: &AC,
1913 space: subst::ParamSpace,
1914 lifetime_defs: &[ast::LifetimeDef],
1915 types: &[ast::TyParam],
1916 base_generics: ty::Generics,
1917 where_clause: &ast::WhereClause,
1918 create_type_parameters_for_associated_types:
1919 CreateTypeParametersForAssociatedTypesFlag)
1921 where AC: AstConv<'tcx> {
1922 let mut result = base_generics;
1924 for (i, l) in lifetime_defs.iter().enumerate() {
1925 let bounds = l.bounds.iter()
1926 .map(|l| ast_region_to_region(this.tcx(), l))
1928 let def = ty::RegionParameterDef { name: l.lifetime.name,
1931 def_id: local_def(l.lifetime.id),
1933 debug!("ty_generics: def for region param: {}", def);
1934 result.regions.push(space, def);
1937 assert!(result.types.is_empty_in(space));
1939 // First, create the virtual type parameters for associated types if
1941 let mut associated_types_generics = ty::Generics::empty();
1942 match create_type_parameters_for_associated_types {
1943 DontCreateTypeParametersForAssociatedTypes => {}
1944 CreateTypeParametersForAssociatedTypes => {
1946 for param in types.iter() {
1947 for bound in param.bounds.iter() {
1949 ast::TraitTyParamBound(ref trait_bound) => {
1950 match lookup_def_tcx(this.tcx(),
1951 trait_bound.path.span,
1952 trait_bound.ref_id) {
1953 def::DefTrait(trait_did) => {
1954 ensure_associated_types(this, trait_did);
1955 let associated_types =
1956 ty::associated_types_for_trait(
1959 for associated_type_info in
1960 associated_types.iter() {
1961 let associated_type_trait_item =
1962 ty::impl_or_trait_item(
1964 associated_type_info.def_id);
1965 let def = ty::TypeParameterDef {
1966 ident: associated_type_trait_item
1969 associated_type_info.def_id,
1971 index: types.len() + index,
1972 bounds: ty::ParamBounds {
1974 ty::empty_builtin_bounds(),
1975 trait_bounds: Vec::new(),
1976 region_bounds: Vec::new(),
1979 Some(local_def(param.id))
1983 associated_types_generics.types
1990 this.tcx().sess.span_bug(trait_bound.path
2003 // Now create the real type parameters.
2004 let gcx = GenericsCtxt {
2006 associated_types_generics: &associated_types_generics,
2008 for (i, param) in types.iter().enumerate() {
2009 let def = get_or_create_type_parameter_def(&gcx,
2014 debug!("ty_generics: def for type param: {}, {}",
2015 def.repr(this.tcx()),
2017 result.types.push(space, def);
2020 // Append the associated types to the result.
2021 for associated_type_param in associated_types_generics.types
2024 assert!(result.types.get_slice(space).len() ==
2025 associated_type_param.index);
2026 debug!("ty_generics: def for associated type: {}, {}",
2027 associated_type_param.repr(this.tcx()),
2029 result.types.push(space, (*associated_type_param).clone());
2034 fn get_or_create_type_parameter_def<'tcx,AC>(
2036 space: subst::ParamSpace,
2037 param: &ast::TyParam,
2039 where_clause: &ast::WhereClause)
2040 -> ty::TypeParameterDef
2041 where AC: AstConv<'tcx> {
2042 match this.tcx().ty_param_defs.borrow().find(¶m.id) {
2043 Some(d) => { return (*d).clone(); }
2047 let param_ty = ty::ParamTy::new(space, index, local_def(param.id));
2048 let bounds = compute_bounds(this,
2051 param.bounds.as_slice(),
2055 let default = match param.default {
2058 let ty = ast_ty_to_ty(this, &ExplicitRscope, &**path);
2059 let cur_idx = index;
2061 ty::walk_ty(ty, |t| {
2062 match ty::get(t).sty {
2063 ty::ty_param(p) => if p.idx > cur_idx {
2064 span_err!(this.tcx().sess, path.span, E0128,
2065 "type parameters with a default cannot use \
2066 forward declared identifiers");
2076 let def = ty::TypeParameterDef {
2080 def_id: local_def(param.id),
2081 associated_with: None,
2086 this.tcx().ty_param_defs.borrow_mut().insert(param.id, def.clone());
2092 fn compute_bounds<'tcx,AC>(this: &AC,
2093 name_of_bounded_thing: ast::Name,
2094 param_ty: ty::ParamTy,
2095 ast_bounds: &[ast::TyParamBound],
2096 unbound: &Option<ast::TyParamBound>,
2098 where_clause: &ast::WhereClause)
2100 where AC: AstConv<'tcx> {
2102 * Translate the AST's notion of ty param bounds (which are an
2103 * enum consisting of a newtyped Ty or a region) to ty's
2104 * notion of ty param bounds, which can either be user-defined
2105 * traits, or the built-in trait (formerly known as kind): Send.
2108 let mut param_bounds = conv_param_bounds(this,
2115 add_unsized_bound(this,
2117 &mut param_bounds.builtin_bounds,
2121 check_bounds_compatible(this.tcx(),
2122 name_of_bounded_thing,
2126 param_bounds.trait_bounds.sort_by(|a,b| a.def_id.cmp(&b.def_id));
2131 fn check_bounds_compatible(tcx: &ty::ctxt,
2132 name_of_bounded_thing: ast::Name,
2133 param_bounds: &ty::ParamBounds,
2135 // Currently the only bound which is incompatible with other bounds is
2137 if !param_bounds.builtin_bounds.contains_elem(ty::BoundSized) {
2138 ty::each_bound_trait_and_supertraits(
2140 param_bounds.trait_bounds.as_slice(),
2142 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
2143 if trait_def.bounds.builtin_bounds.contains_elem(ty::BoundSized) {
2144 span_err!(tcx.sess, span, E0129,
2145 "incompatible bounds on type parameter `{}`, \
2146 bound `{}` does not allow unsized type",
2147 name_of_bounded_thing.user_string(tcx),
2148 ppaux::trait_ref_to_string(tcx, &*trait_ref));
2155 fn conv_param_bounds<'tcx,AC>(this: &AC,
2157 param_ty: ty::ParamTy,
2158 ast_bounds: &[ast::TyParamBound],
2159 where_clause: &ast::WhereClause)
2161 where AC: AstConv<'tcx> {
2163 merge_param_bounds(this.tcx(), param_ty, ast_bounds, where_clause);
2164 let astconv::PartitionedBounds { builtin_bounds,
2167 unboxed_fn_ty_bounds } =
2168 astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
2170 let unboxed_fn_ty_bounds = unboxed_fn_ty_bounds.move_iter().map(|b| {
2171 let trait_id = this.tcx().def_map.borrow().get(&b.ref_id).def_id();
2172 let mut kind = None;
2173 for &(lang_item, this_kind) in [
2174 (this.tcx().lang_items.fn_trait(), ast::FnUnboxedClosureKind),
2175 (this.tcx().lang_items.fn_mut_trait(),
2176 ast::FnMutUnboxedClosureKind),
2177 (this.tcx().lang_items.fn_once_trait(),
2178 ast::FnOnceUnboxedClosureKind)
2180 if Some(trait_id) == lang_item {
2181 kind = Some(this_kind);
2186 let kind = match kind {
2189 this.tcx().sess.span_err(b.path.span,
2190 "unboxed function trait must be one \
2191 of `Fn`, `FnMut`, or `FnOnce`");
2192 ast::FnMutUnboxedClosureKind
2196 let rscope = ExplicitRscope;
2197 let param_ty = param_ty.to_ty(this.tcx());
2198 Rc::new(astconv::trait_ref_for_unboxed_function(this,
2205 let trait_bounds: Vec<Rc<ty::TraitRef>> =
2206 trait_bounds.into_iter()
2208 instantiate_trait_ref(this,
2210 param_ty.to_ty(this.tcx()),
2211 Some(param_ty.to_ty(this.tcx())))
2213 .chain(unboxed_fn_ty_bounds)
2215 let region_bounds: Vec<ty::Region> =
2216 region_bounds.move_iter()
2217 .map(|r| ast_region_to_region(this.tcx(), r))
2220 region_bounds: region_bounds,
2221 builtin_bounds: builtin_bounds,
2222 trait_bounds: trait_bounds,
2226 fn merge_param_bounds<'a>(tcx: &ty::ctxt,
2227 param_ty: ty::ParamTy,
2228 ast_bounds: &'a [ast::TyParamBound],
2229 where_clause: &'a ast::WhereClause)
2230 -> Vec<&'a ast::TyParamBound> {
2232 * Merges the bounds declared on a type parameter with those
2233 * found from where clauses into a single list.
2236 let mut result = Vec::new();
2238 for ast_bound in ast_bounds.iter() {
2239 result.push(ast_bound);
2242 for predicate in where_clause.predicates.iter() {
2243 let predicate_param_id =
2246 .find(&predicate.id)
2247 .expect("compute_bounds(): resolve didn't resolve the type \
2248 parameter identifier in a `where` clause")
2250 if param_ty.def_id != predicate_param_id {
2253 for bound in predicate.bounds.iter() {
2261 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
2264 ast_generics: &ast::Generics,
2267 for i in decl.inputs.iter() {
2268 match (*i).pat.node {
2269 ast::PatIdent(_, _, _) => (),
2270 ast::PatWild(ast::PatWildSingle) => (),
2272 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2273 "patterns aren't allowed in foreign function declarations");
2278 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(
2281 ty::Generics::empty(),
2282 DontCreateTypeParametersForAssociatedTypes);
2283 let rb = BindingRscope::new(def_id.node);
2284 let input_tys = decl.inputs
2286 .map(|a| ty_of_arg(ccx, &rb, a, None))
2289 let output_ty = ast_ty_to_ty(ccx, &rb, &*decl.output);
2291 let t_fn = ty::mk_bare_fn(
2295 fn_style: ast::UnsafeFn,
2296 sig: ty::FnSig {binder_id: def_id.node,
2299 variadic: decl.variadic}
2301 let pty = Polytype {
2302 generics: ty_generics_for_fn_or_method,
2306 ccx.tcx.tcache.borrow_mut().insert(def_id, pty.clone());
2310 pub fn mk_item_substs(ccx: &CrateCtxt,
2311 ty_generics: &ty::Generics)
2315 ty_generics.types.map(
2316 |def| ty::mk_param_from_def(ccx.tcx, def));
2319 ty_generics.regions.map(
2320 |def| ty::ReEarlyBound(def.def_id.node, def.space,
2321 def.index, def.name));
2323 subst::Substs::new(types, regions)
2326 /// Verifies that the explicit self type of a method matches the impl or
2328 fn check_method_self_type<RS:RegionScope>(
2329 crate_context: &CrateCtxt,
2331 required_type: ty::t,
2332 explicit_self: &ast::ExplicitSelf) {
2333 match explicit_self.node {
2334 ast::SelfExplicit(ref ast_type, _) => {
2335 let typ = crate_context.to_ty(rs, &**ast_type);
2336 let base_type = match ty::get(typ).sty {
2337 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
2338 ty::ty_uniq(typ) => typ,
2341 let infcx = infer::new_infer_ctxt(crate_context.tcx);
2342 drop(typeck::require_same_types(crate_context.tcx,
2349 format!("mismatched self type: expected `{}`",
2350 ppaux::ty_to_string(crate_context.tcx, required_type))
2352 infcx.resolve_regions_and_report_errors();