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 {
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 {
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 {
531 for bound in &*ty_param.bounds {
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::ItemExternCrate(_) | ast::ItemUse(_) |
559 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
560 ast::ItemEnum(ref enum_definition, ref generics) => {
561 let scheme = ty_of_item(ccx, it);
562 write_ty_to_tcx(tcx, it.id, scheme.ty);
563 get_enum_variant_types(ccx,
565 enum_definition.variants.as_slice(),
573 // Create generics from the generics specified in the impl head.
574 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
576 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
577 write_ty_to_tcx(tcx, it.id, selfty);
581 .insert(local_def(it.id),
583 generics: ty_generics.clone(),
587 // If there is a trait reference, treat the methods as always public.
588 // This is to work around some incorrect behavior in privacy checking:
589 // when the method belongs to a trait, it should acquire the privacy
590 // from the trait, not the impl. Forcing the visibility to be public
591 // makes things sorta work.
592 let parent_visibility = if opt_trait_ref.is_some() {
598 let mut methods = Vec::new();
599 for impl_item in impl_items {
601 ast::MethodImplItem(ref method) => {
602 let body_id = method.pe_body().id;
603 check_method_self_type(ccx,
604 &BindingRscope::new(),
606 method.pe_explicit_self(),
608 methods.push(&**method);
610 ast::TypeImplItem(ref typedef) => {
611 if opt_trait_ref.is_none() {
612 span_err!(tcx.sess, typedef.span, E0202,
613 "associated items are not allowed in inherent impls");
616 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
619 .insert(local_def(typedef.id),
621 generics: ty::Generics::empty(),
624 write_ty_to_tcx(ccx.tcx, typedef.id, typ);
626 let associated_type = Rc::new(ty::AssociatedType {
627 name: typedef.ident.name,
629 def_id: local_def(typedef.id),
630 container: ty::ImplContainer(local_def(it.id)),
632 tcx.impl_or_trait_items
634 .insert(local_def(typedef.id),
635 ty::TypeTraitItem(associated_type));
641 ImplContainer(local_def(it.id)),
647 if let Some(ref trait_ref) = *opt_trait_ref {
648 astconv::instantiate_trait_ref(ccx,
655 enforce_impl_ty_params_are_constrained(ccx.tcx,
659 ast::ItemTrait(_, _, _, ref trait_methods) => {
660 let trait_def = trait_def_of_item(ccx, it);
662 debug!("trait_def: ident={} trait_def={}",
663 it.ident.repr(ccx.tcx),
664 trait_def.repr(ccx.tcx));
666 for trait_method in trait_methods {
667 let self_type = ty::mk_self_type(tcx);
668 match *trait_method {
669 ast::RequiredMethod(ref type_method) => {
670 let rscope = BindingRscope::new();
671 check_method_self_type(ccx,
674 &type_method.explicit_self,
677 ast::ProvidedMethod(ref method) => {
678 check_method_self_type(ccx,
679 &BindingRscope::new(),
681 method.pe_explicit_self(),
684 ast::TypeTraitItem(ref associated_type) => {
685 convert_associated_type(ccx,
692 // Run convert_methods on the provided methods.
693 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
695 TraitContainer(local_def(it.id)),
696 trait_methods.iter().filter_map(|m| match *m {
697 ast::RequiredMethod(_) => None,
698 ast::ProvidedMethod(ref m) => Some(&**m),
699 ast::TypeTraitItem(_) => None,
701 untransformed_rcvr_ty,
705 // We need to do this *after* converting methods, since
706 // convert_methods produces a tcache entry that is wrong for
707 // static trait methods. This is somewhat unfortunate.
708 collect_trait_methods(ccx, it.id, &*trait_def);
710 ast::ItemStruct(ref struct_def, _) => {
711 // Write the class type.
712 let scheme = ty_of_item(ccx, it);
713 write_ty_to_tcx(tcx, it.id, scheme.ty);
715 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
717 convert_struct(ccx, &**struct_def, scheme, it.id);
719 ast::ItemTy(_, ref generics) => {
720 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
721 let tpt = ty_of_item(ccx, it);
722 write_ty_to_tcx(tcx, it.id, tpt.ty);
725 // This call populates the type cache with the converted type
726 // of the item in passing. All we have to do here is to write
727 // it into the node type table.
728 let scheme = ty_of_item(ccx, it);
729 write_ty_to_tcx(tcx, it.id, scheme.ty);
734 fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
735 struct_def: &ast::StructDef,
736 scheme: ty::TypeScheme<'tcx>,
740 // Write the type of each of the members and check for duplicate fields.
741 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
742 let field_tys = struct_def.fields.iter().map(|f| {
743 let result = convert_field(ccx, &scheme.generics, f, local_def(id));
745 if result.name != special_idents::unnamed_field.name {
746 let dup = match seen_fields.get(&result.name) {
748 span_err!(tcx.sess, f.span, E0124,
749 "field `{}` is already declared",
750 token::get_name(result.name));
751 span_note!(tcx.sess, *prev_span, "previously declared here");
756 // FIXME(#6393) this whole dup thing is just to satisfy
757 // the borrow checker :-(
759 seen_fields.insert(result.name, f.span);
766 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
768 let substs = mk_item_substs(ccx, &scheme.generics);
769 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
771 // If this struct is enum-like or tuple-like, create the type of its
773 match struct_def.ctor_id {
776 if struct_def.fields.len() == 0 {
778 write_ty_to_tcx(tcx, ctor_id, selfty);
780 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
781 } else if struct_def.fields[0].node.kind.is_unnamed() {
783 let inputs: Vec<_> = struct_def.fields.iter().map(
784 |field| (*tcx.tcache.borrow())[
785 local_def(field.node.id)].ty).collect();
786 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
790 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
791 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
793 generics: scheme.generics,
801 fn convert_foreign(ccx: &CollectCtxt, i: &ast::ForeignItem) {
802 // As above, this call populates the type table with the converted
803 // type of the foreign item. We simply write it into the node type
806 // For reasons I cannot fully articulate, I do so hate the AST
807 // map, and I regard each time that I use it as a personal and
808 // moral failing, but at the moment it seems like the only
809 // convenient way to extract the ABI. - ndm
810 let abi = ccx.tcx.map.get_foreign_abi(i.id);
812 let scheme = ty_of_foreign_item(ccx, i, abi);
813 write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
815 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
818 fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
819 trait_id: ast::DefId)
820 -> Rc<ty::TraitDef<'tcx>> {
821 if trait_id.krate != ast::LOCAL_CRATE {
822 return ty::lookup_trait_def(ccx.tcx, trait_id)
825 match ccx.tcx.map.get(trait_id.node) {
826 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
828 ccx.tcx.sess.bug(&format!("get_trait_def({}): not an item",
834 fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
836 -> Rc<ty::TraitDef<'tcx>>
838 let def_id = local_def(it.id);
840 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
844 let (unsafety, generics, bounds, items) = match it.node {
845 ast::ItemTrait(unsafety,
849 (unsafety, generics, supertraits, items.as_slice())
854 &format!("trait_def_of_item invoked on {:?}", s)[]);
858 let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
859 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
860 ccx.tcx.sess.span_err(
862 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
863 which traits can use parenthetical notation");
864 span_help!(ccx.tcx.sess, it.span,
865 "add `#![feature(unboxed_closures)]` to \
866 the crate attributes to use it");
869 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
871 let ty_generics = ty_generics_for_trait(ccx,
877 let self_param_ty = ty::ParamTy::for_self();
879 let bounds = compute_bounds(ccx,
880 self_param_ty.to_ty(ccx.tcx),
885 let associated_type_names: Vec<_> =
889 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
890 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
895 let trait_ref = Rc::new(ty::TraitRef {
900 let trait_def = Rc::new(ty::TraitDef {
901 paren_sugar: paren_sugar,
903 generics: ty_generics,
905 trait_ref: trait_ref,
906 associated_type_names: associated_type_names,
908 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
912 fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
913 generics: &ast::Generics)
914 -> subst::Substs<'tcx>
916 // Creates a no-op substitution for the trait's type parameters.
921 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
927 // Start with the generics in the type parameters...
932 .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
933 i as u32, def.ident.name))
936 // ...and also create the `Self` parameter.
937 let self_ty = ty::mk_self_type(ccx.tcx);
939 subst::Substs::new_trait(types, regions, self_ty)
943 fn ty_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item)
944 -> ty::TypeScheme<'tcx> {
945 let def_id = local_def(it.id);
947 if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
948 return scheme.clone();
951 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
952 let typ = ccx.to_ty(&ExplicitRscope, &**t);
953 let scheme = no_params(typ);
955 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
958 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
959 let ty_generics = ty_generics_for_fn_or_method(ccx,
961 ty::Generics::empty());
962 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
963 let scheme = TypeScheme {
964 generics: ty_generics,
965 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
967 debug!("type of {} (id {}) is {}",
968 token::get_ident(it.ident),
972 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
975 ast::ItemTy(ref t, ref generics) => {
976 match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
977 Some(scheme) => return scheme.clone(),
982 let ty = ccx.to_ty(&ExplicitRscope, &**t);
984 generics: ty_generics_for_type_or_impl(ccx, generics),
989 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
992 ast::ItemEnum(_, ref generics) => {
993 // Create a new generic polytype.
994 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
995 let substs = mk_item_substs(ccx, &ty_generics);
996 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
997 let scheme = TypeScheme {
998 generics: ty_generics,
1002 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
1005 ast::ItemTrait(..) => {
1006 tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
1008 ast::ItemStruct(_, ref generics) => {
1009 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1010 let substs = mk_item_substs(ccx, &ty_generics);
1011 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
1012 let scheme = TypeScheme {
1013 generics: ty_generics,
1017 tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
1020 ast::ItemExternCrate(_) | ast::ItemUse(_) |
1021 ast::ItemImpl(..) | ast::ItemMod(_) |
1022 ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
1026 fn ty_of_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1027 it: &ast::ForeignItem,
1028 abi: abi::Abi) -> ty::TypeScheme<'tcx>
1031 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1032 ty_of_foreign_fn_decl(ccx,
1038 ast::ForeignItemStatic(ref t, _) => {
1040 generics: ty::Generics::empty(),
1041 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
1047 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1048 generics: &ast::Generics)
1049 -> ty::Generics<'tcx> {
1052 &generics.lifetimes[],
1053 &generics.ty_params[],
1054 ty::Generics::empty(),
1055 &generics.where_clause)
1058 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1059 trait_id: ast::NodeId,
1060 substs: &'tcx subst::Substs<'tcx>,
1061 ast_generics: &ast::Generics,
1062 trait_items: &[ast::TraitItem])
1063 -> ty::Generics<'tcx>
1065 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1066 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1071 &ast_generics.lifetimes[],
1072 &ast_generics.ty_params[],
1073 ty::Generics::empty(),
1074 &ast_generics.where_clause);
1076 // Add in the self type parameter.
1078 // Something of a hack: use the node id for the trait, also as
1079 // the node id for the Self type parameter.
1080 let param_id = trait_id;
1082 let self_trait_ref =
1083 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1086 let def = ty::TypeParameterDef {
1087 space: subst::SelfSpace,
1089 name: special_idents::type_self.name,
1090 def_id: local_def(param_id),
1091 bounds: ty::ParamBounds {
1092 region_bounds: vec!(),
1093 builtin_bounds: ty::empty_builtin_bounds(),
1094 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1095 projection_bounds: vec!(),
1100 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1102 generics.types.push(subst::SelfSpace, def);
1104 generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
1106 let assoc_predicates = predicates_for_associated_types(ccx,
1110 debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
1112 for assoc_predicate in assoc_predicates {
1113 generics.predicates.push(subst::TypeSpace, assoc_predicate);
1118 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1119 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1120 trait_items: &[ast::TraitItem])
1121 -> Vec<ty::Predicate<'tcx>>
1125 .flat_map(|trait_item| {
1126 let assoc_type_def = match *trait_item {
1127 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1128 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1129 return vec!().into_iter();
1133 let assoc_ty = ty::mk_projection(ccx.tcx,
1134 self_trait_ref.clone(),
1135 assoc_type_def.ident.name);
1137 let bounds = compute_bounds(ccx,
1139 assoc_type_def.bounds.as_slice(),
1140 SizedByDefault::Yes,
1141 assoc_type_def.span);
1143 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1149 fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1150 generics: &ast::Generics,
1151 base_generics: ty::Generics<'tcx>)
1152 -> ty::Generics<'tcx>
1154 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1158 &generics.ty_params[],
1160 &generics.where_clause)
1163 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1164 fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1165 bounds: &mut ty::BuiltinBounds,
1166 ast_bounds: &[ast::TyParamBound],
1169 // Try to find an unbound in bounds.
1170 let mut unbound = None;
1171 for ab in ast_bounds {
1172 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1173 if unbound.is_none() {
1174 assert!(ptr.bound_lifetimes.is_empty());
1175 unbound = Some(ptr.trait_ref.clone());
1177 span_err!(ccx.tcx.sess, span, E0203,
1178 "type parameter has more than one relaxed default \
1179 bound, only one is supported");
1184 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1187 // FIXME(#8559) currently requires the unbound to be built-in.
1188 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1190 Ok(kind_id) if trait_def_id != kind_id => {
1191 ccx.tcx.sess.span_warn(span,
1192 "default bound relaxed for a type parameter, but \
1193 this does nothing because the given bound is not \
1194 a default. Only `?Sized` is supported");
1195 ty::try_add_builtin_trait(ccx.tcx,
1202 _ if kind_id.is_ok() => {
1203 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1205 // No lang item for Sized, so we can't add it as a bound.
1210 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1211 space: subst::ParamSpace,
1212 lifetime_defs: &[ast::LifetimeDef],
1213 types: &[ast::TyParam],
1214 base_generics: ty::Generics<'tcx>,
1215 where_clause: &ast::WhereClause)
1216 -> ty::Generics<'tcx>
1218 let mut result = base_generics;
1220 for (i, l) in lifetime_defs.iter().enumerate() {
1221 let bounds = l.bounds.iter()
1222 .map(|l| ast_region_to_region(ccx.tcx, l))
1224 let def = ty::RegionParameterDef { name: l.lifetime.name,
1227 def_id: local_def(l.lifetime.id),
1229 debug!("ty_generics: def for region param: {:?}", def);
1230 result.regions.push(space, def);
1233 assert!(result.types.is_empty_in(space));
1235 // Now create the real type parameters.
1236 for (i, param) in types.iter().enumerate() {
1237 let def = get_or_create_type_parameter_def(ccx,
1241 debug!("ty_generics: def for type param: {}, {:?}",
1244 result.types.push(space, def);
1247 // Just for fun, also push the bounds from the type parameters
1248 // into the predicates list. This is currently kind of non-DRY.
1249 create_predicates(ccx.tcx, &mut result, space);
1251 // Add the bounds not associated with a type parameter
1252 for predicate in &where_clause.predicates {
1254 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1255 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1257 for bound in &*bound_pred.bounds {
1259 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1260 let mut projections = Vec::new();
1262 let trait_ref = astconv::instantiate_poly_trait_ref(
1270 result.predicates.push(space, trait_ref.as_predicate());
1272 for projection in &projections {
1273 result.predicates.push(space, projection.as_predicate());
1277 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1278 let region = ast_region_to_region(ccx.tcx, lifetime);
1279 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1280 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1286 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1287 let r1 = ast_region_to_region(ccx.tcx, ®ion_pred.lifetime);
1288 for bound in ®ion_pred.bounds {
1289 let r2 = ast_region_to_region(ccx.tcx, bound);
1290 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1291 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1295 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1297 ccx.tcx.sess.span_bug(eq_pred.span,
1298 "Equality constraints are not yet \
1299 implemented (#20041)")
1306 fn create_predicates<'tcx>(
1307 tcx: &ty::ctxt<'tcx>,
1308 result: &mut ty::Generics<'tcx>,
1309 space: subst::ParamSpace)
1311 for type_param_def in result.types.get_slice(space) {
1312 let param_ty = ty::mk_param_from_def(tcx, type_param_def);
1313 for predicate in ty::predicates(tcx, param_ty, &type_param_def.bounds) {
1314 result.predicates.push(space, predicate);
1318 for region_param_def in result.regions.get_slice(space) {
1319 let region = region_param_def.to_early_bound_region();
1320 for &bound_region in ®ion_param_def.bounds {
1321 // account for new binder introduced in the predicate below; no need
1322 // to shift `region` because it is never a late-bound region
1323 let bound_region = ty_fold::shift_region(bound_region, 1);
1324 result.predicates.push(
1326 ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
1332 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1333 space: subst::ParamSpace,
1334 param: &ast::TyParam,
1336 -> ty::TypeParameterDef<'tcx>
1338 match ccx.tcx.ty_param_defs.borrow().get(¶m.id) {
1339 Some(d) => { return (*d).clone(); }
1343 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1344 let bounds = compute_bounds(ccx,
1345 param_ty.to_ty(ccx.tcx),
1347 SizedByDefault::Yes,
1349 let default = match param.default {
1352 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1353 let cur_idx = index;
1355 ty::walk_ty(ty, |t| {
1357 ty::ty_param(p) => if p.idx > cur_idx {
1358 span_err!(ccx.tcx.sess, path.span, E0128,
1359 "type parameters with a default cannot use \
1360 forward declared identifiers");
1370 let def = ty::TypeParameterDef {
1373 name: param.ident.name,
1374 def_id: local_def(param.id),
1379 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1384 enum SizedByDefault { Yes, No }
1386 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1387 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1388 /// built-in trait (formerly known as kind): Send.
1389 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1390 param_ty: ty::Ty<'tcx>,
1391 ast_bounds: &[ast::TyParamBound],
1392 sized_by_default: SizedByDefault,
1394 -> ty::ParamBounds<'tcx>
1396 let mut param_bounds = conv_param_bounds(ccx,
1401 if let SizedByDefault::Yes = sized_by_default {
1402 add_unsized_bound(ccx,
1403 &mut param_bounds.builtin_bounds,
1407 check_bounds_compatible(ccx.tcx,
1413 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1418 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
1420 param_bounds: &ty::ParamBounds<'tcx>,
1422 // Currently the only bound which is incompatible with other bounds is
1424 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1425 ty::each_bound_trait_and_supertraits(
1427 ¶m_bounds.trait_bounds[],
1429 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
1430 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1431 span_err!(tcx.sess, span, E0129,
1432 "incompatible bounds on `{}`, \
1433 bound `{}` does not allow unsized type",
1434 param_ty.user_string(tcx),
1435 trait_ref.user_string(tcx));
1442 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1444 param_ty: ty::Ty<'tcx>,
1445 ast_bounds: &[ast::TyParamBound])
1446 -> ty::ParamBounds<'tcx>
1448 let astconv::PartitionedBounds { builtin_bounds,
1451 astconv::partition_bounds(ccx.tcx, span, ast_bounds.as_slice());
1453 let mut projection_bounds = Vec::new();
1455 let trait_bounds: Vec<ty::PolyTraitRef> =
1456 trait_bounds.into_iter()
1458 astconv::instantiate_poly_trait_ref(ccx,
1462 &mut projection_bounds)
1465 let region_bounds: Vec<ty::Region> =
1466 region_bounds.into_iter()
1467 .map(|r| ast_region_to_region(ccx.tcx, r))
1470 region_bounds: region_bounds,
1471 builtin_bounds: builtin_bounds,
1472 trait_bounds: trait_bounds,
1473 projection_bounds: projection_bounds,
1477 fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1480 ast_generics: &ast::Generics,
1482 -> ty::TypeScheme<'tcx> {
1483 for i in &decl.inputs {
1484 match (*i).pat.node {
1485 ast::PatIdent(_, _, _) => (),
1486 ast::PatWild(ast::PatWildSingle) => (),
1488 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1489 "patterns aren't allowed in foreign function declarations");
1494 let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
1496 ty::Generics::empty());
1497 let rb = BindingRscope::new();
1498 let input_tys = decl.inputs
1500 .map(|a| ty_of_arg(ccx, &rb, a, None))
1503 let output = match decl.output {
1504 ast::Return(ref ty) =>
1505 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1506 ast::DefaultReturn(..) =>
1507 ty::FnConverging(ty::mk_nil(ccx.tcx)),
1508 ast::NoReturn(..) =>
1512 let t_fn = ty::mk_bare_fn(
1515 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1517 unsafety: ast::Unsafety::Unsafe,
1518 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1520 variadic: decl.variadic}),
1522 let scheme = TypeScheme {
1523 generics: ty_generics_for_fn_or_method,
1527 ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
1531 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1532 ty_generics: &ty::Generics<'tcx>)
1533 -> subst::Substs<'tcx>
1536 ty_generics.types.map(
1537 |def| ty::mk_param_from_def(ccx.tcx, def));
1540 ty_generics.regions.map(
1541 |def| def.to_early_bound_region());
1543 subst::Substs::new(types, regions)
1546 /// Verifies that the explicit self type of a method matches the impl
1547 /// or trait. This is a bit weird but basically because right now we
1548 /// don't handle the general case, but instead map it to one of
1549 /// several pre-defined options using various heuristics, this method
1550 /// comes back to check after the fact that explicit type the user
1551 /// wrote actually matches what the pre-defined option said.
1552 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1553 ccx: &CollectCtxt<'a, 'tcx>,
1555 required_type: Ty<'tcx>,
1556 explicit_self: &ast::ExplicitSelf,
1557 body_id: ast::NodeId)
1559 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1560 let typ = ccx.to_ty(rs, &**ast_type);
1561 let base_type = match typ.sty {
1562 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1563 ty::ty_uniq(typ) => typ,
1567 let body_scope = region::CodeExtent::from_node_id(body_id);
1569 // "Required type" comes from the trait definition. It may
1570 // contain late-bound regions from the method, but not the
1571 // trait (since traits only have early-bound region
1573 assert!(!base_type.has_regions_escaping_depth(1));
1574 let required_type_free =
1575 liberate_early_bound_regions(
1576 ccx.tcx, body_scope,
1577 &ty::liberate_late_bound_regions(
1578 ccx.tcx, body_scope, &ty::Binder(required_type)));
1580 // The "base type" comes from the impl. It too may have late-bound
1581 // regions from the method.
1582 assert!(!base_type.has_regions_escaping_depth(1));
1583 let base_type_free =
1584 liberate_early_bound_regions(
1585 ccx.tcx, body_scope,
1586 &ty::liberate_late_bound_regions(
1587 ccx.tcx, body_scope, &ty::Binder(base_type)));
1589 debug!("required_type={} required_type_free={} \
1590 base_type={} base_type_free={}",
1591 required_type.repr(ccx.tcx),
1592 required_type_free.repr(ccx.tcx),
1593 base_type.repr(ccx.tcx),
1594 base_type_free.repr(ccx.tcx));
1595 let infcx = infer::new_infer_ctxt(ccx.tcx);
1596 drop(::require_same_types(ccx.tcx,
1603 format!("mismatched self type: expected `{}`",
1604 ppaux::ty_to_string(ccx.tcx, required_type))
1606 infcx.resolve_regions_and_report_errors(body_id);
1609 fn liberate_early_bound_regions<'tcx,T>(
1610 tcx: &ty::ctxt<'tcx>,
1611 scope: region::CodeExtent,
1614 where T : TypeFoldable<'tcx> + Repr<'tcx>
1617 * Convert early-bound regions into free regions; normally this is done by
1618 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1619 * method-self-type check is kind of hacky and done very early in the process,
1620 * before we really have a `ParameterEnvironment` to check.
1623 ty_fold::fold_regions(tcx, value, |region, _| {
1625 ty::ReEarlyBound(id, _, _, name) => {
1626 let def_id = local_def(id);
1627 ty::ReFree(ty::FreeRegion { scope: scope,
1628 bound_region: ty::BrNamed(def_id, name) })
1636 /// Checks that all the type parameters on an impl
1637 fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1638 ast_generics: &ast::Generics,
1639 impl_def_id: ast::DefId)
1641 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1642 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1644 // The trait reference is an input, so find all type parameters
1645 // reachable from there, to start (if this is an inherent impl,
1646 // then just examine the self type).
1647 let mut input_parameters: HashSet<_> =
1648 impl_trait_ref.iter()
1649 .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1650 .chain(Some(impl_scheme.ty).iter()) // Self type, always
1651 .flat_map(|t| t.walk())
1652 .filter_map(to_opt_param_ty)
1656 let num_inputs = input_parameters.len();
1658 let mut projection_predicates =
1659 impl_scheme.generics.predicates
1661 .filter_map(|predicate| {
1663 // Ignore higher-ranked binders. For the purposes
1664 // of this check, they don't matter because they
1665 // only affect named regions, and we're just
1666 // concerned about type parameters here.
1667 ty::Predicate::Projection(ref data) => Some(data.0.clone()),
1672 for projection in projection_predicates {
1673 // Special case: watch out for some kind of sneaky attempt
1674 // to project out an associated type defined by this very trait.
1675 if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
1679 let relies_only_on_inputs =
1680 projection.projection_ty.trait_ref.input_types().iter()
1681 .flat_map(|t| t.walk())
1682 .filter_map(to_opt_param_ty)
1683 .all(|t| input_parameters.contains(&t));
1685 if relies_only_on_inputs {
1686 input_parameters.extend(
1687 projection.ty.walk().filter_map(to_opt_param_ty));
1691 if input_parameters.len() == num_inputs {
1696 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1697 let param_ty = ty::ParamTy { space: TypeSpace,
1699 name: ty_param.ident.name };
1700 if !input_parameters.contains(¶m_ty) {
1701 if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1704 format!("the type parameter `{}` is not constrained by the \
1705 impl trait, self type, or predicates",
1706 param_ty.user_string(tcx)).as_slice());
1708 span_err!(tcx.sess, ty_param.span, E0207,
1709 "the type parameter `{}` is not constrained by the \
1710 impl trait, self type, or predicates",
1711 param_ty.user_string(tcx));
1714 format!("you can temporarily opt out of this rule by placing \
1715 the `#[old_impl_check]` attribute on the impl").as_slice());
1720 fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
1722 ty::ty_param(ref d) => Some(d.clone()),