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, 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,
751 let mut seen_methods = FnvHashSet();
752 for (sig, id, ident, vis, span) in methods {
753 if !seen_methods.insert(ident.name) {
754 let fn_desc = match sig.explicit_self.node {
755 ast::SelfStatic => "associated function",
758 span_err!(tcx.sess, span, E0201, "duplicate {}", fn_desc);
767 untransformed_rcvr_ty,
773 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
775 generics: &ast::Generics,
776 thing: &'static str) {
777 let mut warn = false;
779 for ty_param in generics.ty_params.iter() {
780 for bound in ty_param.bounds.iter() {
782 ast::TraitTyParamBound(..) => {
785 ast::RegionTyParamBound(..) => { }
791 // According to accepted RFC #XXX, we should
792 // eventually accept these, but it will not be
793 // part of this PR. Still, convert to warning to
794 // make bootstrapping easier.
795 span_warn!(ccx.tcx.sess, span, E0122,
796 "trait bounds are not (yet) enforced \
802 fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
804 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
806 // These don't define types.
807 ast::ItemExternCrate(_) | ast::ItemUse(_) |
808 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
810 ast::ItemEnum(ref enum_definition, _) => {
811 let (scheme, predicates) = convert_typed_item(ccx, it);
812 write_ty_to_tcx(tcx, it.id, scheme.ty);
813 get_enum_variant_types(ccx,
816 &enum_definition.variants);
818 ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
820 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
825 tcx.record_trait_has_default_impl(trait_ref.def_id);
827 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
834 // Create generics from the generics specified in the impl head.
835 debug!("convert: ast_generics={:?}", generics);
836 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
837 let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
839 debug!("convert: impl_bounds={:?}", ty_predicates);
841 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
842 write_ty_to_tcx(tcx, it.id, selfty);
844 tcx.register_item_type(local_def(it.id),
845 TypeScheme { generics: ty_generics.clone(),
847 tcx.predicates.borrow_mut().insert(local_def(it.id),
848 ty_predicates.clone());
850 // If there is a trait reference, treat the methods as always public.
851 // This is to work around some incorrect behavior in privacy checking:
852 // when the method belongs to a trait, it should acquire the privacy
853 // from the trait, not the impl. Forcing the visibility to be public
854 // makes things sorta work.
855 let parent_visibility = if opt_trait_ref.is_some() {
861 // Convert all the associated consts.
862 for impl_item in impl_items {
863 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
864 let ty = ccx.icx(&ty_predicates)
865 .to_ty(&ExplicitRscope, &*ty);
866 tcx.register_item_type(local_def(impl_item.id),
868 generics: ty_generics.clone(),
871 convert_associated_const(ccx, ImplContainer(local_def(it.id)),
872 impl_item.ident, impl_item.id,
873 impl_item.vis.inherit_from(parent_visibility),
878 // Convert all the associated types.
879 for impl_item in impl_items {
880 if let ast::TypeImplItem(ref ty) = impl_item.node {
881 if opt_trait_ref.is_none() {
882 span_err!(tcx.sess, impl_item.span, E0202,
883 "associated types are not allowed in inherent impls");
886 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
888 convert_associated_type(ccx, ImplContainer(local_def(it.id)),
889 impl_item.ident, impl_item.id, impl_item.vis,
894 let methods = impl_items.iter().filter_map(|ii| {
895 if let ast::MethodImplItem(ref sig, _) = ii.node {
896 // if the method specifies a visibility, use that, otherwise
897 // inherit the visibility from the impl (so `foo` in `pub impl
898 // { fn foo(); }` is public, but private in `impl { fn
900 let method_vis = ii.vis.inherit_from(parent_visibility);
901 Some((sig, ii.id, ii.ident, method_vis, ii.span))
907 ImplContainer(local_def(it.id)),
913 for impl_item in impl_items {
914 if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
915 let body_id = body.id;
916 check_method_self_type(ccx,
917 &BindingRscope::new(),
918 ccx.method_ty(impl_item.id),
925 if let &Some(ref ast_trait_ref) = opt_trait_ref {
926 tcx.impl_trait_refs.borrow_mut().insert(
928 Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
934 tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None);
937 enforce_impl_params_are_constrained(tcx,
942 ast::ItemTrait(_, _, _, ref trait_items) => {
943 let trait_def = trait_def_of_item(ccx, it);
944 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
945 ccx.ensure_super_predicates(it.span, local_def(it.id));
946 convert_trait_predicates(ccx, it);
947 let trait_predicates = tcx.lookup_predicates(local_def(it.id));
949 debug!("convert: trait_bounds={:?}", trait_predicates);
951 // Convert all the associated types.
952 for trait_item in trait_items {
953 match trait_item.node {
954 ast::ConstTraitItem(ref ty, ref default) => {
955 let ty = ccx.icx(&trait_predicates)
956 .to_ty(&ExplicitRscope, ty);
957 tcx.register_item_type(local_def(trait_item.id),
959 generics: trait_def.generics.clone(),
962 convert_associated_const(ccx, TraitContainer(local_def(it.id)),
963 trait_item.ident, trait_item.id,
964 ast::Public, ty, default.as_ref().map(|d| &**d));
970 // Convert all the associated types.
971 for trait_item in trait_items {
972 match trait_item.node {
973 ast::TypeTraitItem(_, ref opt_ty) => {
974 let typ = opt_ty.as_ref().map({
975 |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
978 convert_associated_type(ccx, TraitContainer(local_def(it.id)),
979 trait_item.ident, trait_item.id, ast::Public,
986 let methods = trait_items.iter().filter_map(|ti| {
987 let sig = match ti.node {
988 ast::MethodTraitItem(ref sig, _) => sig,
991 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
994 // Run convert_methods on the trait methods.
996 TraitContainer(local_def(it.id)),
1002 // Add an entry mapping
1003 let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
1004 let def_id = local_def(trait_item.id);
1005 match trait_item.node {
1006 ast::ConstTraitItem(..) => {
1007 ty::ConstTraitItemId(def_id)
1009 ast::MethodTraitItem(..) => {
1010 ty::MethodTraitItemId(def_id)
1012 ast::TypeTraitItem(..) => {
1013 ty::TypeTraitItemId(def_id)
1017 tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids);
1019 // This must be done after `collect_trait_methods` so that
1020 // we have a method type stored for every method.
1021 for trait_item in trait_items {
1022 let sig = match trait_item.node {
1023 ast::MethodTraitItem(ref sig, _) => sig,
1026 check_method_self_type(ccx,
1027 &BindingRscope::new(),
1028 ccx.method_ty(trait_item.id),
1034 ast::ItemStruct(ref struct_def, _) => {
1035 // Write the class type.
1036 let (scheme, predicates) = convert_typed_item(ccx, it);
1037 write_ty_to_tcx(tcx, it.id, scheme.ty);
1038 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
1040 ast::ItemTy(_, ref generics) => {
1041 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
1042 let (scheme, _) = convert_typed_item(ccx, it);
1043 write_ty_to_tcx(tcx, it.id, scheme.ty);
1046 // This call populates the type cache with the converted type
1047 // of the item in passing. All we have to do here is to write
1048 // it into the node type table.
1049 let (scheme, _) = convert_typed_item(ccx, it);
1050 write_ty_to_tcx(tcx, it.id, scheme.ty);
1055 fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1056 struct_def: &ast::StructDef,
1057 scheme: ty::TypeScheme<'tcx>,
1058 predicates: ty::GenericPredicates<'tcx>,
1062 // Write the type of each of the members and check for duplicate fields.
1063 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
1064 let field_tys = struct_def.fields.iter().map(|f| {
1065 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
1067 if result.name != special_idents::unnamed_field.name {
1068 let dup = match seen_fields.get(&result.name) {
1069 Some(prev_span) => {
1070 span_err!(tcx.sess, f.span, E0124,
1071 "field `{}` is already declared",
1072 token::get_name(result.name));
1073 span_note!(tcx.sess, *prev_span, "previously declared here");
1078 // FIXME(#6393) this whole dup thing is just to satisfy
1079 // the borrow checker :-(
1081 seen_fields.insert(result.name, f.span);
1088 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1090 let substs = mk_item_substs(ccx, &scheme.generics);
1091 let selfty = tcx.mk_struct(local_def(id), tcx.mk_substs(substs));
1093 // If this struct is enum-like or tuple-like, create the type of its
1095 match struct_def.ctor_id {
1098 if struct_def.fields.is_empty() {
1100 write_ty_to_tcx(tcx, ctor_id, selfty);
1102 tcx.register_item_type(local_def(ctor_id), scheme);
1103 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1104 } else if struct_def.fields[0].node.kind.is_unnamed() {
1106 let inputs: Vec<_> =
1109 .map(|field| tcx.lookup_item_type(
1110 local_def(field.node.id)).ty)
1112 let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
1115 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1116 tcx.register_item_type(local_def(ctor_id),
1118 generics: scheme.generics,
1121 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1127 /// Ensures that the super-predicates of the trait with def-id
1128 /// trait_def_id are converted and stored. This does NOT ensure that
1129 /// the transitive super-predicates are converted; that is the job of
1130 /// the `ensure_super_predicates()` method in the `AstConv` impl
1131 /// above. Returns a list of trait def-ids that must be ensured as
1132 /// well to guarantee that the transitive superpredicates are
1134 fn ensure_super_predicates_step(ccx: &CrateCtxt,
1135 trait_def_id: ast::DefId)
1140 debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
1142 if trait_def_id.krate != ast::LOCAL_CRATE {
1143 // If this trait comes from an external crate, then all of the
1144 // supertraits it may depend on also must come from external
1145 // crates, and hence all of them already have their
1146 // super-predicates "converted" (and available from crate
1147 // meta-data), so there is no need to transitively test them.
1151 let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned();
1152 let superpredicates = superpredicates.unwrap_or_else(|| {
1153 let trait_node_id = trait_def_id.node;
1155 let item = match ccx.tcx.map.get(trait_node_id) {
1156 ast_map::NodeItem(item) => item,
1157 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1160 let (generics, bounds) = match item.node {
1161 ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
1162 _ => tcx.sess.span_bug(item.span,
1163 "ensure_super_predicates_step invoked on non-trait"),
1166 // In-scope when converting the superbounds for `Trait` are
1167 // that `Self:Trait` as well as any bounds that appear on the
1169 let trait_def = trait_def_of_item(ccx, item);
1170 let self_predicate = ty::GenericPredicates {
1171 predicates: VecPerParamSpace::new(vec![],
1172 vec![trait_def.trait_ref.to_predicate()],
1175 let scope = &(generics, &self_predicate);
1177 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1178 let self_param_ty = tcx.mk_self_type();
1179 let superbounds1 = compute_bounds(&ccx.icx(scope),
1185 let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
1187 // Convert any explicit superbounds in the where clause,
1188 // e.g. `trait Foo where Self : Bar`:
1189 let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
1191 // Combine the two lists to form the complete set of superbounds:
1192 let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
1193 let superpredicates = ty::GenericPredicates {
1194 predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
1196 debug!("superpredicates for trait {:?} = {:?}",
1200 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1205 let def_ids: Vec<_> = superpredicates.predicates
1207 .filter_map(|p| p.to_opt_poly_trait_ref())
1208 .map(|tr| tr.def_id())
1211 debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
1216 fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1218 -> &'tcx ty::TraitDef<'tcx>
1220 let def_id = local_def(it.id);
1223 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1227 let (unsafety, generics, items) = match it.node {
1228 ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
1229 _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
1232 let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
1233 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
1234 ccx.tcx.sess.span_err(
1236 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1237 which traits can use parenthetical notation");
1238 fileline_help!(ccx.tcx.sess, it.span,
1239 "add `#![feature(unboxed_closures)]` to \
1240 the crate attributes to use it");
1243 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1245 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1247 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1248 match trait_item.node {
1249 ast::TypeTraitItem(..) => Some(trait_item.ident.name),
1254 let trait_ref = ty::TraitRef {
1259 let trait_def = ty::TraitDef {
1260 paren_sugar: paren_sugar,
1262 generics: ty_generics,
1263 trait_ref: trait_ref,
1264 associated_type_names: associated_type_names,
1265 nonblanket_impls: RefCell::new(FnvHashMap()),
1266 blanket_impls: RefCell::new(vec![]),
1267 flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS)
1270 return tcx.intern_trait_def(trait_def);
1272 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1273 generics: &ast::Generics)
1278 // Creates a no-op substitution for the trait's type parameters.
1283 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1284 param_id: def.lifetime.id,
1287 name: def.lifetime.name
1291 // Start with the generics in the type parameters...
1296 .map(|(i, def)| tcx.mk_param(TypeSpace,
1297 i as u32, def.ident.name))
1300 // ...and also create the `Self` parameter.
1301 let self_ty = tcx.mk_self_type();
1303 Substs::new_trait(types, regions, self_ty)
1307 fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1308 trait_node_id: ast::NodeId,
1309 assoc_name: ast::Name)
1312 let item = match ccx.tcx.map.get(trait_node_id) {
1313 ast_map::NodeItem(item) => item,
1314 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1317 let trait_items = match item.node {
1318 ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
1319 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
1322 trait_items.iter().any(|trait_item| {
1323 match trait_item.node {
1324 ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
1330 fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
1332 let trait_def = trait_def_of_item(ccx, it);
1334 let def_id = local_def(it.id);
1336 let (generics, items) = match it.node {
1337 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1341 &format!("trait_def_of_item invoked on {:?}", s));
1345 let super_predicates = ccx.tcx.lookup_super_predicates(def_id);
1347 // `ty_generic_predicates` below will consider the bounds on the type
1348 // parameters (including `Self`) and the explicit where-clauses,
1349 // but to get the full set of predicates on a trait we need to add
1350 // in the supertrait bounds and anything declared on the
1351 // associated types.
1352 let mut base_predicates = super_predicates;
1354 // Add in a predicate that `Self:Trait` (where `Trait` is the
1355 // current trait). This is needed for builtin bounds.
1356 let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
1357 base_predicates.predicates.push(SelfSpace, self_predicate);
1359 // add in the explicit where-clauses
1360 let mut trait_predicates =
1361 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1363 let assoc_predicates = predicates_for_associated_types(ccx,
1366 trait_def.trait_ref,
1368 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
1370 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1371 assert!(prev_predicates.is_none());
1375 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1376 ast_generics: &ast::Generics,
1377 trait_predicates: &ty::GenericPredicates<'tcx>,
1378 self_trait_ref: ty::TraitRef<'tcx>,
1379 trait_items: &[P<ast::TraitItem>])
1380 -> Vec<ty::Predicate<'tcx>>
1382 trait_items.iter().flat_map(|trait_item| {
1383 let bounds = match trait_item.node {
1384 ast::TypeTraitItem(ref bounds, _) => bounds,
1386 return vec!().into_iter();
1390 let assoc_ty = ccx.tcx.mk_projection(self_trait_ref,
1391 trait_item.ident.name);
1393 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1396 SizedByDefault::Yes,
1399 bounds.predicates(ccx.tcx, assoc_ty).into_iter()
1404 fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1406 -> ty::TypeScheme<'tcx>
1408 if def_id.krate != ast::LOCAL_CRATE {
1409 return ccx.tcx.lookup_item_type(def_id);
1412 match ccx.tcx.map.find(def_id.node) {
1413 Some(ast_map::NodeItem(item)) => {
1414 type_scheme_of_item(ccx, &*item)
1416 Some(ast_map::NodeForeignItem(foreign_item)) => {
1417 let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
1418 type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
1421 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1422 in get_item_type_scheme(): {:?}",
1428 fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1430 -> ty::TypeScheme<'tcx>
1432 memoized(&ccx.tcx.tcache,
1434 |_| compute_type_scheme_of_item(ccx, it))
1437 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1439 -> ty::TypeScheme<'tcx>
1443 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
1444 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
1445 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1447 ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
1448 let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1449 let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
1450 let ty = tcx.mk_fn(Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
1451 ty::TypeScheme { ty: ty, generics: ty_generics }
1453 ast::ItemTy(ref t, ref generics) => {
1454 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1455 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
1456 ty::TypeScheme { ty: ty, generics: ty_generics }
1458 ast::ItemEnum(_, ref generics) => {
1459 // Create a new generic polytype.
1460 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1461 let substs = mk_item_substs(ccx, &ty_generics);
1462 let t = tcx.mk_enum(local_def(it.id), tcx.mk_substs(substs));
1463 ty::TypeScheme { ty: t, generics: ty_generics }
1465 ast::ItemStruct(_, ref generics) => {
1466 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1467 let substs = mk_item_substs(ccx, &ty_generics);
1468 let t = tcx.mk_struct(local_def(it.id), tcx.mk_substs(substs));
1469 ty::TypeScheme { ty: t, generics: ty_generics }
1471 ast::ItemDefaultImpl(..) |
1472 ast::ItemTrait(..) |
1475 ast::ItemForeignMod(..) |
1476 ast::ItemExternCrate(..) |
1478 ast::ItemMac(..) => {
1481 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1487 fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1489 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1493 let tag = type_scheme_of_item(ccx, it);
1494 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1495 let predicates = match it.node {
1496 ast::ItemStatic(..) | ast::ItemConst(..) => {
1497 ty::GenericPredicates::empty()
1499 ast::ItemFn(_, _, _, _, ref ast_generics, _) => {
1500 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
1502 ast::ItemTy(_, ref generics) => {
1503 ty_generic_predicates_for_type_or_impl(ccx, generics)
1505 ast::ItemEnum(_, ref generics) => {
1506 ty_generic_predicates_for_type_or_impl(ccx, generics)
1508 ast::ItemStruct(_, ref generics) => {
1509 ty_generic_predicates_for_type_or_impl(ccx, generics)
1511 ast::ItemDefaultImpl(..) |
1512 ast::ItemTrait(..) |
1513 ast::ItemExternCrate(..) |
1517 ast::ItemForeignMod(..) |
1518 ast::ItemMac(..) => {
1521 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1526 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1527 predicates.clone());
1528 assert!(prev_predicates.is_none());
1531 if tcx.has_attr(local_def(it.id), "rustc_object_lifetime_default") {
1532 let object_lifetime_default_reprs: String =
1533 scheme.generics.types.iter()
1534 .map(|t| match t.object_lifetime_default {
1535 ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
1536 d => format!("{:?}", d),
1538 .collect::<Vec<String>>()
1541 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1544 return (scheme, predicates);
1547 fn type_scheme_of_foreign_item<'a, 'tcx>(
1548 ccx: &CrateCtxt<'a, 'tcx>,
1549 it: &ast::ForeignItem,
1551 -> ty::TypeScheme<'tcx>
1553 memoized(&ccx.tcx.tcache,
1555 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1558 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
1559 ccx: &CrateCtxt<'a, 'tcx>,
1560 it: &ast::ForeignItem,
1562 -> ty::TypeScheme<'tcx>
1565 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1566 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1568 ast::ForeignItemStatic(ref t, _) => {
1570 generics: ty::Generics::empty(),
1571 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1577 fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1578 it: &ast::ForeignItem)
1580 // For reasons I cannot fully articulate, I do so hate the AST
1581 // map, and I regard each time that I use it as a personal and
1582 // moral failing, but at the moment it seems like the only
1583 // convenient way to extract the ABI. - ndm
1585 let abi = tcx.map.get_foreign_abi(it.id);
1587 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1588 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1590 let predicates = match it.node {
1591 ast::ForeignItemFn(_, ref generics) => {
1592 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
1594 ast::ForeignItemStatic(..) => {
1595 ty::GenericPredicates::empty()
1599 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1600 assert!(prev_predicates.is_none());
1603 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1604 generics: &ast::Generics)
1605 -> ty::Generics<'tcx> {
1606 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
1609 fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1610 generics: &ast::Generics)
1611 -> ty::GenericPredicates<'tcx>
1613 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1616 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1617 trait_id: ast::NodeId,
1618 substs: &'tcx Substs<'tcx>,
1619 ast_generics: &ast::Generics)
1620 -> ty::Generics<'tcx>
1622 debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
1623 local_def(trait_id), substs);
1625 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1627 // Add in the self type parameter.
1629 // Something of a hack: use the node id for the trait, also as
1630 // the node id for the Self type parameter.
1631 let param_id = trait_id;
1633 let def = ty::TypeParameterDef {
1636 name: special_idents::type_self.name,
1637 def_id: local_def(param_id),
1639 object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
1642 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1644 generics.types.push(SelfSpace, def);
1649 fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1650 generics: &ast::Generics,
1651 base_generics: &ty::Generics<'tcx>)
1652 -> ty::Generics<'tcx>
1654 ty_generics(ccx, FnSpace, generics, base_generics)
1657 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1658 generics: &ast::Generics,
1659 base_predicates: &ty::GenericPredicates<'tcx>)
1660 -> ty::GenericPredicates<'tcx>
1662 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1665 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1666 fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1667 bounds: &mut ty::BuiltinBounds,
1668 ast_bounds: &[ast::TyParamBound],
1671 let tcx = astconv.tcx();
1673 // Try to find an unbound in bounds.
1674 let mut unbound = None;
1675 for ab in ast_bounds {
1676 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1677 if unbound.is_none() {
1678 assert!(ptr.bound_lifetimes.is_empty());
1679 unbound = Some(ptr.trait_ref.clone());
1681 span_err!(tcx.sess, span, E0203,
1682 "type parameter has more than one relaxed default \
1683 bound, only one is supported");
1688 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1691 // FIXME(#8559) currently requires the unbound to be built-in.
1692 let trait_def_id = tcx.trait_ref_to_def_id(tpb);
1694 Ok(kind_id) if trait_def_id != kind_id => {
1695 tcx.sess.span_warn(span,
1696 "default bound relaxed for a type parameter, but \
1697 this does nothing because the given bound is not \
1698 a default. Only `?Sized` is supported");
1699 tcx.try_add_builtin_trait(kind_id, bounds);
1704 _ if kind_id.is_ok() => {
1705 tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
1707 // No lang item for Sized, so we can't add it as a bound.
1712 /// Returns the early-bound lifetimes declared in this generics
1713 /// listing. For anything other than fns/methods, this is just all
1714 /// the lifetimes that are declared. For fns or methods, we have to
1715 /// screen out those that do not appear in any where-clauses etc using
1716 /// `resolve_lifetime::early_bound_lifetimes`.
1717 fn early_bound_lifetimes_from_generics(space: ParamSpace,
1718 ast_generics: &ast::Generics)
1719 -> Vec<ast::LifetimeDef>
1722 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1723 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1727 fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1729 ast_generics: &ast::Generics,
1730 base_predicates: &ty::GenericPredicates<'tcx>)
1731 -> ty::GenericPredicates<'tcx>
1734 let mut result = base_predicates.clone();
1736 // Collect the predicates that were written inline by the user on each
1737 // type parameter (e.g., `<T:Foo>`).
1738 for (index, param) in ast_generics.ty_params.iter().enumerate() {
1739 let index = index as u32;
1740 let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
1741 let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
1744 SizedByDefault::Yes,
1746 let predicates = bounds.predicates(ccx.tcx, param_ty);
1747 result.predicates.extend(space, predicates.into_iter());
1750 // Collect the region predicates that were declared inline as
1751 // well. In the case of parameters declared on a fn or method, we
1752 // have to be careful to only iterate over early-bound regions.
1753 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1754 for (index, param) in early_lifetimes.iter().enumerate() {
1755 let index = index as u32;
1757 ty::ReEarlyBound(ty::EarlyBoundRegion {
1758 param_id: param.lifetime.id,
1761 name: param.lifetime.name
1763 for bound in ¶m.bounds {
1764 let bound_region = ast_region_to_region(ccx.tcx, bound);
1765 let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
1766 result.predicates.push(space, outlives.to_predicate());
1770 // Add in the bounds that appear in the where-clause
1771 let where_clause = &ast_generics.where_clause;
1772 for predicate in &where_clause.predicates {
1774 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1775 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1777 &*bound_pred.bounded_ty);
1779 for bound in bound_pred.bounds.iter() {
1781 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1782 let mut projections = Vec::new();
1785 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1790 result.predicates.push(space, trait_ref.to_predicate());
1792 for projection in &projections {
1793 result.predicates.push(space, projection.to_predicate());
1797 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1798 let region = ast_region_to_region(tcx, lifetime);
1799 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1800 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1806 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1807 let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime);
1808 for bound in ®ion_pred.bounds {
1809 let r2 = ast_region_to_region(tcx, bound);
1810 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1811 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1815 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1817 tcx.sess.span_bug(eq_pred.span,
1818 "Equality constraints are not yet \
1819 implemented (#20041)")
1827 fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1829 ast_generics: &ast::Generics,
1830 base_generics: &ty::Generics<'tcx>)
1831 -> ty::Generics<'tcx>
1834 let mut result = base_generics.clone();
1836 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1837 for (i, l) in early_lifetimes.iter().enumerate() {
1838 let bounds = l.bounds.iter()
1839 .map(|l| ast_region_to_region(tcx, l))
1841 let def = ty::RegionParameterDef { name: l.lifetime.name,
1844 def_id: local_def(l.lifetime.id),
1846 result.regions.push(space, def);
1849 assert!(result.types.is_empty_in(space));
1851 // Now create the real type parameters.
1852 for i in 0..ast_generics.ty_params.len() {
1853 let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
1854 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1855 result.types.push(space, def);
1861 fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1867 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
1869 for leaf_ty in ty.walk() {
1870 if let ty::TyParam(p) = leaf_ty.sty {
1871 if p.space == space && p.idx >= index {
1872 span_err!(ccx.tcx.sess, path.span, E0128,
1873 "type parameters with a default cannot use \
1874 forward declared identifiers");
1876 return ccx.tcx.types.err
1884 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1885 ast_generics: &ast::Generics,
1888 -> ty::TypeParameterDef<'tcx>
1890 let param = &ast_generics.ty_params[index as usize];
1893 match tcx.ty_param_defs.borrow().get(¶m.id) {
1894 Some(d) => { return d.clone(); }
1898 let default = param.default.as_ref().map(
1899 |def| convert_default_type_parameter(ccx, def, space, index)
1902 let object_lifetime_default =
1903 compute_object_lifetime_default(ccx, param.id,
1904 ¶m.bounds, &ast_generics.where_clause);
1906 let def = ty::TypeParameterDef {
1909 name: param.ident.name,
1910 def_id: local_def(param.id),
1912 object_lifetime_default: object_lifetime_default,
1915 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1920 /// Scan the bounds and where-clauses on a parameter to extract bounds
1921 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1922 /// This runs as part of computing the minimal type scheme, so we
1923 /// intentionally avoid just asking astconv to convert all the where
1924 /// clauses into a `ty::Predicate`. This is because that could induce
1925 /// artificial cycles.
1926 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1927 param_id: ast::NodeId,
1928 param_bounds: &[ast::TyParamBound],
1929 where_clause: &ast::WhereClause)
1930 -> ty::ObjectLifetimeDefault
1932 let inline_bounds = from_bounds(ccx, param_bounds);
1933 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
1934 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1935 .chain(where_bounds)
1937 return if all_bounds.len() > 1 {
1938 ty::ObjectLifetimeDefault::Ambiguous
1939 } else if all_bounds.len() == 0 {
1940 ty::ObjectLifetimeDefault::BaseDefault
1942 ty::ObjectLifetimeDefault::Specific(
1943 all_bounds.into_iter().next().unwrap())
1946 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1947 bounds: &[ast::TyParamBound])
1951 .filter_map(|bound| {
1953 ast::TraitTyParamBound(..) =>
1955 ast::RegionTyParamBound(ref lifetime) =>
1956 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
1962 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1963 param_id: ast::NodeId,
1964 predicates: &[ast::WherePredicate])
1968 .flat_map(|predicate| {
1970 ast::WherePredicate::BoundPredicate(ref data) => {
1971 if data.bound_lifetimes.is_empty() &&
1972 is_param(ccx.tcx, &data.bounded_ty, param_id)
1974 from_bounds(ccx, &data.bounds).into_iter()
1976 Vec::new().into_iter()
1979 ast::WherePredicate::RegionPredicate(..) |
1980 ast::WherePredicate::EqPredicate(..) => {
1981 Vec::new().into_iter()
1989 enum SizedByDefault { Yes, No, }
1991 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1992 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1993 /// built-in trait (formerly known as kind): Send.
1994 fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
1995 param_ty: ty::Ty<'tcx>,
1996 ast_bounds: &[ast::TyParamBound],
1997 sized_by_default: SizedByDefault,
1999 -> astconv::Bounds<'tcx>
2002 conv_param_bounds(astconv,
2007 if let SizedByDefault::Yes = sized_by_default {
2008 add_unsized_bound(astconv,
2009 &mut bounds.builtin_bounds,
2014 bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
2019 /// Converts a specific TyParamBound from the AST into a set of
2020 /// predicates that apply to the self-type. A vector is returned
2021 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2022 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2023 /// and `<T as Bar>::X == i32`).
2024 fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2026 bound: &ast::TyParamBound)
2027 -> Vec<ty::Predicate<'tcx>>
2030 ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
2031 let mut projections = Vec::new();
2032 let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
2033 projections.into_iter()
2034 .map(|p| p.to_predicate())
2035 .chain(Some(pred.to_predicate()))
2038 ast::RegionTyParamBound(ref lifetime) => {
2039 let region = ast_region_to_region(astconv.tcx(), lifetime);
2040 let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
2041 vec![ty::Predicate::TypeOutlives(pred)]
2043 ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
2049 fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2051 trait_ref: &ast::PolyTraitRef,
2052 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2053 -> ty::PolyTraitRef<'tcx>
2055 astconv::instantiate_poly_trait_ref(astconv,
2062 fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
2064 param_ty: ty::Ty<'tcx>,
2065 ast_bounds: &[ast::TyParamBound])
2066 -> astconv::Bounds<'tcx>
2068 let tcx = astconv.tcx();
2069 let astconv::PartitionedBounds {
2073 } = astconv::partition_bounds(tcx, span, &ast_bounds);
2075 let mut projection_bounds = Vec::new();
2077 let trait_bounds: Vec<ty::PolyTraitRef> =
2079 .map(|bound| conv_poly_trait_ref(astconv,
2082 &mut projection_bounds))
2085 let region_bounds: Vec<ty::Region> =
2086 region_bounds.into_iter()
2087 .map(|r| ast_region_to_region(tcx, r))
2091 region_bounds: region_bounds,
2092 builtin_bounds: builtin_bounds,
2093 trait_bounds: trait_bounds,
2094 projection_bounds: projection_bounds,
2098 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
2099 ccx: &CrateCtxt<'a, 'tcx>,
2101 ast_generics: &ast::Generics,
2103 -> ty::TypeScheme<'tcx>
2105 for i in &decl.inputs {
2106 match (*i).pat.node {
2107 ast::PatIdent(_, _, _) => (),
2108 ast::PatWild(ast::PatWildSingle) => (),
2110 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2111 "patterns aren't allowed in foreign function declarations");
2116 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
2118 let rb = BindingRscope::new();
2119 let input_tys = decl.inputs
2121 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
2124 let output = match decl.output {
2125 ast::Return(ref ty) =>
2126 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
2127 ast::DefaultReturn(..) =>
2128 ty::FnConverging(ccx.tcx.mk_nil()),
2129 ast::NoReturn(..) =>
2133 let t_fn = ccx.tcx.mk_fn(None,
2134 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2136 unsafety: ast::Unsafety::Unsafe,
2137 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2139 variadic: decl.variadic}),
2143 generics: ty_generics,
2148 fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2149 ty_generics: &ty::Generics<'tcx>)
2153 ty_generics.types.map(
2154 |def| ccx.tcx.mk_param_from_def(def));
2157 ty_generics.regions.map(
2158 |def| def.to_early_bound_region());
2160 Substs::new(types, regions)
2163 /// Verifies that the explicit self type of a method matches the impl
2164 /// or trait. This is a bit weird but basically because right now we
2165 /// don't handle the general case, but instead map it to one of
2166 /// several pre-defined options using various heuristics, this method
2167 /// comes back to check after the fact that explicit type the user
2168 /// wrote actually matches what the pre-defined option said.
2169 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2170 ccx: &CrateCtxt<'a, 'tcx>,
2172 method_type: Rc<ty::Method<'tcx>>,
2173 required_type: Ty<'tcx>,
2174 explicit_self: &ast::ExplicitSelf,
2175 body_id: ast::NodeId)
2178 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
2179 let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
2180 let base_type = match typ.sty {
2181 ty::TyRef(_, tm) => tm.ty,
2182 ty::TyBox(typ) => typ,
2186 let body_scope = region::DestructionScopeData::new(body_id);
2188 // "Required type" comes from the trait definition. It may
2189 // contain late-bound regions from the method, but not the
2190 // trait (since traits only have early-bound region
2192 assert!(!base_type.has_regions_escaping_depth(1));
2193 let required_type_free =
2194 liberate_early_bound_regions(
2196 &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(required_type)));
2198 // The "base type" comes from the impl. It too may have late-bound
2199 // regions from the method.
2200 assert!(!base_type.has_regions_escaping_depth(1));
2201 let base_type_free =
2202 liberate_early_bound_regions(
2204 &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(base_type)));
2206 debug!("required_type={:?} required_type_free={:?} \
2207 base_type={:?} base_type_free={:?}",
2213 let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
2214 drop(::require_same_types(tcx,
2221 format!("mismatched self type: expected `{}`",
2225 // We could conceviably add more free-region relations here,
2226 // but since this code is just concerned with checking that
2227 // the `&Self` types etc match up, it's not really necessary.
2228 // It would just allow people to be more approximate in some
2229 // cases. In any case, we can do it later as we feel the need;
2230 // I'd like this function to go away eventually.
2231 let free_regions = FreeRegionMap::new();
2233 infcx.resolve_regions_and_report_errors(&free_regions, body_id);
2236 fn liberate_early_bound_regions<'tcx,T>(
2237 tcx: &ty::ctxt<'tcx>,
2238 scope: region::DestructionScopeData,
2241 where T : TypeFoldable<'tcx>
2244 * Convert early-bound regions into free regions; normally this is done by
2245 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2246 * method-self-type check is kind of hacky and done very early in the process,
2247 * before we really have a `ParameterEnvironment` to check.
2250 ty_fold::fold_regions(tcx, value, &mut false, |region, _| {
2252 ty::ReEarlyBound(data) => {
2253 let def_id = local_def(data.param_id);
2254 ty::ReFree(ty::FreeRegion { scope: scope,
2255 bound_region: ty::BrNamed(def_id, data.name) })
2263 /// Checks that all the type parameters on an impl
2264 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2265 ast_generics: &ast::Generics,
2266 impl_def_id: ast::DefId,
2267 impl_items: &[P<ast::ImplItem>])
2269 let impl_scheme = tcx.lookup_item_type(impl_def_id);
2270 let impl_predicates = tcx.lookup_predicates(impl_def_id);
2271 let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
2273 // The trait reference is an input, so find all type parameters
2274 // reachable from there, to start (if this is an inherent impl,
2275 // then just examine the self type).
2276 let mut input_parameters: HashSet<_> =
2277 ctp::parameters_for_type(impl_scheme.ty).into_iter().collect();
2278 if let Some(ref trait_ref) = impl_trait_ref {
2279 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref));
2282 ctp::identify_constrained_type_params(tcx,
2283 impl_predicates.predicates.as_slice(),
2285 &mut input_parameters);
2287 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2288 let param_ty = ty::ParamTy { space: TypeSpace,
2290 name: ty_param.ident.name };
2291 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
2292 report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.to_string());
2296 // Every lifetime used in an associated type must be constrained.
2298 let lifetimes_in_associated_types: HashSet<_> =
2300 .map(|item| tcx.impl_or_trait_item(local_def(item.id)))
2301 .filter_map(|item| match item {
2302 ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
2303 ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
2305 .flat_map(|ty| ctp::parameters_for_type(ty))
2306 .filter_map(|p| match p {
2307 ctp::Parameter::Type(_) => None,
2308 ctp::Parameter::Region(r) => Some(r),
2312 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2313 let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
2315 index: index as u32,
2316 name: lifetime_def.lifetime.name };
2318 lifetimes_in_associated_types.contains(®ion) && // (*)
2319 !input_parameters.contains(&ctp::Parameter::Region(region))
2321 report_unused_parameter(tcx, lifetime_def.lifetime.span,
2322 "lifetime", ®ion.name.to_string());
2326 // (*) This is a horrible concession to reality. I think it'd be
2327 // better to just ban unconstrianed lifetimes outright, but in
2328 // practice people do non-hygenic macros like:
2331 // macro_rules! __impl_slice_eq1 {
2332 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2333 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2340 // In a concession to backwards compatbility, we continue to
2341 // permit those, so long as the lifetimes aren't used in
2342 // associated types. I believe this is sound, because lifetimes
2343 // used elsewhere are not projected back out.
2346 fn report_unused_parameter(tcx: &ty::ctxt,
2351 span_err!(tcx.sess, span, E0207,
2352 "the {} parameter `{}` is not constrained by the \
2353 impl trait, self type, or predicates",