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 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
613 .insert(local_def(typedef.id),
615 generics: ty::Generics::empty(),
618 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
620 let associated_type = Rc::new(ty::AssociatedType {
621 name: typedef.ident.name,
623 def_id: local_def(typedef.id),
624 container: ty::ImplContainer(local_def(it.id)),
626 tcx.impl_or_trait_items
628 .insert(local_def(typedef.id),
629 ty::TypeTraitItem(associated_type));
635 ImplContainer(local_def(it.id)),
641 for trait_ref in opt_trait_ref.iter() {
642 astconv::instantiate_trait_ref(ccx,
649 enforce_impl_ty_params_are_constrained(ccx.tcx,
653 ast::ItemTrait(_, _, _, ref trait_methods) => {
654 let trait_def = trait_def_of_item(ccx, it);
656 debug!("trait_def: ident={} trait_def={}",
657 it.ident.repr(ccx.tcx),
658 trait_def.repr(ccx.tcx));
660 for trait_method in trait_methods.iter() {
661 let self_type = ty::mk_self_type(tcx);
662 match *trait_method {
663 ast::RequiredMethod(ref type_method) => {
664 let rscope = BindingRscope::new();
665 check_method_self_type(ccx,
668 &type_method.explicit_self,
671 ast::ProvidedMethod(ref method) => {
672 check_method_self_type(ccx,
673 &BindingRscope::new(),
675 method.pe_explicit_self(),
678 ast::TypeTraitItem(ref associated_type) => {
679 convert_associated_type(ccx,
686 // Run convert_methods on the provided methods.
687 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
689 TraitContainer(local_def(it.id)),
690 trait_methods.iter().filter_map(|m| match *m {
691 ast::RequiredMethod(_) => None,
692 ast::ProvidedMethod(ref m) => Some(&**m),
693 ast::TypeTraitItem(_) => None,
695 untransformed_rcvr_ty,
699 // We need to do this *after* converting methods, since
700 // convert_methods produces a tcache entry that is wrong for
701 // static trait methods. This is somewhat unfortunate.
702 collect_trait_methods(ccx, it.id, &*trait_def);
704 ast::ItemStruct(ref struct_def, _) => {
705 // Write the class type.
706 let scheme = ty_of_item(ccx, it);
707 write_ty_to_tcx(tcx, it.id, scheme.ty);
709 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
711 convert_struct(ccx, &**struct_def, scheme, it.id);
713 ast::ItemTy(_, ref generics) => {
714 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
715 let tpt = ty_of_item(ccx, it);
716 write_ty_to_tcx(tcx, it.id, tpt.ty);
719 // This call populates the type cache with the converted type
720 // of the item in passing. All we have to do here is to write
721 // it into the node type table.
722 let scheme = ty_of_item(ccx, it);
723 write_ty_to_tcx(tcx, it.id, scheme.ty);
728 fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
729 struct_def: &ast::StructDef,
730 scheme: ty::TypeScheme<'tcx>,
734 // Write the type of each of the members and check for duplicate fields.
735 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap::new();
736 let field_tys = struct_def.fields.iter().map(|f| {
737 let result = convert_field(ccx, &scheme.generics, f, local_def(id));
739 if result.name != special_idents::unnamed_field.name {
740 let dup = match seen_fields.get(&result.name) {
742 span_err!(tcx.sess, f.span, E0124,
743 "field `{}` is already declared",
744 token::get_name(result.name));
745 span_note!(tcx.sess, *prev_span, "previously declared here");
750 // FIXME(#6393) this whole dup thing is just to satisfy
751 // the borrow checker :-(
753 seen_fields.insert(result.name, f.span);
760 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
762 let substs = mk_item_substs(ccx, &scheme.generics);
763 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
765 // If this struct is enum-like or tuple-like, create the type of its
767 match struct_def.ctor_id {
770 if struct_def.fields.len() == 0 {
772 write_ty_to_tcx(tcx, ctor_id, selfty);
774 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
775 } else if struct_def.fields[0].node.kind.is_unnamed() {
777 let inputs: Vec<_> = struct_def.fields.iter().map(
778 |field| (*tcx.tcache.borrow())[
779 local_def(field.node.id)].ty).collect();
780 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
784 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
785 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
787 generics: scheme.generics,
795 fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
796 // As above, this call populates the type table with the converted
797 // type of the foreign item. We simply write it into the node type
800 // For reasons I cannot fully articulate, I do so hate the AST
801 // map, and I regard each time that I use it as a personal and
802 // moral failing, but at the moment it seems like the only
803 // convenient way to extract the ABI. - ndm
804 let abi = ccx.tcx.map.get_foreign_abi(i.id);
806 let scheme = ty_of_foreign_item(ccx, i, abi);
807 write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
809 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
812 fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
813 trait_id: ast::DefId)
814 -> Rc<ty::TraitDef<'tcx>> {
815 if trait_id.krate != ast::LOCAL_CRATE {
816 return ty::lookup_trait_def(ccx.tcx, trait_id)
819 match ccx.tcx.map.get(trait_id.node) {
820 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
822 ccx.tcx.sess.bug(&format!("get_trait_def({}): not an item",
828 fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
830 -> Rc<ty::TraitDef<'tcx>>
832 let def_id = local_def(it.id);
834 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
838 let (unsafety, generics, bounds, items) = match it.node {
839 ast::ItemTrait(unsafety,
843 (unsafety, generics, supertraits, items.as_slice())
848 &format!("trait_def_of_item invoked on {:?}", s)[]);
852 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
854 let ty_generics = ty_generics_for_trait(ccx,
860 let self_param_ty = ty::ParamTy::for_self();
862 let bounds = compute_bounds(ccx,
863 self_param_ty.to_ty(ccx.tcx),
868 let associated_type_names: Vec<_> =
872 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
873 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
878 let trait_ref = Rc::new(ty::TraitRef {
883 let trait_def = Rc::new(ty::TraitDef {
885 generics: ty_generics,
887 trait_ref: trait_ref,
888 associated_type_names: associated_type_names,
890 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
894 fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
895 generics: &ast::Generics)
896 -> subst::Substs<'tcx>
898 // Creates a no-op substitution for the trait's type parameters.
903 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
909 // Start with the generics in the type parameters...
914 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
915 i as u32, def.ident.name))
918 // ...and also create the `Self` parameter.
919 let self_ty = ty::mk_self_type(ccx.tcx);
921 subst::Substs::new_trait(types, regions, self_ty)
925 fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
926 -> ty::TypeScheme<'tcx> {
927 let def_id = local_def(it.id);
929 if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
930 return scheme.clone();
933 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
934 let typ = ccx.to_ty(&ExplicitRscope, &**t);
935 let scheme = no_params(typ);
937 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
940 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
941 let ty_generics = ty_generics_for_fn_or_method(ccx,
943 ty::Generics::empty());
944 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
945 let scheme = TypeScheme {
946 generics: ty_generics,
947 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
949 debug!("type of {} (id {}) is {}",
950 token::get_ident(it.ident),
954 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
957 ast::ItemTy(ref t, ref generics) => {
958 match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
959 Some(scheme) => return scheme.clone(),
964 let ty = ccx.to_ty(&ExplicitRscope, &**t);
966 generics: ty_generics_for_type_or_impl(ccx, generics),
971 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
974 ast::ItemEnum(_, ref generics) => {
975 // Create a new generic polytype.
976 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
977 let substs = mk_item_substs(ccx, &ty_generics);
978 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
979 let scheme = TypeScheme {
980 generics: ty_generics,
984 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
987 ast::ItemTrait(..) => {
988 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
990 ast::ItemStruct(_, ref generics) => {
991 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
992 let substs = mk_item_substs(ccx, &ty_generics);
993 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
994 let scheme = TypeScheme {
995 generics: ty_generics,
999 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
1002 ast::ItemImpl(..) | ast::ItemMod(_) |
1003 ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
1007 fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1008 it: &ast::ForeignItem,
1009 abi: abi::Abi) -> ty::TypeScheme<'tcx>
1012 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1013 ty_of_foreign_fn_decl(ccx,
1019 ast::ForeignItemStatic(ref t, _) => {
1021 generics: ty::Generics::empty(),
1022 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1028 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1029 generics: &ast::Generics)
1030 -> ty::Generics<'tcx> {
1033 &generics.lifetimes[],
1034 &generics.ty_params[],
1035 ty::Generics::empty(),
1036 &generics.where_clause)
1039 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1040 trait_id: ast::NodeId,
1041 substs: &'tcx subst::Substs<'tcx>,
1042 ast_generics: &ast::Generics,
1043 trait_items: &[ast::TraitItem])
1044 -> ty::Generics<'tcx>
1046 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1047 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1052 &ast_generics.lifetimes[],
1053 &ast_generics.ty_params[],
1054 ty::Generics::empty(),
1055 &ast_generics.where_clause);
1057 // Add in the self type parameter.
1059 // Something of a hack: use the node id for the trait, also as
1060 // the node id for the Self type parameter.
1061 let param_id = trait_id;
1063 let self_trait_ref =
1064 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1067 let def = ty::TypeParameterDef {
1068 space: subst::SelfSpace,
1070 name: special_idents::type_self.name,
1071 def_id: local_def(param_id),
1072 bounds: ty::ParamBounds {
1073 region_bounds: vec!(),
1074 builtin_bounds: ty::empty_builtin_bounds(),
1075 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1076 projection_bounds: vec!(),
1081 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1083 generics.types.push(subst::SelfSpace, def);
1085 generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
1087 let assoc_predicates = predicates_for_associated_types(ccx,
1091 debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
1093 for assoc_predicate in assoc_predicates.into_iter() {
1094 generics.predicates.push(subst::TypeSpace, assoc_predicate);
1099 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1100 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1101 trait_items: &[ast::TraitItem])
1102 -> Vec<ty::Predicate<'tcx>>
1106 .flat_map(|trait_item| {
1107 let assoc_type_def = match *trait_item {
1108 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1109 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1110 return vec!().into_iter();
1114 let assoc_ty = ty::mk_projection(ccx.tcx,
1115 self_trait_ref.clone(),
1116 assoc_type_def.ident.name);
1118 let bounds = compute_bounds(ccx,
1120 assoc_type_def.bounds.as_slice(),
1121 SizedByDefault::Yes,
1122 assoc_type_def.span);
1124 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1130 fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1131 generics: &ast::Generics,
1132 base_generics: ty::Generics<'tcx>)
1133 -> ty::Generics<'tcx>
1135 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1139 &generics.ty_params[],
1141 &generics.where_clause)
1144 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1145 fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1146 bounds: &mut ty::BuiltinBounds,
1147 ast_bounds: &[ast::TyParamBound],
1150 // Try to find an unbound in bounds.
1151 let mut unbound = None;
1152 for ab in ast_bounds.iter() {
1153 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1154 if unbound.is_none() {
1155 assert!(ptr.bound_lifetimes.is_empty());
1156 unbound = Some(ptr.trait_ref.clone());
1158 ccx.tcx.sess.span_err(span, "type parameter has more than one relaxed default \
1159 bound, only one is supported");
1164 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1167 // FIXME(#8559) currently requires the unbound to be built-in.
1168 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1170 Ok(kind_id) if trait_def_id != kind_id => {
1171 ccx.tcx.sess.span_warn(span,
1172 "default bound relaxed for a type parameter, but \
1173 this does nothing because the given bound is not \
1174 a default. Only `?Sized` is supported");
1175 ty::try_add_builtin_trait(ccx.tcx,
1182 _ if kind_id.is_ok() => {
1183 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1185 // No lang item for Sized, so we can't add it as a bound.
1190 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1191 space: subst::ParamSpace,
1192 lifetime_defs: &[ast::LifetimeDef],
1193 types: &[ast::TyParam],
1194 base_generics: ty::Generics<'tcx>,
1195 where_clause: &ast::WhereClause)
1196 -> ty::Generics<'tcx>
1198 let mut result = base_generics;
1200 for (i, l) in lifetime_defs.iter().enumerate() {
1201 let bounds = l.bounds.iter()
1202 .map(|l| ast_region_to_region(ccx.tcx, l))
1204 let def = ty::RegionParameterDef { name: l.lifetime.name,
1207 def_id: local_def(l.lifetime.id),
1209 debug!("ty_generics: def for region param: {:?}", def);
1210 result.regions.push(space, def);
1213 assert!(result.types.is_empty_in(space));
1215 // Now create the real type parameters.
1216 for (i, param) in types.iter().enumerate() {
1217 let def = get_or_create_type_parameter_def(ccx,
1221 debug!("ty_generics: def for type param: {}, {:?}",
1224 result.types.push(space, def);
1227 // Just for fun, also push the bounds from the type parameters
1228 // into the predicates list. This is currently kind of non-DRY.
1229 create_predicates(ccx.tcx, &mut result, space);
1231 // Add the bounds not associated with a type parameter
1232 for predicate in where_clause.predicates.iter() {
1234 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1235 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1237 for bound in bound_pred.bounds.iter() {
1239 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1240 let mut projections = Vec::new();
1242 let trait_ref = astconv::instantiate_poly_trait_ref(
1250 result.predicates.push(space, trait_ref.as_predicate());
1252 for projection in projections.iter() {
1253 result.predicates.push(space, projection.as_predicate());
1257 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1258 let region = ast_region_to_region(ccx.tcx, lifetime);
1259 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1260 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1266 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1267 let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
1268 for bound in region_pred.bounds.iter() {
1269 let r2 = ast_region_to_region(ccx.tcx, bound);
1270 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1271 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1275 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1277 ccx.tcx.sess.span_bug(eq_pred.span,
1278 "Equality constraints are not yet \
1279 implemented (#20041)")
1286 fn create_predicates<'tcx>(
1287 tcx: &ty::ctxt<'tcx>,
1288 result: &mut ty::Generics<'tcx>,
1289 space: subst::ParamSpace)
1291 for type_param_def in result.types.get_slice(space).iter() {
1292 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1293 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds).into_iter() {
1294 result.predicates.push(space, predicate);
1298 for region_param_def in result.regions.get_slice(space).iter() {
1299 let region = region_param_def.to_early_bound_region();
1300 for &bound_region in region_param_def.bounds.iter() {
1301 // account for new binder introduced in the predicate below; no need
1302 // to shift `region` because it is never a late-bound region
1303 let bound_region = ty_fold::shift_region(bound_region, 1);
1304 result.predicates.push(
1306 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1312 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1313 space: subst::ParamSpace,
1314 param: &ast::TyParam,
1316 -> ty::TypeParameterDef<'tcx>
1318 match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
1319 Some(d) => { return (*d).clone(); }
1323 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1324 let bounds = compute_bounds(ccx,
1325 param_ty.to_ty(ccx.tcx),
1327 SizedByDefault::Yes,
1329 let default = match param.default {
1332 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1333 let cur_idx = index;
1335 ty::walk_ty(ty, |t| {
1337 ty::ty_param(p) => if p.idx > cur_idx {
1338 span_err!(ccx.tcx.sess, path.span, E0128,
1339 "type parameters with a default cannot use \
1340 forward declared identifiers");
1350 let def = ty::TypeParameterDef {
1353 name: param.ident.name,
1354 def_id: local_def(param.id),
1359 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1364 enum SizedByDefault { Yes, No }
1366 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1367 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1368 /// built-in trait (formerly known as kind): Send.
1369 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1370 param_ty: ty::Ty<'tcx>,
1371 ast_bounds: &[ast::TyParamBound],
1372 sized_by_default: SizedByDefault,
1374 -> ty::ParamBounds<'tcx>
1376 let mut param_bounds = conv_param_bounds(ccx,
1381 if let SizedByDefault::Yes = sized_by_default {
1382 add_unsized_bound(ccx,
1383 &mut param_bounds.builtin_bounds,
1387 check_bounds_compatible(ccx.tcx,
1393 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1398 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1400 param_bounds: &ty::ParamBounds<'tcx>,
1402 // Currently the only bound which is incompatible with other bounds is
1404 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1405 ty::each_bound_trait_and_supertraits(
1407 ¶m_bounds.trait_bounds[],
1409 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1410 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1411 span_err!(tcx.sess, span, E0129,
1412 "incompatible bounds on `{}`, \
1413 bound `{}` does not allow unsized type",
1414 param_ty.user_string(tcx),
1415 trait_ref.user_string(tcx));
1422 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1424 param_ty: ty::Ty<'tcx>,
1425 ast_bounds: &[ast::TyParamBound])
1426 -> ty::ParamBounds<'tcx>
1428 let astconv::PartitionedBounds { builtin_bounds,
1431 astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
1433 let mut projection_bounds = Vec::new();
1435 let trait_bounds: Vec<ty::PolyTraitRef> =
1436 trait_bounds.into_iter()
1438 astconv::instantiate_poly_trait_ref(ccx,
1442 &mut projection_bounds)
1445 let region_bounds: Vec<ty::Region> =
1446 region_bounds.into_iter()
1447 .map(|r| ast_region_to_region(ccx.tcx, r))
1450 region_bounds: region_bounds,
1451 builtin_bounds: builtin_bounds,
1452 trait_bounds: trait_bounds,
1453 projection_bounds: projection_bounds,
1457 fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1460 ast_generics: &ast::Generics,
1462 -> ty::TypeScheme<'tcx> {
1463 for i in decl.inputs.iter() {
1464 match (*i).pat.node {
1465 ast::PatIdent(_, _, _) => (),
1466 ast::PatWild(ast::PatWildSingle) => (),
1468 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1469 "patterns aren't allowed in foreign function declarations");
1474 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1476 ty::Generics::empty());
1477 let rb = BindingRscope::new();
1478 let input_tys = decl.inputs
1480 .map(|a| ty_of_arg(ccx, &rb, a, None))
1483 let output = match decl.output {
1484 ast::Return(ref ty) =>
1485 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1490 let t_fn = ty::mk_bare_fn(
1493 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1495 unsafety: ast::Unsafety::Unsafe,
1496 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1498 variadic: decl.variadic}),
1500 let scheme = TypeScheme {
1501 generics: ty_generics_for_fn_or_method,
1505 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1509 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1510 ty_generics: &ty::Generics<'tcx>)
1511 -> subst::Substs<'tcx>
1514 ty_generics.types.map(
1515 |def| ty::mk_param_from_def(ccx.tcx, def));
1518 ty_generics.regions.map(
1519 |def| def.to_early_bound_region());
1521 subst::Substs::new(types, regions)
1524 /// Verifies that the explicit self type of a method matches the impl
1525 /// or trait. This is a bit weird but basically because right now we
1526 /// don't handle the general case, but instead map it to one of
1527 /// several pre-defined options using various heuristics, this method
1528 /// comes back to check after the fact that explicit type the user
1529 /// wrote actually matches what the pre-defined option said.
1530 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1531 ccx: &CollectCtxt<'a, 'tcx>,
1533 required_type: Ty<'tcx>,
1534 explicit_self: &ast::ExplicitSelf,
1535 body_id: ast::NodeId)
1537 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1538 let typ = ccx.to_ty(rs, &**ast_type);
1539 let base_type = match typ.sty {
1540 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1541 ty::ty_uniq(typ) => typ,
1545 let body_scope = region::CodeExtent::from_node_id(body_id);
1547 // "Required type" comes from the trait definition. It may
1548 // contain late-bound regions from the method, but not the
1549 // trait (since traits only have early-bound region
1551 assert!(!base_type.has_regions_escaping_depth(1));
1552 let required_type_free =
1553 liberate_early_bound_regions(
1554 ccx.tcx, body_scope,
1555 &ty::liberate_late_bound_regions(
1556 ccx.tcx, body_scope, &ty::Binder(required_type)));
1558 // The "base type" comes from the impl. It too may have late-bound
1559 // regions from the method.
1560 assert!(!base_type.has_regions_escaping_depth(1));
1561 let base_type_free =
1562 liberate_early_bound_regions(
1563 ccx.tcx, body_scope,
1564 &ty::liberate_late_bound_regions(
1565 ccx.tcx, body_scope, &ty::Binder(base_type)));
1567 debug!("required_type={} required_type_free={} \
1568 base_type={} base_type_free={}",
1569 required_type.repr(ccx.tcx),
1570 required_type_free.repr(ccx.tcx),
1571 base_type.repr(ccx.tcx),
1572 base_type_free.repr(ccx.tcx));
1573 let infcx = infer::new_infer_ctxt(ccx.tcx);
1574 drop(::require_same_types(ccx.tcx,
1581 format!("mismatched self type: expected `{}`",
1582 ppaux::ty_to_string(ccx.tcx, required_type))
1584 infcx.resolve_regions_and_report_errors(body_id);
1587 fn liberate_early_bound_regions<'tcx,T>(
1588 tcx: &ty::ctxt<'tcx>,
1589 scope: region::CodeExtent,
1592 where T : TypeFoldable<'tcx> + Repr<'tcx>
1595 * Convert early-bound regions into free regions; normally this is done by
1596 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1597 * method-self-type check is kind of hacky and done very early in the process,
1598 * before we really have a `ParameterEnvironment` to check.
1601 ty_fold::fold_regions(tcx, value, |region, _| {
1603 ty::ReEarlyBound(id, _, _, name) => {
1604 let def_id = local_def(id);
1605 ty::ReFree(ty::FreeRegion { scope: scope,
1606 bound_region: ty::BrNamed(def_id, name) })
1614 /// Checks that all the type parameters on an impl
1615 fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1616 ast_generics: &ast::Generics,
1617 impl_def_id: ast::DefId)
1619 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1620 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1622 // The trait reference is an input, so find all type parameters
1623 // reachable from there, to start (if this is an inherent impl,
1624 // then just examine the self type).
1625 let mut input_parameters: HashSet<_> =
1626 impl_trait_ref.iter()
1627 .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1628 .chain(Some(impl_scheme.ty).iter()) // Self type, always
1629 .flat_map(|t| t.walk())
1630 .filter_map(to_opt_param_ty)
1634 let num_inputs = input_parameters.len();
1636 let mut projection_predicates =
1637 impl_scheme.generics.predicates
1639 .filter_map(|predicate| {
1641 // Ignore higher-ranked binders. For the purposes
1642 // of this check, they don't matter because they
1643 // only affect named regions, and we're just
1644 // concerned about type parameters here.
1645 ty::Predicate::Projection(ref data) => Some(data.0.clone()),
1650 for projection in projection_predicates {
1651 // Special case: watch out for some kind of sneaky attempt
1652 // to project out an associated type defined by this very trait.
1653 if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
1657 let relies_only_on_inputs =
1658 projection.projection_ty.trait_ref.input_types().iter()
1659 .flat_map(|t| t.walk())
1660 .filter_map(to_opt_param_ty)
1661 .all(|t| input_parameters.contains(&t));
1663 if relies_only_on_inputs {
1664 input_parameters.extend(
1665 projection.ty.walk().filter_map(to_opt_param_ty));
1669 if input_parameters.len() == num_inputs {
1674 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1675 let param_ty = ty::ParamTy { space: TypeSpace,
1677 name: ty_param.ident.name };
1678 if !input_parameters.contains(¶m_ty) {
1679 if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1682 format!("the type parameter `{}` is not constrained by the \
1683 impl trait, self type, or predicates",
1684 param_ty.user_string(tcx)).as_slice());
1688 format!("the type parameter `{}` is not constrained by the \
1689 impl trait, self type, or predicates",
1690 param_ty.user_string(tcx)).as_slice());
1693 format!("you can temporarily opt out of this rule by placing \
1694 the `#[old_impl_check]` attribute on the impl").as_slice());
1699 fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
1701 ty::ty_param(ref d) => Some(d.clone()),