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();
454 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
455 span_err!(tcx.sess, m.span, E0201, "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 span_err!(tcx.sess, typedef.span, E0202,
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();
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 span_err!(ccx.tcx.sess, span, E0203,
1164 "type parameter has more than one relaxed default \
1165 bound, only one is supported");
1170 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1173 // FIXME(#8559) currently requires the unbound to be built-in.
1174 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1176 Ok(kind_id) if trait_def_id != kind_id => {
1177 ccx.tcx.sess.span_warn(span,
1178 "default bound relaxed for a type parameter, but \
1179 this does nothing because the given bound is not \
1180 a default. Only `?Sized` is supported");
1181 ty::try_add_builtin_trait(ccx.tcx,
1188 _ if kind_id.is_ok() => {
1189 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1191 // No lang item for Sized, so we can't add it as a bound.
1196 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1197 space: subst::ParamSpace,
1198 lifetime_defs: &[ast::LifetimeDef],
1199 types: &[ast::TyParam],
1200 base_generics: ty::Generics<'tcx>,
1201 where_clause: &ast::WhereClause)
1202 -> ty::Generics<'tcx>
1204 let mut result = base_generics;
1206 for (i, l) in lifetime_defs.iter().enumerate() {
1207 let bounds = l.bounds.iter()
1208 .map(|l| ast_region_to_region(ccx.tcx, l))
1210 let def = ty::RegionParameterDef { name: l.lifetime.name,
1213 def_id: local_def(l.lifetime.id),
1215 debug!("ty_generics: def for region param: {:?}", def);
1216 result.regions.push(space, def);
1219 assert!(result.types.is_empty_in(space));
1221 // Now create the real type parameters.
1222 for (i, param) in types.iter().enumerate() {
1223 let def = get_or_create_type_parameter_def(ccx,
1227 debug!("ty_generics: def for type param: {}, {:?}",
1230 result.types.push(space, def);
1233 // Just for fun, also push the bounds from the type parameters
1234 // into the predicates list. This is currently kind of non-DRY.
1235 create_predicates(ccx.tcx, &mut result, space);
1237 // Add the bounds not associated with a type parameter
1238 for predicate in where_clause.predicates.iter() {
1240 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1241 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1243 for bound in bound_pred.bounds.iter() {
1245 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1246 let mut projections = Vec::new();
1248 let trait_ref = astconv::instantiate_poly_trait_ref(
1256 result.predicates.push(space, trait_ref.as_predicate());
1258 for projection in projections.iter() {
1259 result.predicates.push(space, projection.as_predicate());
1263 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1264 let region = ast_region_to_region(ccx.tcx, lifetime);
1265 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1266 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1272 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1273 let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
1274 for bound in region_pred.bounds.iter() {
1275 let r2 = ast_region_to_region(ccx.tcx, bound);
1276 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1277 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1281 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1283 ccx.tcx.sess.span_bug(eq_pred.span,
1284 "Equality constraints are not yet \
1285 implemented (#20041)")
1292 fn create_predicates<'tcx>(
1293 tcx: &ty::ctxt<'tcx>,
1294 result: &mut ty::Generics<'tcx>,
1295 space: subst::ParamSpace)
1297 for type_param_def in result.types.get_slice(space).iter() {
1298 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1299 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds).into_iter() {
1300 result.predicates.push(space, predicate);
1304 for region_param_def in result.regions.get_slice(space).iter() {
1305 let region = region_param_def.to_early_bound_region();
1306 for &bound_region in region_param_def.bounds.iter() {
1307 // account for new binder introduced in the predicate below; no need
1308 // to shift `region` because it is never a late-bound region
1309 let bound_region = ty_fold::shift_region(bound_region, 1);
1310 result.predicates.push(
1312 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1318 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1319 space: subst::ParamSpace,
1320 param: &ast::TyParam,
1322 -> ty::TypeParameterDef<'tcx>
1324 match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
1325 Some(d) => { return (*d).clone(); }
1329 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1330 let bounds = compute_bounds(ccx,
1331 param_ty.to_ty(ccx.tcx),
1333 SizedByDefault::Yes,
1335 let default = match param.default {
1338 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1339 let cur_idx = index;
1341 ty::walk_ty(ty, |t| {
1343 ty::ty_param(p) => if p.idx > cur_idx {
1344 span_err!(ccx.tcx.sess, path.span, E0128,
1345 "type parameters with a default cannot use \
1346 forward declared identifiers");
1356 let def = ty::TypeParameterDef {
1359 name: param.ident.name,
1360 def_id: local_def(param.id),
1365 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1370 enum SizedByDefault { Yes, No }
1372 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1373 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1374 /// built-in trait (formerly known as kind): Send.
1375 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1376 param_ty: ty::Ty<'tcx>,
1377 ast_bounds: &[ast::TyParamBound],
1378 sized_by_default: SizedByDefault,
1380 -> ty::ParamBounds<'tcx>
1382 let mut param_bounds = conv_param_bounds(ccx,
1387 if let SizedByDefault::Yes = sized_by_default {
1388 add_unsized_bound(ccx,
1389 &mut param_bounds.builtin_bounds,
1393 check_bounds_compatible(ccx.tcx,
1399 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1404 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1406 param_bounds: &ty::ParamBounds<'tcx>,
1408 // Currently the only bound which is incompatible with other bounds is
1410 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1411 ty::each_bound_trait_and_supertraits(
1413 ¶m_bounds.trait_bounds[],
1415 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1416 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1417 span_err!(tcx.sess, span, E0129,
1418 "incompatible bounds on `{}`, \
1419 bound `{}` does not allow unsized type",
1420 param_ty.user_string(tcx),
1421 trait_ref.user_string(tcx));
1428 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1430 param_ty: ty::Ty<'tcx>,
1431 ast_bounds: &[ast::TyParamBound])
1432 -> ty::ParamBounds<'tcx>
1434 let astconv::PartitionedBounds { builtin_bounds,
1437 astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
1439 let mut projection_bounds = Vec::new();
1441 let trait_bounds: Vec<ty::PolyTraitRef> =
1442 trait_bounds.into_iter()
1444 astconv::instantiate_poly_trait_ref(ccx,
1448 &mut projection_bounds)
1451 let region_bounds: Vec<ty::Region> =
1452 region_bounds.into_iter()
1453 .map(|r| ast_region_to_region(ccx.tcx, r))
1456 region_bounds: region_bounds,
1457 builtin_bounds: builtin_bounds,
1458 trait_bounds: trait_bounds,
1459 projection_bounds: projection_bounds,
1463 fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1466 ast_generics: &ast::Generics,
1468 -> ty::TypeScheme<'tcx> {
1469 for i in decl.inputs.iter() {
1470 match (*i).pat.node {
1471 ast::PatIdent(_, _, _) => (),
1472 ast::PatWild(ast::PatWildSingle) => (),
1474 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1475 "patterns aren't allowed in foreign function declarations");
1480 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1482 ty::Generics::empty());
1483 let rb = BindingRscope::new();
1484 let input_tys = decl.inputs
1486 .map(|a| ty_of_arg(ccx, &rb, a, None))
1489 let output = match decl.output {
1490 ast::Return(ref ty) =>
1491 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1492 ast::DefaultReturn(..) =>
1493 ty::FnConverging(ty::mk_nil(ccx.tcx)),
1494 ast::NoReturn(..) =>
1498 let t_fn = ty::mk_bare_fn(
1501 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1503 unsafety: ast::Unsafety::Unsafe,
1504 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1506 variadic: decl.variadic}),
1508 let scheme = TypeScheme {
1509 generics: ty_generics_for_fn_or_method,
1513 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1517 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1518 ty_generics: &ty::Generics<'tcx>)
1519 -> subst::Substs<'tcx>
1522 ty_generics.types.map(
1523 |def| ty::mk_param_from_def(ccx.tcx, def));
1526 ty_generics.regions.map(
1527 |def| def.to_early_bound_region());
1529 subst::Substs::new(types, regions)
1532 /// Verifies that the explicit self type of a method matches the impl
1533 /// or trait. This is a bit weird but basically because right now we
1534 /// don't handle the general case, but instead map it to one of
1535 /// several pre-defined options using various heuristics, this method
1536 /// comes back to check after the fact that explicit type the user
1537 /// wrote actually matches what the pre-defined option said.
1538 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1539 ccx: &CollectCtxt<'a, 'tcx>,
1541 required_type: Ty<'tcx>,
1542 explicit_self: &ast::ExplicitSelf,
1543 body_id: ast::NodeId)
1545 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1546 let typ = ccx.to_ty(rs, &**ast_type);
1547 let base_type = match typ.sty {
1548 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1549 ty::ty_uniq(typ) => typ,
1553 let body_scope = region::CodeExtent::from_node_id(body_id);
1555 // "Required type" comes from the trait definition. It may
1556 // contain late-bound regions from the method, but not the
1557 // trait (since traits only have early-bound region
1559 assert!(!base_type.has_regions_escaping_depth(1));
1560 let required_type_free =
1561 liberate_early_bound_regions(
1562 ccx.tcx, body_scope,
1563 &ty::liberate_late_bound_regions(
1564 ccx.tcx, body_scope, &ty::Binder(required_type)));
1566 // The "base type" comes from the impl. It too may have late-bound
1567 // regions from the method.
1568 assert!(!base_type.has_regions_escaping_depth(1));
1569 let base_type_free =
1570 liberate_early_bound_regions(
1571 ccx.tcx, body_scope,
1572 &ty::liberate_late_bound_regions(
1573 ccx.tcx, body_scope, &ty::Binder(base_type)));
1575 debug!("required_type={} required_type_free={} \
1576 base_type={} base_type_free={}",
1577 required_type.repr(ccx.tcx),
1578 required_type_free.repr(ccx.tcx),
1579 base_type.repr(ccx.tcx),
1580 base_type_free.repr(ccx.tcx));
1581 let infcx = infer::new_infer_ctxt(ccx.tcx);
1582 drop(::require_same_types(ccx.tcx,
1589 format!("mismatched self type: expected `{}`",
1590 ppaux::ty_to_string(ccx.tcx, required_type))
1592 infcx.resolve_regions_and_report_errors(body_id);
1595 fn liberate_early_bound_regions<'tcx,T>(
1596 tcx: &ty::ctxt<'tcx>,
1597 scope: region::CodeExtent,
1600 where T : TypeFoldable<'tcx> + Repr<'tcx>
1603 * Convert early-bound regions into free regions; normally this is done by
1604 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1605 * method-self-type check is kind of hacky and done very early in the process,
1606 * before we really have a `ParameterEnvironment` to check.
1609 ty_fold::fold_regions(tcx, value, |region, _| {
1611 ty::ReEarlyBound(id, _, _, name) => {
1612 let def_id = local_def(id);
1613 ty::ReFree(ty::FreeRegion { scope: scope,
1614 bound_region: ty::BrNamed(def_id, name) })
1622 /// Checks that all the type parameters on an impl
1623 fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1624 ast_generics: &ast::Generics,
1625 impl_def_id: ast::DefId)
1627 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1628 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1630 // The trait reference is an input, so find all type parameters
1631 // reachable from there, to start (if this is an inherent impl,
1632 // then just examine the self type).
1633 let mut input_parameters: HashSet<_> =
1634 impl_trait_ref.iter()
1635 .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1636 .chain(Some(impl_scheme.ty).iter()) // Self type, always
1637 .flat_map(|t| t.walk())
1638 .filter_map(to_opt_param_ty)
1642 let num_inputs = input_parameters.len();
1644 let mut projection_predicates =
1645 impl_scheme.generics.predicates
1647 .filter_map(|predicate| {
1649 // Ignore higher-ranked binders. For the purposes
1650 // of this check, they don't matter because they
1651 // only affect named regions, and we're just
1652 // concerned about type parameters here.
1653 ty::Predicate::Projection(ref data) => Some(data.0.clone()),
1658 for projection in projection_predicates {
1659 // Special case: watch out for some kind of sneaky attempt
1660 // to project out an associated type defined by this very trait.
1661 if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
1665 let relies_only_on_inputs =
1666 projection.projection_ty.trait_ref.input_types().iter()
1667 .flat_map(|t| t.walk())
1668 .filter_map(to_opt_param_ty)
1669 .all(|t| input_parameters.contains(&t));
1671 if relies_only_on_inputs {
1672 input_parameters.extend(
1673 projection.ty.walk().filter_map(to_opt_param_ty));
1677 if input_parameters.len() == num_inputs {
1682 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1683 let param_ty = ty::ParamTy { space: TypeSpace,
1685 name: ty_param.ident.name };
1686 if !input_parameters.contains(¶m_ty) {
1687 if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1690 format!("the type parameter `{}` is not constrained by the \
1691 impl trait, self type, or predicates",
1692 param_ty.user_string(tcx)).as_slice());
1694 span_err!(tcx.sess, ty_param.span, E0207,
1695 "the type parameter `{}` is not constrained by the \
1696 impl trait, self type, or predicates",
1697 param_ty.user_string(tcx));
1700 format!("you can temporarily opt out of this rule by placing \
1701 the `#[old_impl_check]` attribute on the impl").as_slice());
1706 fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
1708 ty::ty_param(ref d) => Some(d.clone()),