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, TypeSpace};
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};
50 use std::collections::HashSet;
56 use syntax::ast_util::{local_def, PostExpansionMethod};
57 use syntax::codemap::Span;
58 use syntax::parse::token::{special_idents};
59 use syntax::parse::token;
63 ///////////////////////////////////////////////////////////////////////////
66 pub fn collect_item_types(tcx: &ty::ctxt) {
67 let ccx = &CollectCtxt { tcx: tcx };
69 match ccx.tcx.lang_items.ty_desc() {
70 Some(id) => { collect_intrinsic_type(ccx, id); }
73 match ccx.tcx.lang_items.opaque() {
74 Some(id) => { collect_intrinsic_type(ccx, id); }
78 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
79 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
81 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
82 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
85 ///////////////////////////////////////////////////////////////////////////
87 struct CollectCtxt<'a,'tcx:'a> {
88 tcx: &'a ty::ctxt<'tcx>,
91 ///////////////////////////////////////////////////////////////////////////
92 // Zeroth phase: collect types of intrinsics
94 fn collect_intrinsic_type(ccx: &CollectCtxt,
95 lang_item: ast::DefId) {
96 let ty::TypeScheme { ty, .. } =
97 ccx.get_item_type_scheme(lang_item);
98 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
101 ///////////////////////////////////////////////////////////////////////////
102 // First phase: just collect *trait definitions* -- basically, the set
103 // of type parameters and supertraits. This is information we need to
104 // know later when parsing field defs.
106 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
107 ccx: &'a CollectCtxt<'a, 'tcx>
110 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
111 fn visit_item(&mut self, i: &ast::Item) {
113 ast::ItemTrait(..) => {
114 // computing the trait def also fills in the table
115 let _ = trait_def_of_item(self.ccx, i);
120 visit::walk_item(self, i);
124 ///////////////////////////////////////////////////////////////////////////
125 // Second phase: collection proper.
127 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
128 ccx: &'a CollectCtxt<'a, 'tcx>
131 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
132 fn visit_item(&mut self, i: &ast::Item) {
133 convert(self.ccx, i);
134 visit::walk_item(self, i);
136 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
137 convert_foreign(self.ccx, i);
138 visit::walk_foreign_item(self, i);
142 ///////////////////////////////////////////////////////////////////////////
143 // Utility types and common code for the above passes.
145 pub trait ToTy<'tcx> {
146 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
149 impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
150 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
151 ast_ty_to_ty(self, rs, ast_ty)
155 impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
156 fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
158 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
159 if id.krate != ast::LOCAL_CRATE {
160 return csearch::get_type(self.tcx, id)
163 match self.tcx.map.find(id.node) {
164 Some(ast_map::NodeItem(item)) => {
165 ty_of_item(self, &*item)
167 Some(ast_map::NodeForeignItem(foreign_item)) => {
168 let abi = self.tcx.map.get_foreign_abi(id.node);
169 ty_of_foreign_item(self, &*foreign_item, abi)
172 self.tcx.sess.bug(format!("unexpected sort of node \
173 in get_item_type_scheme(): {:?}",
179 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
180 get_trait_def(self, id)
183 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
184 span_err!(self.tcx.sess, span, E0121,
185 "the type placeholder `_` is not allowed within types on item signatures");
189 fn projected_ty(&self,
191 trait_ref: Rc<ty::TraitRef<'tcx>>,
192 item_name: ast::Name)
195 ty::mk_projection(self.tcx, trait_ref, item_name)
199 fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
201 variants: &[P<ast::Variant>],
202 generics: &ast::Generics) {
205 // Create a set of parameter types shared among all the variants.
206 for variant in variants.iter() {
207 let variant_def_id = local_def(variant.node.id);
209 // Nullary enum constructors get turned into constants; n-ary enum
210 // constructors get turned into functions.
211 let result_ty = match variant.node.kind {
212 ast::TupleVariantKind(ref args) if args.len() > 0 => {
213 let rs = ExplicitRscope;
214 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
215 ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[], enum_ty)
218 ast::TupleVariantKind(_) => {
222 ast::StructVariantKind(ref struct_def) => {
223 let scheme = TypeScheme {
224 generics: ty_generics_for_type_or_impl(ccx, generics),
228 convert_struct(ccx, &**struct_def, scheme, variant.node.id);
233 let scheme = TypeScheme {
234 generics: ty_generics_for_type_or_impl(ccx, generics),
238 tcx.tcache.borrow_mut().insert(variant_def_id, scheme);
240 write_ty_to_tcx(tcx, variant.node.id, result_ty);
244 fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
245 trait_id: ast::NodeId,
246 trait_def: &ty::TraitDef<'tcx>) {
248 if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
249 if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
250 // For each method, construct a suitable ty::Method and
251 // store it into the `tcx.impl_or_trait_items` table:
252 for trait_item in trait_items.iter() {
254 ast::RequiredMethod(_) |
255 ast::ProvidedMethod(_) => {
256 let ty_method = Rc::new(match *trait_item {
257 ast::RequiredMethod(ref m) => {
258 ty_method_of_trait_method(
271 ast::ProvidedMethod(ref m) => {
272 ty_method_of_trait_method(
279 m.pe_explicit_self(),
285 ast::TypeTraitItem(ref at) => {
286 tcx.sess.span_bug(at.ty_param.span,
287 "there shouldn't be a type trait item here")
291 debug!("ty_method_of_trait_method yielded {} for method {} of trait {}",
292 ty_method.repr(ccx.tcx),
293 trait_item.repr(ccx.tcx),
294 local_def(trait_id).repr(ccx.tcx));
296 make_method_ty(ccx, &*ty_method);
298 tcx.impl_or_trait_items
300 .insert(ty_method.def_id, ty::MethodTraitItem(ty_method));
302 ast::TypeTraitItem(ref ast_associated_type) => {
303 let trait_did = local_def(trait_id);
304 let associated_type = ty::AssociatedType {
305 name: ast_associated_type.ty_param.ident.name,
307 def_id: local_def(ast_associated_type.ty_param.id),
308 container: TraitContainer(trait_did),
311 let trait_item = ty::TypeTraitItem(Rc::new(associated_type));
312 tcx.impl_or_trait_items
314 .insert(associated_type.def_id, trait_item);
319 // Add an entry mapping
320 let trait_item_def_ids =
321 Rc::new(trait_items.iter().map(|ti| {
323 ast::RequiredMethod(ref ty_method) => {
324 ty::MethodTraitItemId(local_def(ty_method.id))
326 ast::ProvidedMethod(ref method) => {
327 ty::MethodTraitItemId(local_def(method.id))
329 ast::TypeTraitItem(ref typedef) => {
330 ty::TypeTraitItemId(local_def(typedef.ty_param.id))
335 let trait_def_id = local_def(trait_id);
336 tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids);
340 fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
341 ccx.tcx.tcache.borrow_mut().insert(
344 generics: m.generics.clone(),
345 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
348 fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
349 trait_id: ast::NodeId,
350 trait_generics: &ty::Generics<'tcx>,
351 _trait_items: &[ast::TraitItem],
354 m_explicit_self: &ast::ExplicitSelf,
356 m_generics: &ast::Generics,
357 m_unsafety: &ast::Unsafety,
358 m_decl: &ast::FnDecl)
359 -> ty::Method<'tcx> {
361 ty_generics_for_fn_or_method(
364 (*trait_generics).clone());
366 let (fty, explicit_self_category) = {
367 let trait_self_ty = ty::mk_self_type(ccx.tcx);
368 astconv::ty_of_method(ccx,
380 explicit_self_category,
381 // assume public, because this is only invoked on trait methods
384 TraitContainer(local_def(trait_id)),
390 fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
391 struct_generics: &ty::Generics<'tcx>,
392 v: &ast::StructField,
393 origin: ast::DefId) -> ty::field_ty {
394 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
395 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
396 /* add the field to the tcache */
397 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
399 generics: struct_generics.clone(),
404 ast::NamedField(ident, visibility) => {
407 id: local_def(v.node.id),
412 ast::UnnamedField(visibility) => {
414 name: special_idents::unnamed_field.name,
415 id: local_def(v.node.id),
423 fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
424 trait_def: &ty::TraitDef<'tcx>,
425 associated_type: &ast::AssociatedType)
427 let associated_type = Rc::new(ty::AssociatedType {
428 name: associated_type.ty_param.ident.name,
430 def_id: local_def(associated_type.ty_param.id),
431 container: TraitContainer(trait_def.trait_ref.def_id),
436 .insert(associated_type.def_id,
437 ty::TypeTraitItem(associated_type));
440 fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
441 container: ImplOrTraitItemContainer,
443 untransformed_rcvr_ty: Ty<'tcx>,
444 rcvr_ty_generics: &ty::Generics<'tcx>,
445 rcvr_visibility: ast::Visibility)
446 where I: Iterator<Item=&'i ast::Method> {
447 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
448 untransformed_rcvr_ty.repr(ccx.tcx),
449 rcvr_ty_generics.repr(ccx.tcx));
452 let mut seen_methods = FnvHashSet::new();
454 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
455 tcx.sess.span_err(m.span, "duplicate method in trait impl");
458 let m_def_id = local_def(m.id);
459 let mty = Rc::new(ty_of_method(ccx,
462 untransformed_rcvr_ty,
465 let fty = ty::mk_bare_fn(tcx, Some(m_def_id), tcx.mk_bare_fn(mty.fty.clone()));
466 debug!("method {} (id {}) has type {}",
467 m.pe_ident().repr(tcx),
470 tcx.tcache.borrow_mut().insert(
473 generics: mty.generics.clone(),
477 write_ty_to_tcx(tcx, m.id, fty);
479 debug!("writing method type: def_id={:?} mty={}",
480 mty.def_id, mty.repr(ccx.tcx));
482 tcx.impl_or_trait_items
484 .insert(mty.def_id, ty::MethodTraitItem(mty));
487 fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
488 container: ImplOrTraitItemContainer,
490 untransformed_rcvr_ty: Ty<'tcx>,
491 rcvr_ty_generics: &ty::Generics<'tcx>,
492 rcvr_visibility: ast::Visibility)
493 -> ty::Method<'tcx> {
495 ty_generics_for_fn_or_method(
498 (*rcvr_ty_generics).clone());
500 let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
502 untransformed_rcvr_ty,
503 m.pe_explicit_self(),
507 // if the method specifies a visibility, use that, otherwise
508 // inherit the visibility from the impl (so `foo` in `pub impl
509 // { fn foo(); }` is public, but private in `priv impl { fn
511 let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
513 ty::Method::new(m.pe_ident().name,
516 explicit_self_category,
524 fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
526 generics: &ast::Generics,
527 thing: &'static str) {
528 let mut warn = false;
530 for ty_param in generics.ty_params.iter() {
531 for bound in ty_param.bounds.iter() {
533 ast::TraitTyParamBound(..) => {
536 ast::RegionTyParamBound(..) => { }
542 // According to accepted RFC #XXX, we should
543 // eventually accept these, but it will not be
544 // part of this PR. Still, convert to warning to
545 // make bootstrapping easier.
546 span_warn!(ccx.tcx.sess, span, E0122,
547 "trait bounds are not (yet) enforced \
553 fn convert(ccx: &CollectCtxt, it: &ast::Item) {
555 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
557 // These don't define types.
558 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
559 ast::ItemEnum(ref enum_definition, ref generics) => {
560 let scheme = ty_of_item(ccx, it);
561 write_ty_to_tcx(tcx, it.id, scheme.ty);
562 get_enum_variant_types(ccx,
564 enum_definition.variants.as_slice(),
572 // Create generics from the generics specified in the impl head.
573 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
575 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
576 write_ty_to_tcx(tcx, it.id, selfty);
580 .insert(local_def(it.id),
582 generics: ty_generics.clone(),
586 // If there is a trait reference, treat the methods as always public.
587 // This is to work around some incorrect behavior in privacy checking:
588 // when the method belongs to a trait, it should acquire the privacy
589 // from the trait, not the impl. Forcing the visibility to be public
590 // makes things sorta work.
591 let parent_visibility = if opt_trait_ref.is_some() {
597 let mut methods = Vec::new();
598 for impl_item in impl_items.iter() {
600 ast::MethodImplItem(ref method) => {
601 let body_id = method.pe_body().id;
602 check_method_self_type(ccx,
603 &BindingRscope::new(),
605 method.pe_explicit_self(),
607 methods.push(&**method);
609 ast::TypeImplItem(ref typedef) => {
610 if opt_trait_ref.is_none() {
611 tcx.sess.span_err(typedef.span,
612 "associated items are not allowed in inherent impls");
615 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
618 .insert(local_def(typedef.id),
620 generics: ty::Generics::empty(),
623 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
625 let associated_type = Rc::new(ty::AssociatedType {
626 name: typedef.ident.name,
628 def_id: local_def(typedef.id),
629 container: ty::ImplContainer(local_def(it.id)),
631 tcx.impl_or_trait_items
633 .insert(local_def(typedef.id),
634 ty::TypeTraitItem(associated_type));
640 ImplContainer(local_def(it.id)),
646 for trait_ref in opt_trait_ref.iter() {
647 astconv::instantiate_trait_ref(ccx,
654 enforce_impl_ty_params_are_constrained(ccx.tcx,
658 ast::ItemTrait(_, _, _, ref trait_methods) => {
659 let trait_def = trait_def_of_item(ccx, it);
661 debug!("trait_def: ident={} trait_def={}",
662 it.ident.repr(ccx.tcx),
663 trait_def.repr(ccx.tcx));
665 for trait_method in trait_methods.iter() {
666 let self_type = ty::mk_self_type(tcx);
667 match *trait_method {
668 ast::RequiredMethod(ref type_method) => {
669 let rscope = BindingRscope::new();
670 check_method_self_type(ccx,
673 &type_method.explicit_self,
676 ast::ProvidedMethod(ref method) => {
677 check_method_self_type(ccx,
678 &BindingRscope::new(),
680 method.pe_explicit_self(),
683 ast::TypeTraitItem(ref associated_type) => {
684 convert_associated_type(ccx,
691 // Run convert_methods on the provided methods.
692 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
694 TraitContainer(local_def(it.id)),
695 trait_methods.iter().filter_map(|m| match *m {
696 ast::RequiredMethod(_) => None,
697 ast::ProvidedMethod(ref m) => Some(&**m),
698 ast::TypeTraitItem(_) => None,
700 untransformed_rcvr_ty,
704 // We need to do this *after* converting methods, since
705 // convert_methods produces a tcache entry that is wrong for
706 // static trait methods. This is somewhat unfortunate.
707 collect_trait_methods(ccx, it.id, &*trait_def);
709 ast::ItemStruct(ref struct_def, _) => {
710 // Write the class type.
711 let scheme = ty_of_item(ccx, it);
712 write_ty_to_tcx(tcx, it.id, scheme.ty);
714 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
716 convert_struct(ccx, &**struct_def, scheme, it.id);
718 ast::ItemTy(_, ref generics) => {
719 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
720 let tpt = ty_of_item(ccx, it);
721 write_ty_to_tcx(tcx, it.id, tpt.ty);
724 // This call populates the type cache with the converted type
725 // of the item in passing. All we have to do here is to write
726 // it into the node type table.
727 let scheme = ty_of_item(ccx, it);
728 write_ty_to_tcx(tcx, it.id, scheme.ty);
733 fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
734 struct_def: &ast::StructDef,
735 scheme: ty::TypeScheme<'tcx>,
739 // Write the type of each of the members and check for duplicate fields.
740 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap::new();
741 let field_tys = struct_def.fields.iter().map(|f| {
742 let result = convert_field(ccx, &scheme.generics, f, local_def(id));
744 if result.name != special_idents::unnamed_field.name {
745 let dup = match seen_fields.get(&result.name) {
747 span_err!(tcx.sess, f.span, E0124,
748 "field `{}` is already declared",
749 token::get_name(result.name));
750 span_note!(tcx.sess, *prev_span, "previously declared here");
755 // FIXME(#6393) this whole dup thing is just to satisfy
756 // the borrow checker :-(
758 seen_fields.insert(result.name, f.span);
765 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
767 let substs = mk_item_substs(ccx, &scheme.generics);
768 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
770 // If this struct is enum-like or tuple-like, create the type of its
772 match struct_def.ctor_id {
775 if struct_def.fields.len() == 0 {
777 write_ty_to_tcx(tcx, ctor_id, selfty);
779 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
780 } else if struct_def.fields[0].node.kind.is_unnamed() {
782 let inputs: Vec<_> = struct_def.fields.iter().map(
783 |field| (*tcx.tcache.borrow())[
784 local_def(field.node.id)].ty).collect();
785 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
789 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
790 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
792 generics: scheme.generics,
800 fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
801 // As above, this call populates the type table with the converted
802 // type of the foreign item. We simply write it into the node type
805 // For reasons I cannot fully articulate, I do so hate the AST
806 // map, and I regard each time that I use it as a personal and
807 // moral failing, but at the moment it seems like the only
808 // convenient way to extract the ABI. - ndm
809 let abi = ccx.tcx.map.get_foreign_abi(i.id);
811 let scheme = ty_of_foreign_item(ccx, i, abi);
812 write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
814 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
817 fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
818 trait_id: ast::DefId)
819 -> Rc<ty::TraitDef<'tcx>> {
820 if trait_id.krate != ast::LOCAL_CRATE {
821 return ty::lookup_trait_def(ccx.tcx, trait_id)
824 match ccx.tcx.map.get(trait_id.node) {
825 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
827 ccx.tcx.sess.bug(&format!("get_trait_def({}): not an item",
833 fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
835 -> Rc<ty::TraitDef<'tcx>>
837 let def_id = local_def(it.id);
839 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
843 let (unsafety, generics, bounds, items) = match it.node {
844 ast::ItemTrait(unsafety,
848 (unsafety, generics, supertraits, items.as_slice())
853 &format!("trait_def_of_item invoked on {:?}", s)[]);
857 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
859 let ty_generics = ty_generics_for_trait(ccx,
865 let self_param_ty = ty::ParamTy::for_self();
867 let bounds = compute_bounds(ccx,
868 self_param_ty.to_ty(ccx.tcx),
873 let associated_type_names: Vec<_> =
877 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
878 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
883 let trait_ref = Rc::new(ty::TraitRef {
888 let trait_def = Rc::new(ty::TraitDef {
890 generics: ty_generics,
892 trait_ref: trait_ref,
893 associated_type_names: associated_type_names,
895 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
899 fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
900 generics: &ast::Generics)
901 -> subst::Substs<'tcx>
903 // Creates a no-op substitution for the trait's type parameters.
908 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
914 // Start with the generics in the type parameters...
919 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
920 i as u32, def.ident.name))
923 // ...and also create the `Self` parameter.
924 let self_ty = ty::mk_self_type(ccx.tcx);
926 subst::Substs::new_trait(types, regions, self_ty)
930 fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
931 -> ty::TypeScheme<'tcx> {
932 let def_id = local_def(it.id);
934 if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
935 return scheme.clone();
938 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
939 let typ = ccx.to_ty(&ExplicitRscope, &**t);
940 let scheme = no_params(typ);
942 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
945 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
946 let ty_generics = ty_generics_for_fn_or_method(ccx,
948 ty::Generics::empty());
949 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
950 let scheme = TypeScheme {
951 generics: ty_generics,
952 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
954 debug!("type of {} (id {}) is {}",
955 token::get_ident(it.ident),
959 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
962 ast::ItemTy(ref t, ref generics) => {
963 match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
964 Some(scheme) => return scheme.clone(),
969 let ty = ccx.to_ty(&ExplicitRscope, &**t);
971 generics: ty_generics_for_type_or_impl(ccx, generics),
976 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
979 ast::ItemEnum(_, ref generics) => {
980 // Create a new generic polytype.
981 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
982 let substs = mk_item_substs(ccx, &ty_generics);
983 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
984 let scheme = TypeScheme {
985 generics: ty_generics,
989 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
992 ast::ItemTrait(..) => {
993 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
995 ast::ItemStruct(_, ref generics) => {
996 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
997 let substs = mk_item_substs(ccx, &ty_generics);
998 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
999 let scheme = TypeScheme {
1000 generics: ty_generics,
1004 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
1007 ast::ItemImpl(..) | ast::ItemMod(_) |
1008 ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
1012 fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1013 it: &ast::ForeignItem,
1014 abi: abi::Abi) -> ty::TypeScheme<'tcx>
1017 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1018 ty_of_foreign_fn_decl(ccx,
1024 ast::ForeignItemStatic(ref t, _) => {
1026 generics: ty::Generics::empty(),
1027 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1033 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1034 generics: &ast::Generics)
1035 -> ty::Generics<'tcx> {
1038 &generics.lifetimes[],
1039 &generics.ty_params[],
1040 ty::Generics::empty(),
1041 &generics.where_clause)
1044 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1045 trait_id: ast::NodeId,
1046 substs: &'tcx subst::Substs<'tcx>,
1047 ast_generics: &ast::Generics,
1048 trait_items: &[ast::TraitItem])
1049 -> ty::Generics<'tcx>
1051 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1052 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1057 &ast_generics.lifetimes[],
1058 &ast_generics.ty_params[],
1059 ty::Generics::empty(),
1060 &ast_generics.where_clause);
1062 // Add in the self type parameter.
1064 // Something of a hack: use the node id for the trait, also as
1065 // the node id for the Self type parameter.
1066 let param_id = trait_id;
1068 let self_trait_ref =
1069 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1072 let def = ty::TypeParameterDef {
1073 space: subst::SelfSpace,
1075 name: special_idents::type_self.name,
1076 def_id: local_def(param_id),
1077 bounds: ty::ParamBounds {
1078 region_bounds: vec!(),
1079 builtin_bounds: ty::empty_builtin_bounds(),
1080 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1081 projection_bounds: vec!(),
1086 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1088 generics.types.push(subst::SelfSpace, def);
1090 generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
1092 let assoc_predicates = predicates_for_associated_types(ccx,
1096 debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
1098 for assoc_predicate in assoc_predicates.into_iter() {
1099 generics.predicates.push(subst::TypeSpace, assoc_predicate);
1104 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1105 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1106 trait_items: &[ast::TraitItem])
1107 -> Vec<ty::Predicate<'tcx>>
1111 .flat_map(|trait_item| {
1112 let assoc_type_def = match *trait_item {
1113 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1114 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1115 return vec!().into_iter();
1119 let assoc_ty = ty::mk_projection(ccx.tcx,
1120 self_trait_ref.clone(),
1121 assoc_type_def.ident.name);
1123 let bounds = compute_bounds(ccx,
1125 assoc_type_def.bounds.as_slice(),
1126 SizedByDefault::Yes,
1127 assoc_type_def.span);
1129 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1135 fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1136 generics: &ast::Generics,
1137 base_generics: ty::Generics<'tcx>)
1138 -> ty::Generics<'tcx>
1140 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1144 &generics.ty_params[],
1146 &generics.where_clause)
1149 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1150 fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1151 bounds: &mut ty::BuiltinBounds,
1152 ast_bounds: &[ast::TyParamBound],
1155 // Try to find an unbound in bounds.
1156 let mut unbound = None;
1157 for ab in ast_bounds.iter() {
1158 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1159 if unbound.is_none() {
1160 assert!(ptr.bound_lifetimes.is_empty());
1161 unbound = Some(ptr.trait_ref.clone());
1163 ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
1164 bound, only one is supported");
1169 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1172 // FIXME(#8559) currently requires the unbound to be built-in.
1173 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1175 Ok(kind_id) if trait_def_id != kind_id => {
1176 ccx.tcx.sess.span_warn(span,
1177 "default bound relaxed for a type parameter, but \
1178 this does nothing because the given bound is not \
1179 a default. Only `?Sized` is supported");
1180 ty::try_add_builtin_trait(ccx.tcx,
1187 _ if kind_id.is_ok() => {
1188 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1190 // No lang item for Sized, so we can't add it as a bound.
1195 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1196 space: subst::ParamSpace,
1197 lifetime_defs: &[ast::LifetimeDef],
1198 types: &[ast::TyParam],
1199 base_generics: ty::Generics<'tcx>,
1200 where_clause: &ast::WhereClause)
1201 -> ty::Generics<'tcx>
1203 let mut result = base_generics;
1205 for (i, l) in lifetime_defs.iter().enumerate() {
1206 let bounds = l.bounds.iter()
1207 .map(|l| ast_region_to_region(ccx.tcx, l))
1209 let def = ty::RegionParameterDef { name: l.lifetime.name,
1212 def_id: local_def(l.lifetime.id),
1214 debug!("ty_generics: def for region param: {:?}", def);
1215 result.regions.push(space, def);
1218 assert!(result.types.is_empty_in(space));
1220 // Now create the real type parameters.
1221 for (i, param) in types.iter().enumerate() {
1222 let def = get_or_create_type_parameter_def(ccx,
1226 debug!("ty_generics: def for type param: {}, {:?}",
1229 result.types.push(space, def);
1232 // Just for fun, also push the bounds from the type parameters
1233 // into the predicates list. This is currently kind of non-DRY.
1234 create_predicates(ccx.tcx, &mut result, space);
1236 // Add the bounds not associated with a type parameter
1237 for predicate in where_clause.predicates.iter() {
1239 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1240 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1242 for bound in bound_pred.bounds.iter() {
1244 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1245 let mut projections = Vec::new();
1247 let trait_ref = astconv::instantiate_poly_trait_ref(
1255 result.predicates.push(space, trait_ref.as_predicate());
1257 for projection in projections.iter() {
1258 result.predicates.push(space, projection.as_predicate());
1262 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1263 let region = ast_region_to_region(ccx.tcx, lifetime);
1264 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1265 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1271 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1272 let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
1273 for bound in region_pred.bounds.iter() {
1274 let r2 = ast_region_to_region(ccx.tcx, bound);
1275 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1276 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1280 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1282 ccx.tcx.sess.span_bug(eq_pred.span,
1283 "Equality constraints are not yet \
1284 implemented (#20041)")
1291 fn create_predicates<'tcx>(
1292 tcx: &ty::ctxt<'tcx>,
1293 result: &mut ty::Generics<'tcx>,
1294 space: subst::ParamSpace)
1296 for type_param_def in result.types.get_slice(space).iter() {
1297 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1298 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds).into_iter() {
1299 result.predicates.push(space, predicate);
1303 for region_param_def in result.regions.get_slice(space).iter() {
1304 let region = region_param_def.to_early_bound_region();
1305 for &bound_region in region_param_def.bounds.iter() {
1306 // account for new binder introduced in the predicate below; no need
1307 // to shift `region` because it is never a late-bound region
1308 let bound_region = ty_fold::shift_region(bound_region, 1);
1309 result.predicates.push(
1311 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1317 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1318 space: subst::ParamSpace,
1319 param: &ast::TyParam,
1321 -> ty::TypeParameterDef<'tcx>
1323 match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
1324 Some(d) => { return (*d).clone(); }
1328 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1329 let bounds = compute_bounds(ccx,
1330 param_ty.to_ty(ccx.tcx),
1332 SizedByDefault::Yes,
1334 let default = match param.default {
1337 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1338 let cur_idx = index;
1340 ty::walk_ty(ty, |t| {
1342 ty::ty_param(p) => if p.idx > cur_idx {
1343 span_err!(ccx.tcx.sess, path.span, E0128,
1344 "type parameters with a default cannot use \
1345 forward declared identifiers");
1355 let def = ty::TypeParameterDef {
1358 name: param.ident.name,
1359 def_id: local_def(param.id),
1364 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1369 enum SizedByDefault { Yes, No }
1371 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1372 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1373 /// built-in trait (formerly known as kind): Send.
1374 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1375 param_ty: ty::Ty<'tcx>,
1376 ast_bounds: &[ast::TyParamBound],
1377 sized_by_default: SizedByDefault,
1379 -> ty::ParamBounds<'tcx>
1381 let mut param_bounds = conv_param_bounds(ccx,
1386 if let SizedByDefault::Yes = sized_by_default {
1387 add_unsized_bound(ccx,
1388 &mut param_bounds.builtin_bounds,
1392 check_bounds_compatible(ccx.tcx,
1398 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1403 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1405 param_bounds: &ty::ParamBounds<'tcx>,
1407 // Currently the only bound which is incompatible with other bounds is
1409 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1410 ty::each_bound_trait_and_supertraits(
1412 ¶m_bounds.trait_bounds[],
1414 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1415 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1416 span_err!(tcx.sess, span, E0129,
1417 "incompatible bounds on `{}`, \
1418 bound `{}` does not allow unsized type",
1419 param_ty.user_string(tcx),
1420 trait_ref.user_string(tcx));
1427 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1429 param_ty: ty::Ty<'tcx>,
1430 ast_bounds: &[ast::TyParamBound])
1431 -> ty::ParamBounds<'tcx>
1433 let astconv::PartitionedBounds { builtin_bounds,
1436 astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
1438 let mut projection_bounds = Vec::new();
1440 let trait_bounds: Vec<ty::PolyTraitRef> =
1441 trait_bounds.into_iter()
1443 astconv::instantiate_poly_trait_ref(ccx,
1447 &mut projection_bounds)
1450 let region_bounds: Vec<ty::Region> =
1451 region_bounds.into_iter()
1452 .map(|r| ast_region_to_region(ccx.tcx, r))
1455 region_bounds: region_bounds,
1456 builtin_bounds: builtin_bounds,
1457 trait_bounds: trait_bounds,
1458 projection_bounds: projection_bounds,
1462 fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1465 ast_generics: &ast::Generics,
1467 -> ty::TypeScheme<'tcx> {
1468 for i in decl.inputs.iter() {
1469 match (*i).pat.node {
1470 ast::PatIdent(_, _, _) => (),
1471 ast::PatWild(ast::PatWildSingle) => (),
1473 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1474 "patterns aren't allowed in foreign function declarations");
1479 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1481 ty::Generics::empty());
1482 let rb = BindingRscope::new();
1483 let input_tys = decl.inputs
1485 .map(|a| ty_of_arg(ccx, &rb, a, None))
1488 let output = match decl.output {
1489 ast::Return(ref ty) =>
1490 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1495 let t_fn = ty::mk_bare_fn(
1498 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1500 unsafety: ast::Unsafety::Unsafe,
1501 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1503 variadic: decl.variadic}),
1505 let scheme = TypeScheme {
1506 generics: ty_generics_for_fn_or_method,
1510 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1514 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1515 ty_generics: &ty::Generics<'tcx>)
1516 -> subst::Substs<'tcx>
1519 ty_generics.types.map(
1520 |def| ty::mk_param_from_def(ccx.tcx, def));
1523 ty_generics.regions.map(
1524 |def| def.to_early_bound_region());
1526 subst::Substs::new(types, regions)
1529 /// Verifies that the explicit self type of a method matches the impl
1530 /// or trait. This is a bit weird but basically because right now we
1531 /// don't handle the general case, but instead map it to one of
1532 /// several pre-defined options using various heuristics, this method
1533 /// comes back to check after the fact that explicit type the user
1534 /// wrote actually matches what the pre-defined option said.
1535 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1536 ccx: &CollectCtxt<'a, 'tcx>,
1538 required_type: Ty<'tcx>,
1539 explicit_self: &ast::ExplicitSelf,
1540 body_id: ast::NodeId)
1542 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1543 let typ = ccx.to_ty(rs, &**ast_type);
1544 let base_type = match typ.sty {
1545 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1546 ty::ty_uniq(typ) => typ,
1550 let body_scope = region::CodeExtent::from_node_id(body_id);
1552 // "Required type" comes from the trait definition. It may
1553 // contain late-bound regions from the method, but not the
1554 // trait (since traits only have early-bound region
1556 assert!(!base_type.has_regions_escaping_depth(1));
1557 let required_type_free =
1558 liberate_early_bound_regions(
1559 ccx.tcx, body_scope,
1560 &ty::liberate_late_bound_regions(
1561 ccx.tcx, body_scope, &ty::Binder(required_type)));
1563 // The "base type" comes from the impl. It too may have late-bound
1564 // regions from the method.
1565 assert!(!base_type.has_regions_escaping_depth(1));
1566 let base_type_free =
1567 liberate_early_bound_regions(
1568 ccx.tcx, body_scope,
1569 &ty::liberate_late_bound_regions(
1570 ccx.tcx, body_scope, &ty::Binder(base_type)));
1572 debug!("required_type={} required_type_free={} \
1573 base_type={} base_type_free={}",
1574 required_type.repr(ccx.tcx),
1575 required_type_free.repr(ccx.tcx),
1576 base_type.repr(ccx.tcx),
1577 base_type_free.repr(ccx.tcx));
1578 let infcx = infer::new_infer_ctxt(ccx.tcx);
1579 drop(::require_same_types(ccx.tcx,
1586 format!("mismatched self type: expected `{}`",
1587 ppaux::ty_to_string(ccx.tcx, required_type))
1589 infcx.resolve_regions_and_report_errors(body_id);
1592 fn liberate_early_bound_regions<'tcx,T>(
1593 tcx: &ty::ctxt<'tcx>,
1594 scope: region::CodeExtent,
1597 where T : TypeFoldable<'tcx> + Repr<'tcx>
1600 * Convert early-bound regions into free regions; normally this is done by
1601 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1602 * method-self-type check is kind of hacky and done very early in the process,
1603 * before we really have a `ParameterEnvironment` to check.
1606 ty_fold::fold_regions(tcx, value, |region, _| {
1608 ty::ReEarlyBound(id, _, _, name) => {
1609 let def_id = local_def(id);
1610 ty::ReFree(ty::FreeRegion { scope: scope,
1611 bound_region: ty::BrNamed(def_id, name) })
1619 /// Checks that all the type parameters on an impl
1620 fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1621 ast_generics: &ast::Generics,
1622 impl_def_id: ast::DefId)
1624 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1625 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1627 // The trait reference is an input, so find all type parameters
1628 // reachable from there, to start (if this is an inherent impl,
1629 // then just examine the self type).
1630 let mut input_parameters: HashSet<_> =
1631 impl_trait_ref.iter()
1632 .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1633 .chain(Some(impl_scheme.ty).iter()) // Self type, always
1634 .flat_map(|t| t.walk())
1635 .filter_map(to_opt_param_ty)
1639 let num_inputs = input_parameters.len();
1641 let mut projection_predicates =
1642 impl_scheme.generics.predicates
1644 .filter_map(|predicate| {
1646 // Ignore higher-ranked binders. For the purposes
1647 // of this check, they don't matter because they
1648 // only affect named regions, and we're just
1649 // concerned about type parameters here.
1650 ty::Predicate::Projection(ref data) => Some(data.0.clone()),
1655 for projection in projection_predicates {
1656 // Special case: watch out for some kind of sneaky attempt
1657 // to project out an associated type defined by this very trait.
1658 if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
1662 let relies_only_on_inputs =
1663 projection.projection_ty.trait_ref.input_types().iter()
1664 .flat_map(|t| t.walk())
1665 .filter_map(to_opt_param_ty)
1666 .all(|t| input_parameters.contains(&t));
1668 if relies_only_on_inputs {
1669 input_parameters.extend(
1670 projection.ty.walk().filter_map(to_opt_param_ty));
1674 if input_parameters.len() == num_inputs {
1679 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1680 let param_ty = ty::ParamTy { space: TypeSpace,
1682 name: ty_param.ident.name };
1683 if !input_parameters.contains(¶m_ty) {
1684 if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1687 format!("the type parameter `{}` is not constrained by the \
1688 impl trait, self type, or predicates",
1689 param_ty.user_string(tcx)).as_slice());
1693 format!("the type parameter `{}` is not constrained by the \
1694 impl trait, self type, or predicates",
1695 param_ty.user_string(tcx)).as_slice());
1698 format!("you can temporarily opt out of this rule by placing \
1699 the `#[old_impl_check]` attribute on the impl").as_slice());
1704 fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
1706 ty::ty_param(ref d) => Some(d.clone()),