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 type schemes. This means that they are
24 generic types that may have type parameters. TypeSchemes are
25 represented by an instance of `ty::TypeScheme`. This combines the
26 core type along with a list of the bounds for each parameter. Type
27 parameters themselves are represented as `ty_param()` instances.
29 The phasing of type conversion is somewhat complicated. There is no
30 clear set of phases we can enforce (e.g., converting traits first,
31 then types, or something like that) because the user can introduce
32 arbitrary interdependencies. So instead we generally convert things
33 lazilly and on demand, and include logic that checks for cycles.
34 Demand is driven by calls to `AstConv::get_item_type_scheme` or
35 `AstConv::lookup_trait_def`.
37 Currently, we "convert" types and traits in three phases (note that
38 conversion only affects the types of items / enum variants / methods;
39 it does not e.g. compute the types of individual expressions):
45 Conversion itself is done by simply walking each of the items in turn
46 and invoking an appropriate function (e.g., `trait_def_of_item` or
47 `convert_item`). However, it is possible that while converting an
48 item, we may need to compute the *type scheme* or *trait definition*
51 There are some shortcomings in this design:
53 - Before walking the set of supertraits for a given trait, you must
54 call `ensure_super_predicates` on that trait def-id. Otherwise,
55 `lookup_super_predicates` will result in ICEs.
56 - Because the type scheme includes defaults, cycles through type
57 parameter defaults are illegal even if those defaults are never
58 employed. This is not necessarily a bug.
59 - The phasing of trait definitions before type definitions does not
60 seem to be necessary, sufficient, or particularly helpful, given that
61 processing a trait definition can trigger processing a type def and
62 vice versa. However, if I remove it, I get ICEs, so some more work is
63 needed in that area. -nmatsakis
67 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
69 use constrained_type_params as ctp;
70 use middle::lang_items::SizedTraitLangItem;
71 use middle::free_region::FreeRegionMap;
73 use middle::resolve_lifetime;
74 use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
75 use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
76 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
77 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
81 use util::common::{ErrorReported, memoized};
82 use util::nodemap::{FnvHashMap, FnvHashSet};
85 use std::cell::{Cell, RefCell};
86 use std::collections::HashSet;
91 use syntax::ast_util::local_def;
92 use syntax::codemap::Span;
93 use syntax::parse::token::special_idents;
94 use syntax::parse::token;
98 ///////////////////////////////////////////////////////////////////////////
101 pub fn collect_item_types(tcx: &ty::ctxt) {
102 let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
104 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
105 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
107 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
108 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
111 ///////////////////////////////////////////////////////////////////////////
113 struct CrateCtxt<'a,'tcx:'a> {
114 tcx: &'a ty::ctxt<'tcx>,
116 // This stack is used to identify cycles in the user's source.
117 // Note that these cycles can cross multiple items.
118 stack: RefCell<Vec<AstConvRequest>>,
121 /// Context specific to some particular item. This is what implements
122 /// AstConv. It has information about the predicates that are defined
123 /// on the trait. Unfortunately, this predicate information is
124 /// available in various different forms at various points in the
125 /// process. So we can't just store a pointer to e.g. the AST or the
126 /// parsed ty form, we have to be more flexible. To this end, the
127 /// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
128 /// that it uses to satisfy `get_type_parameter_bounds` requests.
129 /// This object might draw the information from the AST
130 /// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
131 /// or both (a tuple).
132 struct ItemCtxt<'a,'tcx:'a> {
133 ccx: &'a CrateCtxt<'a,'tcx>,
134 param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
137 #[derive(Copy, Clone, PartialEq, Eq)]
138 enum AstConvRequest {
139 GetItemTypeScheme(ast::DefId),
140 GetTraitDef(ast::DefId),
141 EnsureSuperPredicates(ast::DefId),
142 GetTypeParameterBounds(ast::NodeId),
145 ///////////////////////////////////////////////////////////////////////////
146 // First phase: just collect *trait definitions* -- basically, the set
147 // of type parameters and supertraits. This is information we need to
148 // know later when parsing field defs.
150 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
151 ccx: &'a CrateCtxt<'a, 'tcx>
154 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
155 fn visit_item(&mut self, i: &ast::Item) {
157 ast::ItemTrait(..) => {
158 // computing the trait def also fills in the table
159 let _ = trait_def_of_item(self.ccx, i);
164 visit::walk_item(self, i);
168 ///////////////////////////////////////////////////////////////////////////
169 // Second phase: collection proper.
171 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
172 ccx: &'a CrateCtxt<'a, 'tcx>
175 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
176 fn visit_item(&mut self, i: &ast::Item) {
177 convert_item(self.ccx, i);
178 visit::walk_item(self, i);
180 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
181 convert_foreign_item(self.ccx, i);
182 visit::walk_foreign_item(self, i);
186 ///////////////////////////////////////////////////////////////////////////
187 // Utility types and common code for the above passes.
189 impl<'a,'tcx> CrateCtxt<'a,'tcx> {
190 fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
191 ItemCtxt { ccx: self, param_bounds: param_bounds }
194 fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
195 let def_id = local_def(method_id);
196 match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
197 ty::MethodTraitItem(ref mty) => mty.clone(),
199 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
204 fn cycle_check<F,R>(&self,
206 request: AstConvRequest,
208 -> Result<R,ErrorReported>
209 where F: FnOnce() -> Result<R,ErrorReported>
212 let mut stack = self.stack.borrow_mut();
213 match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
216 let cycle = &stack[i..];
217 self.report_cycle(span, cycle);
218 return Err(ErrorReported);
226 self.stack.borrow_mut().pop();
230 fn report_cycle(&self,
232 cycle: &[AstConvRequest])
234 assert!(!cycle.is_empty());
237 span_err!(tcx.sess, span, E0391,
238 "unsupported cyclic reference between types/traits detected");
241 AstConvRequest::GetItemTypeScheme(def_id) |
242 AstConvRequest::GetTraitDef(def_id) => {
244 &format!("the cycle begins when processing `{}`...",
245 tcx.item_path_str(def_id)));
247 AstConvRequest::EnsureSuperPredicates(def_id) => {
249 &format!("the cycle begins when computing the supertraits of `{}`...",
250 tcx.item_path_str(def_id)));
252 AstConvRequest::GetTypeParameterBounds(id) => {
253 let def = tcx.type_parameter_def(id);
255 &format!("the cycle begins when computing the bounds \
256 for type parameter `{}`...",
261 for request in &cycle[1..] {
263 AstConvRequest::GetItemTypeScheme(def_id) |
264 AstConvRequest::GetTraitDef(def_id) => {
266 &format!("...which then requires processing `{}`...",
267 tcx.item_path_str(def_id)));
269 AstConvRequest::EnsureSuperPredicates(def_id) => {
271 &format!("...which then requires computing the supertraits of `{}`...",
272 tcx.item_path_str(def_id)));
274 AstConvRequest::GetTypeParameterBounds(id) => {
275 let def = tcx.type_parameter_def(id);
277 &format!("...which then requires computing the bounds \
278 for type parameter `{}`...",
285 AstConvRequest::GetItemTypeScheme(def_id) |
286 AstConvRequest::GetTraitDef(def_id) => {
288 &format!("...which then again requires processing `{}`, completing the cycle.",
289 tcx.item_path_str(def_id)));
291 AstConvRequest::EnsureSuperPredicates(def_id) => {
293 &format!("...which then again requires computing the supertraits of `{}`, \
294 completing the cycle.",
295 tcx.item_path_str(def_id)));
297 AstConvRequest::GetTypeParameterBounds(id) => {
298 let def = tcx.type_parameter_def(id);
300 &format!("...which then again requires computing the bounds \
301 for type parameter `{}`, completing the cycle.",
307 /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
308 fn get_trait_def(&self, trait_id: ast::DefId)
309 -> &'tcx ty::TraitDef<'tcx>
313 if trait_id.krate != ast::LOCAL_CRATE {
314 return tcx.lookup_trait_def(trait_id)
317 let item = match tcx.map.get(trait_id.node) {
318 ast_map::NodeItem(item) => item,
319 _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
322 trait_def_of_item(self, &*item)
325 /// Ensure that the (transitive) super predicates for
326 /// `trait_def_id` are available. This will report a cycle error
327 /// if a trait `X` (transitively) extends itself in some form.
328 fn ensure_super_predicates(&self, span: Span, trait_def_id: ast::DefId)
329 -> Result<(), ErrorReported>
331 self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || {
332 let def_ids = ensure_super_predicates_step(self, trait_def_id);
334 for def_id in def_ids {
335 try!(self.ensure_super_predicates(span, def_id));
343 impl<'a,'tcx> ItemCtxt<'a,'tcx> {
344 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
345 ast_ty_to_ty(self, rs, ast_ty)
349 impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
350 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
352 fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
353 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
355 self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
356 Ok(type_scheme_of_def_id(self.ccx, id))
360 fn get_trait_def(&self, span: Span, id: ast::DefId)
361 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
363 self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
364 Ok(self.ccx.get_trait_def(id))
368 fn ensure_super_predicates(&self,
370 trait_def_id: ast::DefId)
371 -> Result<(), ErrorReported>
373 debug!("ensure_super_predicates(trait_def_id={:?})",
376 self.ccx.ensure_super_predicates(span, trait_def_id)
380 fn get_type_parameter_bounds(&self,
382 node_id: ast::NodeId)
383 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
385 self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
386 let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id)
388 .filter_map(|p| p.to_opt_poly_trait_ref())
394 fn trait_defines_associated_type_named(&self,
395 trait_def_id: ast::DefId,
396 assoc_name: ast::Name)
399 if trait_def_id.krate == ast::LOCAL_CRATE {
400 trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
402 let trait_def = self.tcx().lookup_trait_def(trait_def_id);
403 trait_def.associated_type_names.contains(&assoc_name)
407 fn ty_infer(&self, _default: Option<Ty<'tcx>>, span: Span) -> Ty<'tcx> {
408 span_err!(self.tcx().sess, span, E0121,
409 "the type placeholder `_` is not allowed within types on item signatures");
413 fn projected_ty(&self,
415 trait_ref: ty::TraitRef<'tcx>,
416 item_name: ast::Name)
419 self.tcx().mk_projection(trait_ref, item_name)
423 /// Interface used to find the bounds on a type parameter from within
424 /// an `ItemCtxt`. This allows us to use multiple kinds of sources.
425 trait GetTypeParameterBounds<'tcx> {
426 fn get_type_parameter_bounds(&self,
427 astconv: &AstConv<'tcx>,
429 node_id: ast::NodeId)
430 -> Vec<ty::Predicate<'tcx>>;
433 /// Find bounds from both elements of the tuple.
434 impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
435 where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
437 fn get_type_parameter_bounds(&self,
438 astconv: &AstConv<'tcx>,
440 node_id: ast::NodeId)
441 -> Vec<ty::Predicate<'tcx>>
443 let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
444 v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id));
449 /// Empty set of bounds.
450 impl<'tcx> GetTypeParameterBounds<'tcx> for () {
451 fn get_type_parameter_bounds(&self,
452 _astconv: &AstConv<'tcx>,
454 _node_id: ast::NodeId)
455 -> Vec<ty::Predicate<'tcx>>
461 /// Find bounds from the parsed and converted predicates. This is
462 /// used when converting methods, because by that time the predicates
463 /// from the trait/impl have been fully converted.
464 impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
465 fn get_type_parameter_bounds(&self,
466 astconv: &AstConv<'tcx>,
468 node_id: ast::NodeId)
469 -> Vec<ty::Predicate<'tcx>>
471 let def = astconv.tcx().type_parameter_def(node_id);
475 .filter(|predicate| {
477 ty::Predicate::Trait(ref data) => {
478 data.skip_binder().self_ty().is_param(def.space, def.index)
480 ty::Predicate::TypeOutlives(ref data) => {
481 data.skip_binder().0.is_param(def.space, def.index)
483 ty::Predicate::Equate(..) |
484 ty::Predicate::RegionOutlives(..) |
485 ty::Predicate::Projection(..) => {
495 /// Find bounds from ast::Generics. This requires scanning through the
496 /// AST. We do this to avoid having to convert *all* the bounds, which
497 /// would create artificial cycles. Instead we can only convert the
498 /// bounds for those a type parameter `X` if `X::Foo` is used.
499 impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
500 fn get_type_parameter_bounds(&self,
501 astconv: &AstConv<'tcx>,
503 node_id: ast::NodeId)
504 -> Vec<ty::Predicate<'tcx>>
506 // In the AST, bounds can derive from two places. Either
507 // written inline like `<T:Foo>` or in a where clause like
510 let def = astconv.tcx().type_parameter_def(node_id);
511 let ty = astconv.tcx().mk_param_from_def(&def);
516 .filter(|p| p.id == node_id)
517 .flat_map(|p| p.bounds.iter())
518 .flat_map(|b| predicates_from_bound(astconv, ty, b));
520 let from_where_clauses =
524 .filter_map(|wp| match *wp {
525 ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
528 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
529 .flat_map(|bp| bp.bounds.iter())
530 .flat_map(|b| predicates_from_bound(astconv, ty, b));
532 from_ty_params.chain(from_where_clauses).collect()
536 /// Tests whether this is the AST for a reference to the type
537 /// parameter with id `param_id`. We use this so as to avoid running
538 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
539 /// conversion of the type to avoid inducing unnecessary cycles.
540 fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
542 param_id: ast::NodeId)
545 if let ast::TyPath(None, _) = ast_ty.node {
546 let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
547 match path_res.base_def {
548 def::DefSelfTy(Some(def_id), None) => {
549 path_res.depth == 0 && def_id.node == param_id
551 def::DefTyParam(_, _, def_id, _) => {
552 path_res.depth == 0 && def_id == local_def(param_id)
563 fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
564 enum_scheme: ty::TypeScheme<'tcx>,
565 enum_predicates: ty::GenericPredicates<'tcx>,
566 variants: &[P<ast::Variant>]) {
568 let icx = ccx.icx(&enum_predicates);
570 // Create a set of parameter types shared among all the variants.
571 for variant in variants {
572 let variant_def_id = local_def(variant.node.id);
574 // Nullary enum constructors get turned into constants; n-ary enum
575 // constructors get turned into functions.
576 let result_ty = match variant.node.kind {
577 ast::TupleVariantKind(ref args) if !args.is_empty() => {
578 let rs = ExplicitRscope;
579 let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
580 tcx.mk_ctor_fn(variant_def_id, &input_tys, enum_scheme.ty)
583 ast::TupleVariantKind(_) => {
587 ast::StructVariantKind(ref struct_def) => {
588 convert_struct(ccx, &**struct_def, enum_scheme.clone(),
589 enum_predicates.clone(), variant.node.id);
594 let variant_scheme = TypeScheme {
595 generics: enum_scheme.generics.clone(),
599 tcx.register_item_type(variant_def_id, variant_scheme.clone());
600 tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
601 write_ty_to_tcx(tcx, variant.node.id, result_ty);
605 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
606 container: ImplOrTraitItemContainer,
607 sig: &ast::MethodSig,
610 vis: ast::Visibility,
611 untransformed_rcvr_ty: Ty<'tcx>,
612 rcvr_ty_generics: &ty::Generics<'tcx>,
613 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
614 let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics);
616 let ty_generic_predicates =
617 ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
619 let (fty, explicit_self_category) =
620 astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
621 sig, untransformed_rcvr_ty);
623 let def_id = local_def(id);
624 let ty_method = ty::Method::new(ident.name,
626 ty_generic_predicates,
628 explicit_self_category,
634 let fty = ccx.tcx.mk_fn(Some(def_id),
635 ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
636 debug!("method {} (id {}) has type {:?}",
638 ccx.tcx.register_item_type(def_id, TypeScheme {
639 generics: ty_method.generics.clone(),
642 ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
644 write_ty_to_tcx(ccx.tcx, id, fty);
646 debug!("writing method type: def_id={:?} mty={:?}",
649 ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
650 ty::MethodTraitItem(Rc::new(ty_method)));
653 fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
654 struct_generics: &ty::Generics<'tcx>,
655 struct_predicates: &ty::GenericPredicates<'tcx>,
656 v: &ast::StructField,
660 let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
661 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
663 /* add the field to the tcache */
664 ccx.tcx.register_item_type(local_def(v.node.id),
666 generics: struct_generics.clone(),
669 ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
670 struct_predicates.clone());
673 ast::NamedField(ident, visibility) => {
676 id: local_def(v.node.id),
681 ast::UnnamedField(visibility) => {
683 name: special_idents::unnamed_field.name,
684 id: local_def(v.node.id),
692 fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
693 container: ImplOrTraitItemContainer,
696 vis: ast::Visibility,
698 default: Option<&ast::Expr>)
700 ccx.tcx.predicates.borrow_mut().insert(local_def(id),
701 ty::GenericPredicates::empty());
703 write_ty_to_tcx(ccx.tcx, id, ty);
704 let default_id = default.map(|expr| local_def(expr.id));
706 let associated_const = Rc::new(ty::AssociatedConst {
709 def_id: local_def(id),
710 container: container,
714 ccx.tcx.impl_or_trait_items.borrow_mut()
715 .insert(local_def(id), ty::ConstTraitItem(associated_const));
718 fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
719 container: ImplOrTraitItemContainer,
722 vis: ast::Visibility,
723 ty: Option<Ty<'tcx>>)
725 let associated_type = Rc::new(ty::AssociatedType {
729 def_id: local_def(id),
732 ccx.tcx.impl_or_trait_items.borrow_mut()
733 .insert(local_def(id), ty::TypeTraitItem(associated_type));
736 fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
737 container: ImplOrTraitItemContainer,
739 untransformed_rcvr_ty: Ty<'tcx>,
740 rcvr_ty_generics: &ty::Generics<'tcx>,
741 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
742 where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
744 debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
745 rcvr_ty_predicates={:?})",
746 untransformed_rcvr_ty,
750 for (sig, id, ident, vis, _span) in methods {
757 untransformed_rcvr_ty,
763 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
765 generics: &ast::Generics,
766 thing: &'static str) {
767 let mut warn = false;
769 for ty_param in generics.ty_params.iter() {
770 for bound in ty_param.bounds.iter() {
772 ast::TraitTyParamBound(..) => {
775 ast::RegionTyParamBound(..) => { }
781 // According to accepted RFC #XXX, we should
782 // eventually accept these, but it will not be
783 // part of this PR. Still, convert to warning to
784 // make bootstrapping easier.
785 span_warn!(ccx.tcx.sess, span, E0122,
786 "trait bounds are not (yet) enforced \
792 fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
794 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
796 // These don't define types.
797 ast::ItemExternCrate(_) | ast::ItemUse(_) |
798 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
800 ast::ItemEnum(ref enum_definition, _) => {
801 let (scheme, predicates) = convert_typed_item(ccx, it);
802 write_ty_to_tcx(tcx, it.id, scheme.ty);
803 get_enum_variant_types(ccx,
806 &enum_definition.variants);
808 ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
810 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
815 tcx.record_trait_has_default_impl(trait_ref.def_id);
817 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
824 // Create generics from the generics specified in the impl head.
825 debug!("convert: ast_generics={:?}", generics);
826 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
827 let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
829 debug!("convert: impl_bounds={:?}", ty_predicates);
831 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
832 write_ty_to_tcx(tcx, it.id, selfty);
834 tcx.register_item_type(local_def(it.id),
835 TypeScheme { generics: ty_generics.clone(),
837 tcx.predicates.borrow_mut().insert(local_def(it.id),
838 ty_predicates.clone());
840 // If there is a trait reference, treat the methods as always public.
841 // This is to work around some incorrect behavior in privacy checking:
842 // when the method belongs to a trait, it should acquire the privacy
843 // from the trait, not the impl. Forcing the visibility to be public
844 // makes things sorta work.
845 let parent_visibility = if opt_trait_ref.is_some() {
851 // Convert all the associated consts.
852 // Also, check if there are any duplicate associated items
853 let mut seen_type_items = FnvHashSet();
854 let mut seen_value_items = FnvHashSet();
856 for impl_item in impl_items {
857 let seen_items = match impl_item.node {
858 ast::TypeImplItem(_) => &mut seen_type_items,
859 _ => &mut seen_value_items,
861 if !seen_items.insert(impl_item.ident.name) {
862 let desc = match impl_item.node {
863 ast::ConstImplItem(_, _) => "associated constant",
864 ast::TypeImplItem(_) => "associated type",
865 ast::MethodImplItem(ref sig, _) =>
866 match sig.explicit_self.node {
867 ast::SelfStatic => "associated function",
870 _ => "associated item",
873 span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
876 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
877 let ty = ccx.icx(&ty_predicates)
878 .to_ty(&ExplicitRscope, &*ty);
879 tcx.register_item_type(local_def(impl_item.id),
881 generics: ty_generics.clone(),
884 convert_associated_const(ccx, ImplContainer(local_def(it.id)),
885 impl_item.ident, impl_item.id,
886 impl_item.vis.inherit_from(parent_visibility),
891 // Convert all the associated types.
892 for impl_item in impl_items {
893 if let ast::TypeImplItem(ref ty) = impl_item.node {
894 if opt_trait_ref.is_none() {
895 span_err!(tcx.sess, impl_item.span, E0202,
896 "associated types are not allowed in inherent impls");
899 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
901 convert_associated_type(ccx, ImplContainer(local_def(it.id)),
902 impl_item.ident, impl_item.id, impl_item.vis,
907 let methods = impl_items.iter().filter_map(|ii| {
908 if let ast::MethodImplItem(ref sig, _) = ii.node {
909 // if the method specifies a visibility, use that, otherwise
910 // inherit the visibility from the impl (so `foo` in `pub impl
911 // { fn foo(); }` is public, but private in `impl { fn
913 let method_vis = ii.vis.inherit_from(parent_visibility);
914 Some((sig, ii.id, ii.ident, method_vis, ii.span))
920 ImplContainer(local_def(it.id)),
926 for impl_item in impl_items {
927 if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
928 let body_id = body.id;
929 check_method_self_type(ccx,
930 &BindingRscope::new(),
931 ccx.method_ty(impl_item.id),
938 if let &Some(ref ast_trait_ref) = opt_trait_ref {
939 tcx.impl_trait_refs.borrow_mut().insert(
941 Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
947 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None);
950 enforce_impl_params_are_constrained(tcx,
955 ast::ItemTrait(_, _, _, ref trait_items) => {
956 let trait_def = trait_def_of_item(ccx, it);
957 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
958 ccx.ensure_super_predicates(it.span, local_def(it.id));
959 convert_trait_predicates(ccx, it);
960 let trait_predicates = tcx.lookup_predicates(local_def(it.id));
962 debug!("convert: trait_bounds={:?}", trait_predicates);
964 // Convert all the associated types.
965 for trait_item in trait_items {
966 match trait_item.node {
967 ast::ConstTraitItem(ref ty, ref default) => {
968 let ty = ccx.icx(&trait_predicates)
969 .to_ty(&ExplicitRscope, ty);
970 tcx.register_item_type(local_def(trait_item.id),
972 generics: trait_def.generics.clone(),
975 convert_associated_const(ccx, TraitContainer(local_def(it.id)),
976 trait_item.ident, trait_item.id,
977 ast::Public, ty, default.as_ref().map(|d| &**d));
983 // Convert all the associated types.
984 for trait_item in trait_items {
985 match trait_item.node {
986 ast::TypeTraitItem(_, ref opt_ty) => {
987 let typ = opt_ty.as_ref().map({
988 |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
991 convert_associated_type(ccx, TraitContainer(local_def(it.id)),
992 trait_item.ident, trait_item.id, ast::Public,
999 let methods = trait_items.iter().filter_map(|ti| {
1000 let sig = match ti.node {
1001 ast::MethodTraitItem(ref sig, _) => sig,
1004 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
1007 // Run convert_methods on the trait methods.
1008 convert_methods(ccx,
1009 TraitContainer(local_def(it.id)),
1012 &trait_def.generics,
1015 // Add an entry mapping
1016 let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
1017 let def_id = local_def(trait_item.id);
1018 match trait_item.node {
1019 ast::ConstTraitItem(..) => {
1020 ty::ConstTraitItemId(def_id)
1022 ast::MethodTraitItem(..) => {
1023 ty::MethodTraitItemId(def_id)
1025 ast::TypeTraitItem(..) => {
1026 ty::TypeTraitItemId(def_id)
1030 tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids);
1032 // This must be done after `collect_trait_methods` so that
1033 // we have a method type stored for every method.
1034 for trait_item in trait_items {
1035 let sig = match trait_item.node {
1036 ast::MethodTraitItem(ref sig, _) => sig,
1039 check_method_self_type(ccx,
1040 &BindingRscope::new(),
1041 ccx.method_ty(trait_item.id),
1047 ast::ItemStruct(ref struct_def, _) => {
1048 // Write the class type.
1049 let (scheme, predicates) = convert_typed_item(ccx, it);
1050 write_ty_to_tcx(tcx, it.id, scheme.ty);
1051 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
1053 ast::ItemTy(_, ref generics) => {
1054 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
1055 let (scheme, _) = convert_typed_item(ccx, it);
1056 write_ty_to_tcx(tcx, it.id, scheme.ty);
1059 // This call populates the type cache with the converted type
1060 // of the item in passing. All we have to do here is to write
1061 // it into the node type table.
1062 let (scheme, _) = convert_typed_item(ccx, it);
1063 write_ty_to_tcx(tcx, it.id, scheme.ty);
1068 fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1069 struct_def: &ast::StructDef,
1070 scheme: ty::TypeScheme<'tcx>,
1071 predicates: ty::GenericPredicates<'tcx>,
1075 // Write the type of each of the members and check for duplicate fields.
1076 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
1077 let field_tys = struct_def.fields.iter().map(|f| {
1078 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
1080 if result.name != special_idents::unnamed_field.name {
1081 let dup = match seen_fields.get(&result.name) {
1082 Some(prev_span) => {
1083 span_err!(tcx.sess, f.span, E0124,
1084 "field `{}` is already declared",
1085 token::get_name(result.name));
1086 span_note!(tcx.sess, *prev_span, "previously declared here");
1091 // FIXME(#6393) this whole dup thing is just to satisfy
1092 // the borrow checker :-(
1094 seen_fields.insert(result.name, f.span);
1101 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1103 let substs = mk_item_substs(ccx, &scheme.generics);
1104 let selfty = tcx.mk_struct(local_def(id), tcx.mk_substs(substs));
1106 // If this struct is enum-like or tuple-like, create the type of its
1108 match struct_def.ctor_id {
1111 if struct_def.fields.is_empty() {
1113 write_ty_to_tcx(tcx, ctor_id, selfty);
1115 tcx.register_item_type(local_def(ctor_id), scheme);
1116 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1117 } else if struct_def.fields[0].node.kind.is_unnamed() {
1119 let inputs: Vec<_> =
1122 .map(|field| tcx.lookup_item_type(
1123 local_def(field.node.id)).ty)
1125 let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
1128 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1129 tcx.register_item_type(local_def(ctor_id),
1131 generics: scheme.generics,
1134 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1140 /// Ensures that the super-predicates of the trait with def-id
1141 /// trait_def_id are converted and stored. This does NOT ensure that
1142 /// the transitive super-predicates are converted; that is the job of
1143 /// the `ensure_super_predicates()` method in the `AstConv` impl
1144 /// above. Returns a list of trait def-ids that must be ensured as
1145 /// well to guarantee that the transitive superpredicates are
1147 fn ensure_super_predicates_step(ccx: &CrateCtxt,
1148 trait_def_id: ast::DefId)
1153 debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
1155 if trait_def_id.krate != ast::LOCAL_CRATE {
1156 // If this trait comes from an external crate, then all of the
1157 // supertraits it may depend on also must come from external
1158 // crates, and hence all of them already have their
1159 // super-predicates "converted" (and available from crate
1160 // meta-data), so there is no need to transitively test them.
1164 let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned();
1165 let superpredicates = superpredicates.unwrap_or_else(|| {
1166 let trait_node_id = trait_def_id.node;
1168 let item = match ccx.tcx.map.get(trait_node_id) {
1169 ast_map::NodeItem(item) => item,
1170 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1173 let (generics, bounds) = match item.node {
1174 ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
1175 _ => tcx.sess.span_bug(item.span,
1176 "ensure_super_predicates_step invoked on non-trait"),
1179 // In-scope when converting the superbounds for `Trait` are
1180 // that `Self:Trait` as well as any bounds that appear on the
1182 let trait_def = trait_def_of_item(ccx, item);
1183 let self_predicate = ty::GenericPredicates {
1184 predicates: VecPerParamSpace::new(vec![],
1185 vec![trait_def.trait_ref.to_predicate()],
1188 let scope = &(generics, &self_predicate);
1190 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1191 let self_param_ty = tcx.mk_self_type();
1192 let superbounds1 = compute_bounds(&ccx.icx(scope),
1198 let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
1200 // Convert any explicit superbounds in the where clause,
1201 // e.g. `trait Foo where Self : Bar`:
1202 let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
1204 // Combine the two lists to form the complete set of superbounds:
1205 let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
1206 let superpredicates = ty::GenericPredicates {
1207 predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
1209 debug!("superpredicates for trait {:?} = {:?}",
1213 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1218 let def_ids: Vec<_> = superpredicates.predicates
1220 .filter_map(|p| p.to_opt_poly_trait_ref())
1221 .map(|tr| tr.def_id())
1224 debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
1229 fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1231 -> &'tcx ty::TraitDef<'tcx>
1233 let def_id = local_def(it.id);
1236 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1240 let (unsafety, generics, items) = match it.node {
1241 ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
1242 _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
1245 let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
1246 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
1247 ccx.tcx.sess.span_err(
1249 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1250 which traits can use parenthetical notation");
1251 fileline_help!(ccx.tcx.sess, it.span,
1252 "add `#![feature(unboxed_closures)]` to \
1253 the crate attributes to use it");
1256 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1258 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1260 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1261 match trait_item.node {
1262 ast::TypeTraitItem(..) => Some(trait_item.ident.name),
1267 let trait_ref = ty::TraitRef {
1272 let trait_def = ty::TraitDef {
1273 paren_sugar: paren_sugar,
1275 generics: ty_generics,
1276 trait_ref: trait_ref,
1277 associated_type_names: associated_type_names,
1278 nonblanket_impls: RefCell::new(FnvHashMap()),
1279 blanket_impls: RefCell::new(vec![]),
1280 flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS)
1283 return tcx.intern_trait_def(trait_def);
1285 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1286 generics: &ast::Generics)
1291 // Creates a no-op substitution for the trait's type parameters.
1296 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1297 param_id: def.lifetime.id,
1300 name: def.lifetime.name
1304 // Start with the generics in the type parameters...
1309 .map(|(i, def)| tcx.mk_param(TypeSpace,
1310 i as u32, def.ident.name))
1313 // ...and also create the `Self` parameter.
1314 let self_ty = tcx.mk_self_type();
1316 Substs::new_trait(types, regions, self_ty)
1320 fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1321 trait_node_id: ast::NodeId,
1322 assoc_name: ast::Name)
1325 let item = match ccx.tcx.map.get(trait_node_id) {
1326 ast_map::NodeItem(item) => item,
1327 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1330 let trait_items = match item.node {
1331 ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
1332 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
1335 trait_items.iter().any(|trait_item| {
1336 match trait_item.node {
1337 ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
1343 fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
1345 let trait_def = trait_def_of_item(ccx, it);
1347 let def_id = local_def(it.id);
1349 let (generics, items) = match it.node {
1350 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1354 &format!("trait_def_of_item invoked on {:?}", s));
1358 let super_predicates = ccx.tcx.lookup_super_predicates(def_id);
1360 // `ty_generic_predicates` below will consider the bounds on the type
1361 // parameters (including `Self`) and the explicit where-clauses,
1362 // but to get the full set of predicates on a trait we need to add
1363 // in the supertrait bounds and anything declared on the
1364 // associated types.
1365 let mut base_predicates = super_predicates;
1367 // Add in a predicate that `Self:Trait` (where `Trait` is the
1368 // current trait). This is needed for builtin bounds.
1369 let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
1370 base_predicates.predicates.push(SelfSpace, self_predicate);
1372 // add in the explicit where-clauses
1373 let mut trait_predicates =
1374 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1376 let assoc_predicates = predicates_for_associated_types(ccx,
1379 trait_def.trait_ref,
1381 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
1383 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1384 assert!(prev_predicates.is_none());
1388 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1389 ast_generics: &ast::Generics,
1390 trait_predicates: &ty::GenericPredicates<'tcx>,
1391 self_trait_ref: ty::TraitRef<'tcx>,
1392 trait_items: &[P<ast::TraitItem>])
1393 -> Vec<ty::Predicate<'tcx>>
1395 trait_items.iter().flat_map(|trait_item| {
1396 let bounds = match trait_item.node {
1397 ast::TypeTraitItem(ref bounds, _) => bounds,
1399 return vec!().into_iter();
1403 let assoc_ty = ccx.tcx.mk_projection(self_trait_ref,
1404 trait_item.ident.name);
1406 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1409 SizedByDefault::Yes,
1412 bounds.predicates(ccx.tcx, assoc_ty).into_iter()
1417 fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1419 -> ty::TypeScheme<'tcx>
1421 if def_id.krate != ast::LOCAL_CRATE {
1422 return ccx.tcx.lookup_item_type(def_id);
1425 match ccx.tcx.map.find(def_id.node) {
1426 Some(ast_map::NodeItem(item)) => {
1427 type_scheme_of_item(ccx, &*item)
1429 Some(ast_map::NodeForeignItem(foreign_item)) => {
1430 let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
1431 type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
1434 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1435 in get_item_type_scheme(): {:?}",
1441 fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1443 -> ty::TypeScheme<'tcx>
1445 memoized(&ccx.tcx.tcache,
1447 |_| compute_type_scheme_of_item(ccx, it))
1450 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1452 -> ty::TypeScheme<'tcx>
1456 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
1457 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
1458 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1460 ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
1461 let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1462 let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
1463 let ty = tcx.mk_fn(Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
1464 ty::TypeScheme { ty: ty, generics: ty_generics }
1466 ast::ItemTy(ref t, ref generics) => {
1467 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1468 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
1469 ty::TypeScheme { ty: ty, generics: ty_generics }
1471 ast::ItemEnum(_, ref generics) => {
1472 // Create a new generic polytype.
1473 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1474 let substs = mk_item_substs(ccx, &ty_generics);
1475 let t = tcx.mk_enum(local_def(it.id), tcx.mk_substs(substs));
1476 ty::TypeScheme { ty: t, generics: ty_generics }
1478 ast::ItemStruct(_, ref generics) => {
1479 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1480 let substs = mk_item_substs(ccx, &ty_generics);
1481 let t = tcx.mk_struct(local_def(it.id), tcx.mk_substs(substs));
1482 ty::TypeScheme { ty: t, generics: ty_generics }
1484 ast::ItemDefaultImpl(..) |
1485 ast::ItemTrait(..) |
1488 ast::ItemForeignMod(..) |
1489 ast::ItemExternCrate(..) |
1491 ast::ItemMac(..) => {
1494 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1500 fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1502 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1506 let tag = type_scheme_of_item(ccx, it);
1507 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1508 let predicates = match it.node {
1509 ast::ItemStatic(..) | ast::ItemConst(..) => {
1510 ty::GenericPredicates::empty()
1512 ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
1513 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
1515 ast::ItemTy(_, ref generics) => {
1516 ty_generic_predicates_for_type_or_impl(ccx, generics)
1518 ast::ItemEnum(_, ref generics) => {
1519 ty_generic_predicates_for_type_or_impl(ccx, generics)
1521 ast::ItemStruct(_, ref generics) => {
1522 ty_generic_predicates_for_type_or_impl(ccx, generics)
1524 ast::ItemDefaultImpl(..) |
1525 ast::ItemTrait(..) |
1526 ast::ItemExternCrate(..) |
1530 ast::ItemForeignMod(..) |
1531 ast::ItemMac(..) => {
1534 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1539 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1540 predicates.clone());
1541 assert!(prev_predicates.is_none());
1544 if tcx.has_attr(local_def(it.id), "rustc_object_lifetime_default") {
1545 let object_lifetime_default_reprs: String =
1546 scheme.generics.types.iter()
1547 .map(|t| match t.object_lifetime_default {
1548 ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
1549 d => format!("{:?}", d),
1551 .collect::<Vec<String>>()
1554 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1557 return (scheme, predicates);
1560 fn type_scheme_of_foreign_item<'a, 'tcx>(
1561 ccx: &CrateCtxt<'a, 'tcx>,
1562 it: &ast::ForeignItem,
1564 -> ty::TypeScheme<'tcx>
1566 memoized(&ccx.tcx.tcache,
1568 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1571 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
1572 ccx: &CrateCtxt<'a, 'tcx>,
1573 it: &ast::ForeignItem,
1575 -> ty::TypeScheme<'tcx>
1578 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1579 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1581 ast::ForeignItemStatic(ref t, _) => {
1583 generics: ty::Generics::empty(),
1584 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1590 fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1591 it: &ast::ForeignItem)
1593 // For reasons I cannot fully articulate, I do so hate the AST
1594 // map, and I regard each time that I use it as a personal and
1595 // moral failing, but at the moment it seems like the only
1596 // convenient way to extract the ABI. - ndm
1598 let abi = tcx.map.get_foreign_abi(it.id);
1600 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1601 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1603 let predicates = match it.node {
1604 ast::ForeignItemFn(_, ref generics) => {
1605 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
1607 ast::ForeignItemStatic(..) => {
1608 ty::GenericPredicates::empty()
1612 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1613 assert!(prev_predicates.is_none());
1616 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1617 generics: &ast::Generics)
1618 -> ty::Generics<'tcx> {
1619 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
1622 fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1623 generics: &ast::Generics)
1624 -> ty::GenericPredicates<'tcx>
1626 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1629 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1630 trait_id: ast::NodeId,
1631 substs: &'tcx Substs<'tcx>,
1632 ast_generics: &ast::Generics)
1633 -> ty::Generics<'tcx>
1635 debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
1636 local_def(trait_id), substs);
1638 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1640 // Add in the self type parameter.
1642 // Something of a hack: use the node id for the trait, also as
1643 // the node id for the Self type parameter.
1644 let param_id = trait_id;
1646 let def = ty::TypeParameterDef {
1649 name: special_idents::type_self.name,
1650 def_id: local_def(param_id),
1652 object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
1655 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1657 generics.types.push(SelfSpace, def);
1662 fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1663 generics: &ast::Generics,
1664 base_generics: &ty::Generics<'tcx>)
1665 -> ty::Generics<'tcx>
1667 ty_generics(ccx, FnSpace, generics, base_generics)
1670 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1671 generics: &ast::Generics,
1672 base_predicates: &ty::GenericPredicates<'tcx>)
1673 -> ty::GenericPredicates<'tcx>
1675 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1678 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1679 fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1680 bounds: &mut ty::BuiltinBounds,
1681 ast_bounds: &[ast::TyParamBound],
1684 let tcx = astconv.tcx();
1686 // Try to find an unbound in bounds.
1687 let mut unbound = None;
1688 for ab in ast_bounds {
1689 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1690 if unbound.is_none() {
1691 assert!(ptr.bound_lifetimes.is_empty());
1692 unbound = Some(ptr.trait_ref.clone());
1694 span_err!(tcx.sess, span, E0203,
1695 "type parameter has more than one relaxed default \
1696 bound, only one is supported");
1701 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1704 // FIXME(#8559) currently requires the unbound to be built-in.
1705 let trait_def_id = tcx.trait_ref_to_def_id(tpb);
1707 Ok(kind_id) if trait_def_id != kind_id => {
1708 tcx.sess.span_warn(span,
1709 "default bound relaxed for a type parameter, but \
1710 this does nothing because the given bound is not \
1711 a default. Only `?Sized` is supported");
1712 tcx.try_add_builtin_trait(kind_id, bounds);
1717 _ if kind_id.is_ok() => {
1718 tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
1720 // No lang item for Sized, so we can't add it as a bound.
1725 /// Returns the early-bound lifetimes declared in this generics
1726 /// listing. For anything other than fns/methods, this is just all
1727 /// the lifetimes that are declared. For fns or methods, we have to
1728 /// screen out those that do not appear in any where-clauses etc using
1729 /// `resolve_lifetime::early_bound_lifetimes`.
1730 fn early_bound_lifetimes_from_generics(space: ParamSpace,
1731 ast_generics: &ast::Generics)
1732 -> Vec<ast::LifetimeDef>
1735 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1736 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1740 fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1742 ast_generics: &ast::Generics,
1743 base_predicates: &ty::GenericPredicates<'tcx>)
1744 -> ty::GenericPredicates<'tcx>
1747 let mut result = base_predicates.clone();
1749 // Collect the predicates that were written inline by the user on each
1750 // type parameter (e.g., `<T:Foo>`).
1751 for (index, param) in ast_generics.ty_params.iter().enumerate() {
1752 let index = index as u32;
1753 let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
1754 let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
1757 SizedByDefault::Yes,
1759 let predicates = bounds.predicates(ccx.tcx, param_ty);
1760 result.predicates.extend(space, predicates.into_iter());
1763 // Collect the region predicates that were declared inline as
1764 // well. In the case of parameters declared on a fn or method, we
1765 // have to be careful to only iterate over early-bound regions.
1766 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1767 for (index, param) in early_lifetimes.iter().enumerate() {
1768 let index = index as u32;
1770 ty::ReEarlyBound(ty::EarlyBoundRegion {
1771 param_id: param.lifetime.id,
1774 name: param.lifetime.name
1776 for bound in ¶m.bounds {
1777 let bound_region = ast_region_to_region(ccx.tcx, bound);
1778 let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
1779 result.predicates.push(space, outlives.to_predicate());
1783 // Add in the bounds that appear in the where-clause
1784 let where_clause = &ast_generics.where_clause;
1785 for predicate in &where_clause.predicates {
1787 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1788 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1790 &*bound_pred.bounded_ty);
1792 for bound in bound_pred.bounds.iter() {
1794 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1795 let mut projections = Vec::new();
1798 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1803 result.predicates.push(space, trait_ref.to_predicate());
1805 for projection in &projections {
1806 result.predicates.push(space, projection.to_predicate());
1810 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1811 let region = ast_region_to_region(tcx, lifetime);
1812 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1813 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1819 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1820 let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime);
1821 for bound in ®ion_pred.bounds {
1822 let r2 = ast_region_to_region(tcx, bound);
1823 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1824 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1828 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1830 tcx.sess.span_bug(eq_pred.span,
1831 "Equality constraints are not yet \
1832 implemented (#20041)")
1840 fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1842 ast_generics: &ast::Generics,
1843 base_generics: &ty::Generics<'tcx>)
1844 -> ty::Generics<'tcx>
1847 let mut result = base_generics.clone();
1849 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1850 for (i, l) in early_lifetimes.iter().enumerate() {
1851 let bounds = l.bounds.iter()
1852 .map(|l| ast_region_to_region(tcx, l))
1854 let def = ty::RegionParameterDef { name: l.lifetime.name,
1857 def_id: local_def(l.lifetime.id),
1859 result.regions.push(space, def);
1862 assert!(result.types.is_empty_in(space));
1864 // Now create the real type parameters.
1865 for i in 0..ast_generics.ty_params.len() {
1866 let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
1867 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1868 result.types.push(space, def);
1874 fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1880 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
1882 for leaf_ty in ty.walk() {
1883 if let ty::TyParam(p) = leaf_ty.sty {
1884 if p.space == space && p.idx >= index {
1885 span_err!(ccx.tcx.sess, path.span, E0128,
1886 "type parameters with a default cannot use \
1887 forward declared identifiers");
1889 return ccx.tcx.types.err
1897 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1898 ast_generics: &ast::Generics,
1901 -> ty::TypeParameterDef<'tcx>
1903 let param = &ast_generics.ty_params[index as usize];
1906 match tcx.ty_param_defs.borrow().get(¶m.id) {
1907 Some(d) => { return d.clone(); }
1911 let default = param.default.as_ref().map(
1912 |def| convert_default_type_parameter(ccx, def, space, index)
1915 let object_lifetime_default =
1916 compute_object_lifetime_default(ccx, param.id,
1917 ¶m.bounds, &ast_generics.where_clause);
1919 let def = ty::TypeParameterDef {
1922 name: param.ident.name,
1923 def_id: local_def(param.id),
1925 object_lifetime_default: object_lifetime_default,
1928 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1933 /// Scan the bounds and where-clauses on a parameter to extract bounds
1934 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1935 /// This runs as part of computing the minimal type scheme, so we
1936 /// intentionally avoid just asking astconv to convert all the where
1937 /// clauses into a `ty::Predicate`. This is because that could induce
1938 /// artificial cycles.
1939 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1940 param_id: ast::NodeId,
1941 param_bounds: &[ast::TyParamBound],
1942 where_clause: &ast::WhereClause)
1943 -> ty::ObjectLifetimeDefault
1945 let inline_bounds = from_bounds(ccx, param_bounds);
1946 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
1947 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1948 .chain(where_bounds)
1950 return if all_bounds.len() > 1 {
1951 ty::ObjectLifetimeDefault::Ambiguous
1952 } else if all_bounds.len() == 0 {
1953 ty::ObjectLifetimeDefault::BaseDefault
1955 ty::ObjectLifetimeDefault::Specific(
1956 all_bounds.into_iter().next().unwrap())
1959 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1960 bounds: &[ast::TyParamBound])
1964 .filter_map(|bound| {
1966 ast::TraitTyParamBound(..) =>
1968 ast::RegionTyParamBound(ref lifetime) =>
1969 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
1975 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1976 param_id: ast::NodeId,
1977 predicates: &[ast::WherePredicate])
1981 .flat_map(|predicate| {
1983 ast::WherePredicate::BoundPredicate(ref data) => {
1984 if data.bound_lifetimes.is_empty() &&
1985 is_param(ccx.tcx, &data.bounded_ty, param_id)
1987 from_bounds(ccx, &data.bounds).into_iter()
1989 Vec::new().into_iter()
1992 ast::WherePredicate::RegionPredicate(..) |
1993 ast::WherePredicate::EqPredicate(..) => {
1994 Vec::new().into_iter()
2002 enum SizedByDefault { Yes, No, }
2004 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
2005 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
2006 /// built-in trait (formerly known as kind): Send.
2007 fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
2008 param_ty: ty::Ty<'tcx>,
2009 ast_bounds: &[ast::TyParamBound],
2010 sized_by_default: SizedByDefault,
2012 -> astconv::Bounds<'tcx>
2015 conv_param_bounds(astconv,
2020 if let SizedByDefault::Yes = sized_by_default {
2021 add_unsized_bound(astconv,
2022 &mut bounds.builtin_bounds,
2027 bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
2032 /// Converts a specific TyParamBound from the AST into a set of
2033 /// predicates that apply to the self-type. A vector is returned
2034 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2035 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2036 /// and `<T as Bar>::X == i32`).
2037 fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2039 bound: &ast::TyParamBound)
2040 -> Vec<ty::Predicate<'tcx>>
2043 ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
2044 let mut projections = Vec::new();
2045 let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
2046 projections.into_iter()
2047 .map(|p| p.to_predicate())
2048 .chain(Some(pred.to_predicate()))
2051 ast::RegionTyParamBound(ref lifetime) => {
2052 let region = ast_region_to_region(astconv.tcx(), lifetime);
2053 let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
2054 vec![ty::Predicate::TypeOutlives(pred)]
2056 ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
2062 fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2064 trait_ref: &ast::PolyTraitRef,
2065 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2066 -> ty::PolyTraitRef<'tcx>
2068 astconv::instantiate_poly_trait_ref(astconv,
2075 fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
2077 param_ty: ty::Ty<'tcx>,
2078 ast_bounds: &[ast::TyParamBound])
2079 -> astconv::Bounds<'tcx>
2081 let tcx = astconv.tcx();
2082 let astconv::PartitionedBounds {
2086 } = astconv::partition_bounds(tcx, span, &ast_bounds);
2088 let mut projection_bounds = Vec::new();
2090 let trait_bounds: Vec<ty::PolyTraitRef> =
2092 .map(|bound| conv_poly_trait_ref(astconv,
2095 &mut projection_bounds))
2098 let region_bounds: Vec<ty::Region> =
2099 region_bounds.into_iter()
2100 .map(|r| ast_region_to_region(tcx, r))
2104 region_bounds: region_bounds,
2105 builtin_bounds: builtin_bounds,
2106 trait_bounds: trait_bounds,
2107 projection_bounds: projection_bounds,
2111 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
2112 ccx: &CrateCtxt<'a, 'tcx>,
2114 ast_generics: &ast::Generics,
2116 -> ty::TypeScheme<'tcx>
2118 for i in &decl.inputs {
2119 match (*i).pat.node {
2120 ast::PatIdent(_, _, _) => (),
2121 ast::PatWild(ast::PatWildSingle) => (),
2123 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2124 "patterns aren't allowed in foreign function declarations");
2129 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
2131 let rb = BindingRscope::new();
2132 let input_tys = decl.inputs
2134 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
2137 let output = match decl.output {
2138 ast::Return(ref ty) =>
2139 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
2140 ast::DefaultReturn(..) =>
2141 ty::FnConverging(ccx.tcx.mk_nil()),
2142 ast::NoReturn(..) =>
2146 let t_fn = ccx.tcx.mk_fn(None,
2147 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2149 unsafety: ast::Unsafety::Unsafe,
2150 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2152 variadic: decl.variadic}),
2156 generics: ty_generics,
2161 fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2162 ty_generics: &ty::Generics<'tcx>)
2166 ty_generics.types.map(
2167 |def| ccx.tcx.mk_param_from_def(def));
2170 ty_generics.regions.map(
2171 |def| def.to_early_bound_region());
2173 Substs::new(types, regions)
2176 /// Verifies that the explicit self type of a method matches the impl
2177 /// or trait. This is a bit weird but basically because right now we
2178 /// don't handle the general case, but instead map it to one of
2179 /// several pre-defined options using various heuristics, this method
2180 /// comes back to check after the fact that explicit type the user
2181 /// wrote actually matches what the pre-defined option said.
2182 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2183 ccx: &CrateCtxt<'a, 'tcx>,
2185 method_type: Rc<ty::Method<'tcx>>,
2186 required_type: Ty<'tcx>,
2187 explicit_self: &ast::ExplicitSelf,
2188 body_id: ast::NodeId)
2191 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
2192 let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
2193 let base_type = match typ.sty {
2194 ty::TyRef(_, tm) => tm.ty,
2195 ty::TyBox(typ) => typ,
2199 let body_scope = region::DestructionScopeData::new(body_id);
2201 // "Required type" comes from the trait definition. It may
2202 // contain late-bound regions from the method, but not the
2203 // trait (since traits only have early-bound region
2205 assert!(!base_type.has_regions_escaping_depth(1));
2206 let required_type_free =
2207 liberate_early_bound_regions(
2209 &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(required_type)));
2211 // The "base type" comes from the impl. It too may have late-bound
2212 // regions from the method.
2213 assert!(!base_type.has_regions_escaping_depth(1));
2214 let base_type_free =
2215 liberate_early_bound_regions(
2217 &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(base_type)));
2219 debug!("required_type={:?} required_type_free={:?} \
2220 base_type={:?} base_type_free={:?}",
2226 let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
2227 drop(::require_same_types(tcx,
2234 format!("mismatched self type: expected `{}`",
2238 // We could conceviably add more free-region relations here,
2239 // but since this code is just concerned with checking that
2240 // the `&Self` types etc match up, it's not really necessary.
2241 // It would just allow people to be more approximate in some
2242 // cases. In any case, we can do it later as we feel the need;
2243 // I'd like this function to go away eventually.
2244 let free_regions = FreeRegionMap::new();
2246 infcx.resolve_regions_and_report_errors(&free_regions, body_id);
2249 fn liberate_early_bound_regions<'tcx,T>(
2250 tcx: &ty::ctxt<'tcx>,
2251 scope: region::DestructionScopeData,
2254 where T : TypeFoldable<'tcx>
2257 * Convert early-bound regions into free regions; normally this is done by
2258 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2259 * method-self-type check is kind of hacky and done very early in the process,
2260 * before we really have a `ParameterEnvironment` to check.
2263 ty_fold::fold_regions(tcx, value, &mut false, |region, _| {
2265 ty::ReEarlyBound(data) => {
2266 let def_id = local_def(data.param_id);
2267 ty::ReFree(ty::FreeRegion { scope: scope,
2268 bound_region: ty::BrNamed(def_id, data.name) })
2276 /// Checks that all the type parameters on an impl
2277 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2278 ast_generics: &ast::Generics,
2279 impl_def_id: ast::DefId,
2280 impl_items: &[P<ast::ImplItem>])
2282 let impl_scheme = tcx.lookup_item_type(impl_def_id);
2283 let impl_predicates = tcx.lookup_predicates(impl_def_id);
2284 let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
2286 // The trait reference is an input, so find all type parameters
2287 // reachable from there, to start (if this is an inherent impl,
2288 // then just examine the self type).
2289 let mut input_parameters: HashSet<_> =
2290 ctp::parameters_for_type(impl_scheme.ty).into_iter().collect();
2291 if let Some(ref trait_ref) = impl_trait_ref {
2292 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref));
2295 ctp::identify_constrained_type_params(tcx,
2296 impl_predicates.predicates.as_slice(),
2298 &mut input_parameters);
2300 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2301 let param_ty = ty::ParamTy { space: TypeSpace,
2303 name: ty_param.ident.name };
2304 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
2305 report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.to_string());
2309 // Every lifetime used in an associated type must be constrained.
2311 let lifetimes_in_associated_types: HashSet<_> =
2313 .map(|item| tcx.impl_or_trait_item(local_def(item.id)))
2314 .filter_map(|item| match item {
2315 ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
2316 ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
2318 .flat_map(|ty| ctp::parameters_for_type(ty))
2319 .filter_map(|p| match p {
2320 ctp::Parameter::Type(_) => None,
2321 ctp::Parameter::Region(r) => Some(r),
2325 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2326 let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
2328 index: index as u32,
2329 name: lifetime_def.lifetime.name };
2331 lifetimes_in_associated_types.contains(®ion) && // (*)
2332 !input_parameters.contains(&ctp::Parameter::Region(region))
2334 report_unused_parameter(tcx, lifetime_def.lifetime.span,
2335 "lifetime", ®ion.name.to_string());
2339 // (*) This is a horrible concession to reality. I think it'd be
2340 // better to just ban unconstrianed lifetimes outright, but in
2341 // practice people do non-hygenic macros like:
2344 // macro_rules! __impl_slice_eq1 {
2345 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2346 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2353 // In a concession to backwards compatbility, we continue to
2354 // permit those, so long as the lifetimes aren't used in
2355 // associated types. I believe this is sound, because lifetimes
2356 // used elsewhere are not projected back out.
2359 fn report_unused_parameter(tcx: &ty::ctxt,
2364 span_err!(tcx.sess, span, E0207,
2365 "the {} parameter `{}` is not constrained by the \
2366 impl trait, self type, or predicates",