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 two 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):
42 1. Trait/Type definitions
44 Conversion itself is done by simply walking each of the items in turn
45 and invoking an appropriate function (e.g., `trait_def_of_item` or
46 `convert_item`). However, it is possible that while converting an
47 item, we may need to compute the *type scheme* or *trait definition*
50 There are some shortcomings in this design:
52 - Before walking the set of supertraits for a given trait, you must
53 call `ensure_super_predicates` on that trait def-id. Otherwise,
54 `lookup_super_predicates` will result in ICEs.
55 - Because the type scheme includes defaults, cycles through type
56 parameter defaults are illegal even if those defaults are never
57 employed. This is not necessarily a bug.
61 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
63 use middle::def_id::DefId;
64 use constrained_type_params as ctp;
65 use middle::lang_items::SizedTraitLangItem;
66 use middle::resolve_lifetime;
67 use middle::const_eval::{self, ConstVal};
68 use middle::const_eval::EvalHint::UncheckedExprHint;
69 use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
70 use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
71 use middle::ty::{self, ToPolyTraitRef, Ty, TypeScheme};
72 use middle::ty::{VariantKind};
73 use middle::ty::fold::{TypeFolder};
74 use middle::ty::util::IntTypeExt;
76 use rustc::dep_graph::DepNode;
77 use rustc::front::map as hir_map;
78 use util::common::{ErrorReported, MemoizationMap};
79 use util::nodemap::{FnvHashMap, FnvHashSet};
82 use std::cell::RefCell;
83 use std::collections::HashSet;
89 use syntax::codemap::Span;
90 use syntax::parse::token::special_idents;
93 use rustc_front::intravisit;
94 use rustc_front::print::pprust;
96 ///////////////////////////////////////////////////////////////////////////
99 pub fn collect_item_types(tcx: &ty::ctxt) {
100 let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
102 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
103 ccx.tcx.map.krate().visit_all_items(&mut visitor);
106 ///////////////////////////////////////////////////////////////////////////
108 struct CrateCtxt<'a,'tcx:'a> {
109 tcx: &'a ty::ctxt<'tcx>,
111 // This stack is used to identify cycles in the user's source.
112 // Note that these cycles can cross multiple items.
113 stack: RefCell<Vec<AstConvRequest>>,
116 /// Context specific to some particular item. This is what implements
117 /// AstConv. It has information about the predicates that are defined
118 /// on the trait. Unfortunately, this predicate information is
119 /// available in various different forms at various points in the
120 /// process. So we can't just store a pointer to e.g. the AST or the
121 /// parsed ty form, we have to be more flexible. To this end, the
122 /// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
123 /// that it uses to satisfy `get_type_parameter_bounds` requests.
124 /// This object might draw the information from the AST
125 /// (`hir::Generics`) or it might draw from a `ty::GenericPredicates`
126 /// or both (a tuple).
127 struct ItemCtxt<'a,'tcx:'a> {
128 ccx: &'a CrateCtxt<'a,'tcx>,
129 param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
132 #[derive(Copy, Clone, PartialEq, Eq)]
133 enum AstConvRequest {
134 GetItemTypeScheme(DefId),
136 EnsureSuperPredicates(DefId),
137 GetTypeParameterBounds(ast::NodeId),
140 ///////////////////////////////////////////////////////////////////////////
142 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
143 ccx: &'a CrateCtxt<'a, 'tcx>
146 impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
147 fn visit_item(&mut self, item: &hir::Item) {
148 let tcx = self.ccx.tcx;
149 let item_def_id = tcx.map.local_def_id(item.id);
150 let _task = tcx.dep_graph.in_task(DepNode::CollectItem(item_def_id));
151 convert_item(self.ccx, item);
155 ///////////////////////////////////////////////////////////////////////////
156 // Utility types and common code for the above passes.
158 impl<'a,'tcx> CrateCtxt<'a,'tcx> {
159 fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
160 ItemCtxt { ccx: self, param_bounds: param_bounds }
163 fn cycle_check<F,R>(&self,
165 request: AstConvRequest,
167 -> Result<R,ErrorReported>
168 where F: FnOnce() -> Result<R,ErrorReported>
171 let mut stack = self.stack.borrow_mut();
172 match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
175 let cycle = &stack[i..];
176 self.report_cycle(span, cycle);
177 return Err(ErrorReported);
185 self.stack.borrow_mut().pop();
189 fn report_cycle(&self,
191 cycle: &[AstConvRequest])
193 assert!(!cycle.is_empty());
196 let mut err = struct_span_err!(tcx.sess, span, E0391,
197 "unsupported cyclic reference between types/traits detected");
200 AstConvRequest::GetItemTypeScheme(def_id) |
201 AstConvRequest::GetTraitDef(def_id) => {
203 &format!("the cycle begins when processing `{}`...",
204 tcx.item_path_str(def_id)));
206 AstConvRequest::EnsureSuperPredicates(def_id) => {
208 &format!("the cycle begins when computing the supertraits of `{}`...",
209 tcx.item_path_str(def_id)));
211 AstConvRequest::GetTypeParameterBounds(id) => {
212 let def = tcx.type_parameter_def(id);
214 &format!("the cycle begins when computing the bounds \
215 for type parameter `{}`...",
220 for request in &cycle[1..] {
222 AstConvRequest::GetItemTypeScheme(def_id) |
223 AstConvRequest::GetTraitDef(def_id) => {
225 &format!("...which then requires processing `{}`...",
226 tcx.item_path_str(def_id)));
228 AstConvRequest::EnsureSuperPredicates(def_id) => {
230 &format!("...which then requires computing the supertraits of `{}`...",
231 tcx.item_path_str(def_id)));
233 AstConvRequest::GetTypeParameterBounds(id) => {
234 let def = tcx.type_parameter_def(id);
236 &format!("...which then requires computing the bounds \
237 for type parameter `{}`...",
244 AstConvRequest::GetItemTypeScheme(def_id) |
245 AstConvRequest::GetTraitDef(def_id) => {
247 &format!("...which then again requires processing `{}`, completing the cycle.",
248 tcx.item_path_str(def_id)));
250 AstConvRequest::EnsureSuperPredicates(def_id) => {
252 &format!("...which then again requires computing the supertraits of `{}`, \
253 completing the cycle.",
254 tcx.item_path_str(def_id)));
256 AstConvRequest::GetTypeParameterBounds(id) => {
257 let def = tcx.type_parameter_def(id);
259 &format!("...which then again requires computing the bounds \
260 for type parameter `{}`, completing the cycle.",
267 /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
268 fn get_trait_def(&self, trait_id: DefId)
269 -> &'tcx ty::TraitDef<'tcx>
273 if let Some(trait_id) = tcx.map.as_local_node_id(trait_id) {
274 let item = match tcx.map.get(trait_id) {
275 hir_map::NodeItem(item) => item,
276 _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
279 trait_def_of_item(self, &*item)
281 tcx.lookup_trait_def(trait_id)
285 /// Ensure that the (transitive) super predicates for
286 /// `trait_def_id` are available. This will report a cycle error
287 /// if a trait `X` (transitively) extends itself in some form.
288 fn ensure_super_predicates(&self, span: Span, trait_def_id: DefId)
289 -> Result<(), ErrorReported>
291 self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || {
292 let def_ids = ensure_super_predicates_step(self, trait_def_id);
294 for def_id in def_ids {
295 try!(self.ensure_super_predicates(span, def_id));
303 impl<'a,'tcx> ItemCtxt<'a,'tcx> {
304 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &hir::Ty) -> Ty<'tcx> {
305 ast_ty_to_ty(self, rs, ast_ty)
309 impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
310 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
312 fn get_item_type_scheme(&self, span: Span, id: DefId)
313 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
315 self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
316 Ok(type_scheme_of_def_id(self.ccx, id))
320 fn get_trait_def(&self, span: Span, id: DefId)
321 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
323 self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
324 Ok(self.ccx.get_trait_def(id))
328 fn ensure_super_predicates(&self,
331 -> Result<(), ErrorReported>
333 debug!("ensure_super_predicates(trait_def_id={:?})",
336 self.ccx.ensure_super_predicates(span, trait_def_id)
340 fn get_type_parameter_bounds(&self,
342 node_id: ast::NodeId)
343 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
345 self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
346 let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id)
348 .filter_map(|p| p.to_opt_poly_trait_ref())
354 fn trait_defines_associated_type_named(&self,
356 assoc_name: ast::Name)
359 if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) {
360 trait_defines_associated_type_named(self.ccx, trait_id, assoc_name)
362 let trait_def = self.tcx().lookup_trait_def(trait_def_id);
363 trait_def.associated_type_names.contains(&assoc_name)
368 _ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
369 _substs: Option<&mut Substs<'tcx>>,
370 _space: Option<ParamSpace>,
371 span: Span) -> Ty<'tcx> {
372 span_err!(self.tcx().sess, span, E0121,
373 "the type placeholder `_` is not allowed within types on item signatures");
377 fn projected_ty(&self,
379 trait_ref: ty::TraitRef<'tcx>,
380 item_name: ast::Name)
383 self.tcx().mk_projection(trait_ref, item_name)
387 /// Interface used to find the bounds on a type parameter from within
388 /// an `ItemCtxt`. This allows us to use multiple kinds of sources.
389 trait GetTypeParameterBounds<'tcx> {
390 fn get_type_parameter_bounds(&self,
391 astconv: &AstConv<'tcx>,
393 node_id: ast::NodeId)
394 -> Vec<ty::Predicate<'tcx>>;
397 /// Find bounds from both elements of the tuple.
398 impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
399 where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
401 fn get_type_parameter_bounds(&self,
402 astconv: &AstConv<'tcx>,
404 node_id: ast::NodeId)
405 -> Vec<ty::Predicate<'tcx>>
407 let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
408 v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id));
413 /// Empty set of bounds.
414 impl<'tcx> GetTypeParameterBounds<'tcx> for () {
415 fn get_type_parameter_bounds(&self,
416 _astconv: &AstConv<'tcx>,
418 _node_id: ast::NodeId)
419 -> Vec<ty::Predicate<'tcx>>
425 /// Find bounds from the parsed and converted predicates. This is
426 /// used when converting methods, because by that time the predicates
427 /// from the trait/impl have been fully converted.
428 impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
429 fn get_type_parameter_bounds(&self,
430 astconv: &AstConv<'tcx>,
432 node_id: ast::NodeId)
433 -> Vec<ty::Predicate<'tcx>>
435 let def = astconv.tcx().type_parameter_def(node_id);
439 .filter(|predicate| {
441 ty::Predicate::Trait(ref data) => {
442 data.skip_binder().self_ty().is_param(def.space, def.index)
444 ty::Predicate::TypeOutlives(ref data) => {
445 data.skip_binder().0.is_param(def.space, def.index)
447 ty::Predicate::Equate(..) |
448 ty::Predicate::RegionOutlives(..) |
449 ty::Predicate::WellFormed(..) |
450 ty::Predicate::ObjectSafe(..) |
451 ty::Predicate::Projection(..) => {
461 /// Find bounds from hir::Generics. This requires scanning through the
462 /// AST. We do this to avoid having to convert *all* the bounds, which
463 /// would create artificial cycles. Instead we can only convert the
464 /// bounds for a type parameter `X` if `X::Foo` is used.
465 impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
466 fn get_type_parameter_bounds(&self,
467 astconv: &AstConv<'tcx>,
469 node_id: ast::NodeId)
470 -> Vec<ty::Predicate<'tcx>>
472 // In the AST, bounds can derive from two places. Either
473 // written inline like `<T:Foo>` or in a where clause like
476 let def = astconv.tcx().type_parameter_def(node_id);
477 let ty = astconv.tcx().mk_param_from_def(&def);
482 .filter(|p| p.id == node_id)
483 .flat_map(|p| p.bounds.iter())
484 .flat_map(|b| predicates_from_bound(astconv, ty, b));
486 let from_where_clauses =
490 .filter_map(|wp| match *wp {
491 hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
494 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
495 .flat_map(|bp| bp.bounds.iter())
496 .flat_map(|b| predicates_from_bound(astconv, ty, b));
498 from_ty_params.chain(from_where_clauses).collect()
502 /// Tests whether this is the AST for a reference to the type
503 /// parameter with id `param_id`. We use this so as to avoid running
504 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
505 /// conversion of the type to avoid inducing unnecessary cycles.
506 fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
508 param_id: ast::NodeId)
511 if let hir::TyPath(None, _) = ast_ty.node {
512 let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
513 match path_res.base_def {
514 def::DefSelfTy(Some(def_id), None) => {
515 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
517 def::DefTyParam(_, _, def_id, _) => {
518 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
530 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
531 container: ImplOrTraitItemContainer,
534 vis: hir::Visibility,
535 sig: &hir::MethodSig,
536 untransformed_rcvr_ty: Ty<'tcx>,
537 rcvr_ty_generics: &ty::Generics<'tcx>,
538 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
539 let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics);
541 let ty_generic_predicates =
542 ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
544 let (fty, explicit_self_category) =
545 astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
546 sig, untransformed_rcvr_ty);
548 let def_id = ccx.tcx.map.local_def_id(id);
549 let ty_method = ty::Method::new(name,
551 ty_generic_predicates,
553 explicit_self_category,
558 let fty = ccx.tcx.mk_fn(Some(def_id),
559 ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
560 debug!("method {} (id {}) has type {:?}",
562 ccx.tcx.register_item_type(def_id, TypeScheme {
563 generics: ty_method.generics.clone(),
566 ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
568 write_ty_to_tcx(ccx.tcx, id, fty);
570 debug!("writing method type: def_id={:?} mty={:?}",
573 ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
574 ty::MethodTraitItem(Rc::new(ty_method)));
577 fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
578 struct_generics: &ty::Generics<'tcx>,
579 struct_predicates: &ty::GenericPredicates<'tcx>,
580 v: &hir::StructField,
581 ty_f: ty::FieldDefMaster<'tcx>)
583 let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
585 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
587 /* add the field to the tcache */
588 ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(v.node.id),
590 generics: struct_generics.clone(),
593 ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(v.node.id),
594 struct_predicates.clone());
597 fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
598 container: ImplOrTraitItemContainer,
601 vis: hir::Visibility,
605 ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
606 ty::GenericPredicates::empty());
608 write_ty_to_tcx(ccx.tcx, id, ty);
610 let associated_const = Rc::new(ty::AssociatedConst {
613 def_id: ccx.tcx.map.local_def_id(id),
614 container: container,
618 ccx.tcx.impl_or_trait_items.borrow_mut()
619 .insert(ccx.tcx.map.local_def_id(id), ty::ConstTraitItem(associated_const));
622 fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
623 container: ImplOrTraitItemContainer,
626 vis: hir::Visibility,
627 ty: Option<Ty<'tcx>>)
629 let associated_type = Rc::new(ty::AssociatedType {
633 def_id: ccx.tcx.map.local_def_id(id),
636 ccx.tcx.impl_or_trait_items.borrow_mut()
637 .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type));
640 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
642 generics: &hir::Generics,
643 thing: &'static str) {
644 let mut warn = false;
646 for ty_param in generics.ty_params.iter() {
647 for bound in ty_param.bounds.iter() {
649 hir::TraitTyParamBound(..) => {
652 hir::RegionTyParamBound(..) => { }
658 // According to accepted RFC #XXX, we should
659 // eventually accept these, but it will not be
660 // part of this PR. Still, convert to warning to
661 // make bootstrapping easier.
662 span_warn!(ccx.tcx.sess, span, E0122,
663 "trait bounds are not (yet) enforced \
669 fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
671 debug!("convert: item {} with id {}", it.name, it.id);
673 // These don't define types.
674 hir::ItemExternCrate(_) | hir::ItemUse(_) | hir::ItemMod(_) => {
676 hir::ItemForeignMod(ref foreign_mod) => {
677 for item in &foreign_mod.items {
678 convert_foreign_item(ccx, item);
681 hir::ItemEnum(ref enum_definition, _) => {
682 let (scheme, predicates) = convert_typed_item(ccx, it);
683 write_ty_to_tcx(tcx, it.id, scheme.ty);
684 convert_enum_variant_types(ccx,
685 tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)),
688 &enum_definition.variants);
690 hir::ItemDefaultImpl(_, ref ast_trait_ref) => {
692 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
697 tcx.record_trait_has_default_impl(trait_ref.def_id);
699 tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
707 // Create generics from the generics specified in the impl head.
708 debug!("convert: ast_generics={:?}", generics);
709 let def_id = ccx.tcx.map.local_def_id(it.id);
710 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
711 let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
713 debug!("convert: impl_bounds={:?}", ty_predicates);
715 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
716 write_ty_to_tcx(tcx, it.id, selfty);
718 tcx.register_item_type(def_id,
719 TypeScheme { generics: ty_generics.clone(),
721 if let &Some(ref ast_trait_ref) = opt_trait_ref {
722 tcx.impl_trait_refs.borrow_mut().insert(
724 Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
730 tcx.impl_trait_refs.borrow_mut().insert(def_id, None);
733 enforce_impl_params_are_constrained(tcx, generics, &mut ty_predicates, def_id);
734 tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone());
737 // If there is a trait reference, treat the methods as always public.
738 // This is to work around some incorrect behavior in privacy checking:
739 // when the method belongs to a trait, it should acquire the privacy
740 // from the trait, not the impl. Forcing the visibility to be public
741 // makes things sorta work.
742 let parent_visibility = if opt_trait_ref.is_some() {
748 // Convert all the associated consts.
749 // Also, check if there are any duplicate associated items
750 let mut seen_type_items = FnvHashSet();
751 let mut seen_value_items = FnvHashSet();
753 for impl_item in impl_items {
754 let seen_items = match impl_item.node {
755 hir::ImplItemKind::Type(_) => &mut seen_type_items,
756 _ => &mut seen_value_items,
758 if !seen_items.insert(impl_item.name) {
759 let desc = match impl_item.node {
760 hir::ImplItemKind::Const(_, _) => "associated constant",
761 hir::ImplItemKind::Type(_) => "associated type",
762 hir::ImplItemKind::Method(ref sig, _) =>
763 match sig.explicit_self.node {
764 hir::SelfStatic => "associated function",
769 span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
772 if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node {
773 let ty = ccx.icx(&ty_predicates)
774 .to_ty(&ExplicitRscope, &*ty);
775 tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id),
777 generics: ty_generics.clone(),
780 convert_associated_const(ccx, ImplContainer(def_id),
781 impl_item.name, impl_item.id,
782 impl_item.vis.inherit_from(parent_visibility),
783 ty, true /* has_value */);
787 // Convert all the associated types.
788 for impl_item in impl_items {
789 if let hir::ImplItemKind::Type(ref ty) = impl_item.node {
790 if opt_trait_ref.is_none() {
791 span_err!(tcx.sess, impl_item.span, E0202,
792 "associated types are not allowed in inherent impls");
795 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
797 convert_associated_type(ccx, ImplContainer(def_id),
798 impl_item.name, impl_item.id, impl_item.vis,
803 for impl_item in impl_items {
804 if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
805 // if the method specifies a visibility, use that, otherwise
806 // inherit the visibility from the impl (so `foo` in `pub impl
807 // { fn foo(); }` is public, but private in `impl { fn
809 let method_vis = impl_item.vis.inherit_from(parent_visibility);
811 convert_method(ccx, ImplContainer(def_id),
812 impl_item.name, impl_item.id, method_vis,
813 sig, selfty, &ty_generics, &ty_predicates);
817 enforce_impl_lifetimes_are_constrained(tcx, generics, def_id, impl_items);
819 hir::ItemTrait(_, _, _, ref trait_items) => {
820 let trait_def = trait_def_of_item(ccx, it);
821 let def_id = trait_def.trait_ref.def_id;
822 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
823 ccx.ensure_super_predicates(it.span, def_id);
824 convert_trait_predicates(ccx, it);
825 let trait_predicates = tcx.lookup_predicates(def_id);
827 debug!("convert: trait_bounds={:?}", trait_predicates);
829 // FIXME: is the ordering here important? I think it is.
830 let container = TraitContainer(def_id);
832 // Convert all the associated constants.
833 for trait_item in trait_items {
834 if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
835 let ty = ccx.icx(&trait_predicates)
836 .to_ty(&ExplicitRscope, ty);
837 tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id),
839 generics: trait_def.generics.clone(),
842 convert_associated_const(ccx,
852 // Convert all the associated types.
853 for trait_item in trait_items {
854 if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node {
855 let typ = opt_ty.as_ref().map({
856 |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
859 convert_associated_type(ccx,
868 // Convert all the methods
869 for trait_item in trait_items {
870 if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
884 // Add an entry mapping
885 let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
886 let def_id = ccx.tcx.map.local_def_id(trait_item.id);
887 match trait_item.node {
888 hir::ConstTraitItem(..) => ty::ConstTraitItemId(def_id),
889 hir::MethodTraitItem(..) => ty::MethodTraitItemId(def_id),
890 hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id)
893 tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
896 hir::ItemStruct(ref struct_def, _) => {
897 let (scheme, predicates) = convert_typed_item(ccx, it);
898 write_ty_to_tcx(tcx, it.id, scheme.ty);
900 let it_def_id = ccx.tcx.map.local_def_id(it.id);
901 let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant();
903 for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) {
904 convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
907 if !struct_def.is_struct() {
908 convert_variant_ctor(tcx, struct_def.id(), variant, scheme, predicates);
911 hir::ItemTy(_, ref generics) => {
912 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
913 let (scheme, _) = convert_typed_item(ccx, it);
914 write_ty_to_tcx(tcx, it.id, scheme.ty);
917 // This call populates the type cache with the converted type
918 // of the item in passing. All we have to do here is to write
919 // it into the node type table.
920 let (scheme, _) = convert_typed_item(ccx, it);
921 write_ty_to_tcx(tcx, it.id, scheme.ty);
926 fn convert_variant_ctor<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
927 ctor_id: ast::NodeId,
928 variant: ty::VariantDef<'tcx>,
929 scheme: ty::TypeScheme<'tcx>,
930 predicates: ty::GenericPredicates<'tcx>) {
931 let ctor_ty = match variant.kind() {
932 VariantKind::Unit | VariantKind::Struct => scheme.ty,
933 VariantKind::Tuple => {
937 .map(|field| field.unsubst_ty())
939 tcx.mk_ctor_fn(tcx.map.local_def_id(ctor_id),
944 write_ty_to_tcx(tcx, ctor_id, ctor_ty);
945 tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates);
946 tcx.register_item_type(tcx.map.local_def_id(ctor_id),
948 generics: scheme.generics,
953 fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
954 def: ty::AdtDefMaster<'tcx>,
955 scheme: ty::TypeScheme<'tcx>,
956 predicates: ty::GenericPredicates<'tcx>,
957 variants: &[hir::Variant]) {
958 // fill the field types
959 for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
960 for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) {
961 convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
964 // Convert the ctor, if any. This also registers the variant as
966 convert_variant_ctor(
968 variant.node.data.id(),
976 fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
980 def: &hir::VariantData) -> ty::VariantDefData<'tcx, 'tcx> {
981 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
982 let fields = def.fields().iter().map(|f| {
983 let fid = tcx.map.local_def_id(f.node.id);
985 hir::NamedField(name, vis) => {
986 let dup_span = seen_fields.get(&name).cloned();
987 if let Some(prev_span) = dup_span {
988 let mut err = struct_span_err!(tcx.sess, f.span, E0124,
989 "field `{}` is already declared",
991 span_note!(&mut err, prev_span, "previously declared here");
994 seen_fields.insert(name, f.span);
997 ty::FieldDefData::new(fid, name, vis)
999 hir::UnnamedField(vis) => {
1000 ty::FieldDefData::new(fid, special_idents::unnamed_field.name, vis)
1004 ty::VariantDefData {
1012 fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
1014 def: &hir::VariantData)
1015 -> ty::AdtDefMaster<'tcx>
1018 let did = tcx.map.local_def_id(it.id);
1019 let ctor_id = if !def.is_struct() {
1020 tcx.map.local_def_id(def.id())
1026 ty::AdtKind::Struct,
1027 vec![convert_struct_variant(tcx, ctor_id, it.name, 0, def)]
1031 fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
1034 -> ty::AdtDefMaster<'tcx>
1036 fn evaluate_disr_expr<'tcx>(tcx: &ty::ctxt<'tcx>,
1038 e: &hir::Expr) -> Option<ty::Disr> {
1039 debug!("disr expr, checking {}", pprust::expr_to_string(e));
1041 let hint = UncheckedExprHint(repr_ty);
1042 match const_eval::eval_const_expr_partial(tcx, e, hint, None) {
1043 Ok(ConstVal::Int(val)) => Some(val as ty::Disr),
1044 Ok(ConstVal::Uint(val)) => Some(val as ty::Disr),
1046 let sign_desc = if repr_ty.is_signed() {
1051 span_err!(tcx.sess, e.span, E0079,
1052 "expected {} integer constant",
1057 let mut diag = struct_span_err!(tcx.sess, err.span, E0080,
1058 "constant evaluation error: {}",
1060 if !e.span.contains(err.span) {
1061 diag.span_note(e.span, "for enum discriminant here");
1069 fn report_discrim_overflow(tcx: &ty::ctxt,
1072 repr_type: attr::IntType,
1073 prev_val: ty::Disr) {
1074 let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
1075 let computed_value = repr_type.disr_string(computed_value);
1076 let prev_val = repr_type.disr_string(prev_val);
1077 let repr_type = repr_type.to_ty(tcx);
1078 span_err!(tcx.sess, variant_span, E0370,
1079 "enum discriminant overflowed on value after {}: {}; \
1080 set explicitly via {} = {} if that is desired outcome",
1081 prev_val, repr_type, variant_name, computed_value);
1084 fn next_disr(tcx: &ty::ctxt,
1086 repr_type: attr::IntType,
1087 prev_disr_val: Option<ty::Disr>) -> Option<ty::Disr> {
1088 if let Some(prev_disr_val) = prev_disr_val {
1089 let result = repr_type.disr_incr(prev_disr_val);
1090 if let None = result {
1091 report_discrim_overflow(tcx, v.span, &v.node.name.as_str(),
1092 repr_type, prev_disr_val);
1096 Some(ty::INITIAL_DISCRIMINANT_VALUE)
1099 fn convert_enum_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
1102 -> ty::VariantDefData<'tcx, 'tcx>
1104 let did = tcx.map.local_def_id(v.node.data.id());
1105 let name = v.node.name;
1106 convert_struct_variant(tcx, did, name, disr, &v.node.data)
1108 let did = tcx.map.local_def_id(it.id);
1109 let repr_hints = tcx.lookup_repr_hints(did);
1110 let (repr_type, repr_type_ty) = tcx.enum_repr_type(repr_hints.get(0));
1111 let mut prev_disr = None;
1112 let variants = def.variants.iter().map(|v| {
1113 let disr = match v.node.disr_expr {
1114 Some(ref e) => evaluate_disr_expr(tcx, repr_type_ty, e),
1115 None => next_disr(tcx, v, repr_type, prev_disr)
1116 }.unwrap_or(repr_type.disr_wrap_incr(prev_disr));
1118 let v = convert_enum_variant(tcx, v, disr);
1119 prev_disr = Some(disr);
1122 tcx.intern_adt_def(tcx.map.local_def_id(it.id), ty::AdtKind::Enum, variants)
1125 /// Ensures that the super-predicates of the trait with def-id
1126 /// trait_def_id are converted and stored. This does NOT ensure that
1127 /// the transitive super-predicates are converted; that is the job of
1128 /// the `ensure_super_predicates()` method in the `AstConv` impl
1129 /// above. Returns a list of trait def-ids that must be ensured as
1130 /// well to guarantee that the transitive superpredicates are
1132 fn ensure_super_predicates_step(ccx: &CrateCtxt,
1133 trait_def_id: DefId)
1138 debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
1140 let trait_node_id = if let Some(n) = tcx.map.as_local_node_id(trait_def_id) {
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 item = match ccx.tcx.map.get(trait_node_id) {
1154 hir_map::NodeItem(item) => item,
1155 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1158 let (generics, bounds) = match item.node {
1159 hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
1160 _ => tcx.sess.span_bug(item.span,
1161 "ensure_super_predicates_step invoked on non-trait"),
1164 // In-scope when converting the superbounds for `Trait` are
1165 // that `Self:Trait` as well as any bounds that appear on the
1167 let trait_def = trait_def_of_item(ccx, item);
1168 let self_predicate = ty::GenericPredicates {
1169 predicates: VecPerParamSpace::new(vec![],
1170 vec![trait_def.trait_ref.to_predicate()],
1173 let scope = &(generics, &self_predicate);
1175 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1176 let self_param_ty = tcx.mk_self_type();
1177 let superbounds1 = compute_bounds(&ccx.icx(scope),
1183 let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
1185 // Convert any explicit superbounds in the where clause,
1186 // e.g. `trait Foo where Self : Bar`:
1187 let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
1189 // Combine the two lists to form the complete set of superbounds:
1190 let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
1191 let superpredicates = ty::GenericPredicates {
1192 predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
1194 debug!("superpredicates for trait {:?} = {:?}",
1195 tcx.map.local_def_id(item.id),
1198 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1203 let def_ids: Vec<_> = superpredicates.predicates
1205 .filter_map(|p| p.to_opt_poly_trait_ref())
1206 .map(|tr| tr.def_id())
1209 debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
1214 fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1216 -> &'tcx ty::TraitDef<'tcx>
1218 let def_id = ccx.tcx.map.local_def_id(it.id);
1221 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1225 let (unsafety, generics, items) = match it.node {
1226 hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
1227 _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
1230 let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
1231 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
1232 let mut err = ccx.tcx.sess.struct_span_err(
1234 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1235 which traits can use parenthetical notation");
1236 fileline_help!(&mut err, it.span,
1237 "add `#![feature(unboxed_closures)]` to \
1238 the crate attributes to use it");
1242 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1244 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1246 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1247 match trait_item.node {
1248 hir::TypeTraitItem(..) => Some(trait_item.name),
1253 let trait_ref = ty::TraitRef {
1258 let trait_def = ty::TraitDef::new(unsafety,
1262 associated_type_names);
1264 return tcx.intern_trait_def(trait_def);
1266 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1267 generics: &hir::Generics)
1272 // Creates a no-op substitution for the trait's type parameters.
1277 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1280 name: def.lifetime.name
1284 // Start with the generics in the type parameters...
1289 .map(|(i, def)| tcx.mk_param(TypeSpace,
1290 i as u32, def.name))
1293 // ...and also create the `Self` parameter.
1294 let self_ty = tcx.mk_self_type();
1296 Substs::new_trait(types, regions, self_ty)
1300 fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1301 trait_node_id: ast::NodeId,
1302 assoc_name: ast::Name)
1305 let item = match ccx.tcx.map.get(trait_node_id) {
1306 hir_map::NodeItem(item) => item,
1307 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1310 let trait_items = match item.node {
1311 hir::ItemTrait(_, _, _, ref trait_items) => trait_items,
1312 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
1315 trait_items.iter().any(|trait_item| {
1316 match trait_item.node {
1317 hir::TypeTraitItem(..) => trait_item.name == assoc_name,
1323 fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) {
1325 let trait_def = trait_def_of_item(ccx, it);
1327 let def_id = ccx.tcx.map.local_def_id(it.id);
1329 let (generics, items) = match it.node {
1330 hir::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1334 &format!("trait_def_of_item invoked on {:?}", s));
1338 let super_predicates = ccx.tcx.lookup_super_predicates(def_id);
1340 // `ty_generic_predicates` below will consider the bounds on the type
1341 // parameters (including `Self`) and the explicit where-clauses,
1342 // but to get the full set of predicates on a trait we need to add
1343 // in the supertrait bounds and anything declared on the
1344 // associated types.
1345 let mut base_predicates = super_predicates;
1347 // Add in a predicate that `Self:Trait` (where `Trait` is the
1348 // current trait). This is needed for builtin bounds.
1349 let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
1350 base_predicates.predicates.push(SelfSpace, self_predicate);
1352 // add in the explicit where-clauses
1353 let mut trait_predicates =
1354 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1356 let assoc_predicates = predicates_for_associated_types(ccx,
1359 trait_def.trait_ref,
1361 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
1363 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1364 assert!(prev_predicates.is_none());
1368 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1369 ast_generics: &hir::Generics,
1370 trait_predicates: &ty::GenericPredicates<'tcx>,
1371 self_trait_ref: ty::TraitRef<'tcx>,
1372 trait_items: &[hir::TraitItem])
1373 -> Vec<ty::Predicate<'tcx>>
1375 trait_items.iter().flat_map(|trait_item| {
1376 let bounds = match trait_item.node {
1377 hir::TypeTraitItem(ref bounds, _) => bounds,
1379 return vec!().into_iter();
1383 let assoc_ty = ccx.tcx.mk_projection(self_trait_ref,
1386 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1389 SizedByDefault::Yes,
1392 bounds.predicates(ccx.tcx, assoc_ty).into_iter()
1397 fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1399 -> ty::TypeScheme<'tcx>
1401 if let Some(node_id) = ccx.tcx.map.as_local_node_id(def_id) {
1402 match ccx.tcx.map.find(node_id) {
1403 Some(hir_map::NodeItem(item)) => {
1404 type_scheme_of_item(ccx, &*item)
1406 Some(hir_map::NodeForeignItem(foreign_item)) => {
1407 let abi = ccx.tcx.map.get_foreign_abi(node_id);
1408 type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
1411 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1412 in get_item_type_scheme(): {:?}",
1417 ccx.tcx.lookup_item_type(def_id)
1421 fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1423 -> ty::TypeScheme<'tcx>
1425 let item_def_id = ccx.tcx.map.local_def_id(item.id);
1426 ccx.tcx.tcache.memoize(item_def_id, || {
1427 // NB. Since the `memoized` function enters a new task, and we
1428 // are giving this task access to the item `item`, we must
1430 ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
1431 compute_type_scheme_of_item(ccx, item)
1435 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1437 -> ty::TypeScheme<'tcx>
1441 hir::ItemStatic(ref t, _, _) | hir::ItemConst(ref t, _) => {
1442 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
1443 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1445 hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
1446 let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1447 let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
1448 let ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(it.id)), tcx.mk_bare_fn(tofd));
1449 ty::TypeScheme { ty: ty, generics: ty_generics }
1451 hir::ItemTy(ref t, ref generics) => {
1452 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1453 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
1454 ty::TypeScheme { ty: ty, generics: ty_generics }
1456 hir::ItemEnum(ref ei, ref generics) => {
1457 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1458 let substs = mk_item_substs(ccx, &ty_generics);
1459 let def = convert_enum_def(tcx, it, ei);
1460 let t = tcx.mk_enum(def, tcx.mk_substs(substs));
1461 ty::TypeScheme { ty: t, generics: ty_generics }
1463 hir::ItemStruct(ref si, ref generics) => {
1464 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1465 let substs = mk_item_substs(ccx, &ty_generics);
1466 let def = convert_struct_def(tcx, it, si);
1467 let t = tcx.mk_struct(def, tcx.mk_substs(substs));
1468 ty::TypeScheme { ty: t, generics: ty_generics }
1470 hir::ItemDefaultImpl(..) |
1471 hir::ItemTrait(..) |
1474 hir::ItemForeignMod(..) |
1475 hir::ItemExternCrate(..) |
1476 hir::ItemUse(..) => {
1479 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1485 fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1487 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1491 let tag = type_scheme_of_item(ccx, it);
1492 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1493 let predicates = match it.node {
1494 hir::ItemStatic(..) | hir::ItemConst(..) => {
1495 ty::GenericPredicates::empty()
1497 hir::ItemFn(_, _, _, _, ref ast_generics, _) => {
1498 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
1500 hir::ItemTy(_, ref generics) => {
1501 ty_generic_predicates_for_type_or_impl(ccx, generics)
1503 hir::ItemEnum(_, ref generics) => {
1504 ty_generic_predicates_for_type_or_impl(ccx, generics)
1506 hir::ItemStruct(_, ref generics) => {
1507 ty_generic_predicates_for_type_or_impl(ccx, generics)
1509 hir::ItemDefaultImpl(..) |
1510 hir::ItemTrait(..) |
1511 hir::ItemExternCrate(..) |
1515 hir::ItemForeignMod(..) => {
1518 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1523 let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
1524 predicates.clone());
1525 assert!(prev_predicates.is_none());
1528 if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") {
1529 let object_lifetime_default_reprs: String =
1530 scheme.generics.types.iter()
1531 .map(|t| match t.object_lifetime_default {
1532 ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
1533 d => format!("{:?}", d),
1535 .collect::<Vec<String>>()
1538 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1541 return (scheme, predicates);
1544 fn type_scheme_of_foreign_item<'a, 'tcx>(
1545 ccx: &CrateCtxt<'a, 'tcx>,
1546 item: &hir::ForeignItem,
1548 -> ty::TypeScheme<'tcx>
1550 let item_def_id = ccx.tcx.map.local_def_id(item.id);
1551 ccx.tcx.tcache.memoize(item_def_id, || {
1552 // NB. Since the `memoized` function enters a new task, and we
1553 // are giving this task access to the item `item`, we must
1555 ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
1556 compute_type_scheme_of_foreign_item(ccx, item, abi)
1560 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
1561 ccx: &CrateCtxt<'a, 'tcx>,
1562 it: &hir::ForeignItem,
1564 -> ty::TypeScheme<'tcx>
1567 hir::ForeignItemFn(ref fn_decl, ref generics) => {
1568 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1570 hir::ForeignItemStatic(ref t, _) => {
1572 generics: ty::Generics::empty(),
1573 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1579 fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1580 it: &hir::ForeignItem)
1582 // For reasons I cannot fully articulate, I do so hate the AST
1583 // map, and I regard each time that I use it as a personal and
1584 // moral failing, but at the moment it seems like the only
1585 // convenient way to extract the ABI. - ndm
1587 let abi = tcx.map.get_foreign_abi(it.id);
1589 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1590 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1592 let predicates = match it.node {
1593 hir::ForeignItemFn(_, ref generics) => {
1594 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
1596 hir::ForeignItemStatic(..) => {
1597 ty::GenericPredicates::empty()
1601 let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
1603 assert!(prev_predicates.is_none());
1606 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1607 generics: &hir::Generics)
1608 -> ty::Generics<'tcx> {
1609 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
1612 fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1613 generics: &hir::Generics)
1614 -> ty::GenericPredicates<'tcx>
1616 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1619 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1620 trait_id: ast::NodeId,
1621 substs: &'tcx Substs<'tcx>,
1622 ast_generics: &hir::Generics)
1623 -> ty::Generics<'tcx>
1625 debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
1626 ccx.tcx.map.local_def_id(trait_id), substs);
1628 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1630 // Add in the self type parameter.
1632 // Something of a hack: use the node id for the trait, also as
1633 // the node id for the Self type parameter.
1634 let param_id = trait_id;
1636 let parent = ccx.tcx.map.get_parent(param_id);
1638 let def = ty::TypeParameterDef {
1641 name: special_idents::type_self.name,
1642 def_id: ccx.tcx.map.local_def_id(param_id),
1643 default_def_id: ccx.tcx.map.local_def_id(parent),
1645 object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
1648 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1650 generics.types.push(SelfSpace, def);
1655 fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1656 generics: &hir::Generics,
1657 base_generics: &ty::Generics<'tcx>)
1658 -> ty::Generics<'tcx>
1660 ty_generics(ccx, FnSpace, generics, base_generics)
1663 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1664 generics: &hir::Generics,
1665 base_predicates: &ty::GenericPredicates<'tcx>)
1666 -> ty::GenericPredicates<'tcx>
1668 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1671 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1672 fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1673 bounds: &mut ty::BuiltinBounds,
1674 ast_bounds: &[hir::TyParamBound],
1677 let tcx = astconv.tcx();
1679 // Try to find an unbound in bounds.
1680 let mut unbound = None;
1681 for ab in ast_bounds {
1682 if let &hir::TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
1683 if unbound.is_none() {
1684 assert!(ptr.bound_lifetimes.is_empty());
1685 unbound = Some(ptr.trait_ref.clone());
1687 span_err!(tcx.sess, span, E0203,
1688 "type parameter has more than one relaxed default \
1689 bound, only one is supported");
1694 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1697 // FIXME(#8559) currently requires the unbound to be built-in.
1698 let trait_def_id = tcx.trait_ref_to_def_id(tpb);
1700 Ok(kind_id) if trait_def_id != kind_id => {
1701 tcx.sess.span_warn(span,
1702 "default bound relaxed for a type parameter, but \
1703 this does nothing because the given bound is not \
1704 a default. Only `?Sized` is supported");
1705 tcx.try_add_builtin_trait(kind_id, bounds);
1710 _ if kind_id.is_ok() => {
1711 tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
1713 // No lang item for Sized, so we can't add it as a bound.
1718 /// Returns the early-bound lifetimes declared in this generics
1719 /// listing. For anything other than fns/methods, this is just all
1720 /// the lifetimes that are declared. For fns or methods, we have to
1721 /// screen out those that do not appear in any where-clauses etc using
1722 /// `resolve_lifetime::early_bound_lifetimes`.
1723 fn early_bound_lifetimes_from_generics(space: ParamSpace,
1724 ast_generics: &hir::Generics)
1725 -> Vec<hir::LifetimeDef>
1728 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1729 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1733 fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1735 ast_generics: &hir::Generics,
1736 base_predicates: &ty::GenericPredicates<'tcx>)
1737 -> ty::GenericPredicates<'tcx>
1740 let mut result = base_predicates.clone();
1742 // Collect the predicates that were written inline by the user on each
1743 // type parameter (e.g., `<T:Foo>`).
1744 for (index, param) in ast_generics.ty_params.iter().enumerate() {
1745 let index = index as u32;
1746 let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx);
1747 let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
1750 SizedByDefault::Yes,
1752 let predicates = bounds.predicates(ccx.tcx, param_ty);
1753 result.predicates.extend(space, predicates.into_iter());
1756 // Collect the region predicates that were declared inline as
1757 // well. In the case of parameters declared on a fn or method, we
1758 // have to be careful to only iterate over early-bound regions.
1759 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1760 for (index, param) in early_lifetimes.iter().enumerate() {
1761 let index = index as u32;
1763 ty::ReEarlyBound(ty::EarlyBoundRegion {
1766 name: param.lifetime.name
1768 for bound in ¶m.bounds {
1769 let bound_region = ast_region_to_region(ccx.tcx, bound);
1770 let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
1771 result.predicates.push(space, outlives.to_predicate());
1775 // Add in the bounds that appear in the where-clause
1776 let where_clause = &ast_generics.where_clause;
1777 for predicate in &where_clause.predicates {
1779 &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
1780 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1782 &*bound_pred.bounded_ty);
1784 for bound in bound_pred.bounds.iter() {
1786 &hir::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1787 let mut projections = Vec::new();
1790 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1795 result.predicates.push(space, trait_ref.to_predicate());
1797 for projection in &projections {
1798 result.predicates.push(space, projection.to_predicate());
1802 &hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
1803 let region = ast_region_to_region(tcx, lifetime);
1804 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1805 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1811 &hir::WherePredicate::RegionPredicate(ref region_pred) => {
1812 let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime);
1813 for bound in ®ion_pred.bounds {
1814 let r2 = ast_region_to_region(tcx, bound);
1815 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1816 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1820 &hir::WherePredicate::EqPredicate(ref eq_pred) => {
1822 tcx.sess.span_bug(eq_pred.span,
1823 "Equality constraints are not yet \
1824 implemented (#20041)")
1832 fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1834 ast_generics: &hir::Generics,
1835 base_generics: &ty::Generics<'tcx>)
1836 -> ty::Generics<'tcx>
1839 let mut result = base_generics.clone();
1841 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1842 for (i, l) in early_lifetimes.iter().enumerate() {
1843 let bounds = l.bounds.iter()
1844 .map(|l| ast_region_to_region(tcx, l))
1846 let def = ty::RegionParameterDef { name: l.lifetime.name,
1849 def_id: ccx.tcx.map.local_def_id(l.lifetime.id),
1851 result.regions.push(space, def);
1854 assert!(result.types.is_empty_in(space));
1856 // Now create the real type parameters.
1857 for i in 0..ast_generics.ty_params.len() {
1858 let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
1859 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1860 result.types.push(space, def);
1866 fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1872 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
1874 for leaf_ty in ty.walk() {
1875 if let ty::TyParam(p) = leaf_ty.sty {
1876 if p.space == space && p.idx >= index {
1877 span_err!(ccx.tcx.sess, path.span, E0128,
1878 "type parameters with a default cannot use \
1879 forward declared identifiers");
1881 return ccx.tcx.types.err
1889 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1890 ast_generics: &hir::Generics,
1893 -> ty::TypeParameterDef<'tcx>
1895 let param = &ast_generics.ty_params[index as usize];
1898 match tcx.ty_param_defs.borrow().get(¶m.id) {
1899 Some(d) => { return d.clone(); }
1903 let default = param.default.as_ref().map(
1904 |def| convert_default_type_parameter(ccx, def, space, index)
1907 let object_lifetime_default =
1908 compute_object_lifetime_default(ccx, param.id,
1909 ¶m.bounds, &ast_generics.where_clause);
1911 let parent = tcx.map.get_parent(param.id);
1913 let def = ty::TypeParameterDef {
1917 def_id: ccx.tcx.map.local_def_id(param.id),
1918 default_def_id: ccx.tcx.map.local_def_id(parent),
1920 object_lifetime_default: object_lifetime_default,
1923 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1928 /// Scan the bounds and where-clauses on a parameter to extract bounds
1929 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1930 /// This runs as part of computing the minimal type scheme, so we
1931 /// intentionally avoid just asking astconv to convert all the where
1932 /// clauses into a `ty::Predicate`. This is because that could induce
1933 /// artificial cycles.
1934 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1935 param_id: ast::NodeId,
1936 param_bounds: &[hir::TyParamBound],
1937 where_clause: &hir::WhereClause)
1938 -> ty::ObjectLifetimeDefault
1940 let inline_bounds = from_bounds(ccx, param_bounds);
1941 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
1942 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1943 .chain(where_bounds)
1945 return if all_bounds.len() > 1 {
1946 ty::ObjectLifetimeDefault::Ambiguous
1947 } else if all_bounds.len() == 0 {
1948 ty::ObjectLifetimeDefault::BaseDefault
1950 ty::ObjectLifetimeDefault::Specific(
1951 all_bounds.into_iter().next().unwrap())
1954 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1955 bounds: &[hir::TyParamBound])
1959 .filter_map(|bound| {
1961 hir::TraitTyParamBound(..) =>
1963 hir::RegionTyParamBound(ref lifetime) =>
1964 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
1970 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1971 param_id: ast::NodeId,
1972 predicates: &[hir::WherePredicate])
1976 .flat_map(|predicate| {
1978 hir::WherePredicate::BoundPredicate(ref data) => {
1979 if data.bound_lifetimes.is_empty() &&
1980 is_param(ccx.tcx, &data.bounded_ty, param_id)
1982 from_bounds(ccx, &data.bounds).into_iter()
1984 Vec::new().into_iter()
1987 hir::WherePredicate::RegionPredicate(..) |
1988 hir::WherePredicate::EqPredicate(..) => {
1989 Vec::new().into_iter()
1997 enum SizedByDefault { Yes, No, }
1999 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
2000 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
2001 /// built-in trait (formerly known as kind): Send.
2002 fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
2003 param_ty: ty::Ty<'tcx>,
2004 ast_bounds: &[hir::TyParamBound],
2005 sized_by_default: SizedByDefault,
2007 -> astconv::Bounds<'tcx>
2010 conv_param_bounds(astconv,
2015 if let SizedByDefault::Yes = sized_by_default {
2016 add_unsized_bound(astconv,
2017 &mut bounds.builtin_bounds,
2022 bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
2027 /// Converts a specific TyParamBound from the AST into a set of
2028 /// predicates that apply to the self-type. A vector is returned
2029 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2030 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2031 /// and `<T as Bar>::X == i32`).
2032 fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2034 bound: &hir::TyParamBound)
2035 -> Vec<ty::Predicate<'tcx>>
2038 hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
2039 let mut projections = Vec::new();
2040 let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
2041 projections.into_iter()
2042 .map(|p| p.to_predicate())
2043 .chain(Some(pred.to_predicate()))
2046 hir::RegionTyParamBound(ref lifetime) => {
2047 let region = ast_region_to_region(astconv.tcx(), lifetime);
2048 let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
2049 vec![ty::Predicate::TypeOutlives(pred)]
2051 hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {
2057 fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2059 trait_ref: &hir::PolyTraitRef,
2060 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2061 -> ty::PolyTraitRef<'tcx>
2063 astconv::instantiate_poly_trait_ref(astconv,
2070 fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
2072 param_ty: ty::Ty<'tcx>,
2073 ast_bounds: &[hir::TyParamBound])
2074 -> astconv::Bounds<'tcx>
2076 let tcx = astconv.tcx();
2077 let astconv::PartitionedBounds {
2081 } = astconv::partition_bounds(tcx, span, &ast_bounds);
2083 let mut projection_bounds = Vec::new();
2085 let trait_bounds: Vec<ty::PolyTraitRef> =
2087 .map(|bound| conv_poly_trait_ref(astconv,
2090 &mut projection_bounds))
2093 let region_bounds: Vec<ty::Region> =
2094 region_bounds.into_iter()
2095 .map(|r| ast_region_to_region(tcx, r))
2099 region_bounds: region_bounds,
2100 builtin_bounds: builtin_bounds,
2101 trait_bounds: trait_bounds,
2102 projection_bounds: projection_bounds,
2106 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
2107 ccx: &CrateCtxt<'a, 'tcx>,
2109 ast_generics: &hir::Generics,
2111 -> ty::TypeScheme<'tcx>
2113 for i in &decl.inputs {
2114 match (*i).pat.node {
2115 hir::PatIdent(_, _, _) => (),
2118 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2119 "patterns aren't allowed in foreign function declarations");
2124 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
2126 let rb = BindingRscope::new();
2127 let input_tys = decl.inputs
2129 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
2132 let output = match decl.output {
2133 hir::Return(ref ty) =>
2134 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
2135 hir::DefaultReturn(..) =>
2136 ty::FnConverging(ccx.tcx.mk_nil()),
2137 hir::NoReturn(..) =>
2141 let t_fn = ccx.tcx.mk_fn(None,
2142 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2144 unsafety: hir::Unsafety::Unsafe,
2145 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2147 variadic: decl.variadic}),
2151 generics: ty_generics,
2156 fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2157 ty_generics: &ty::Generics<'tcx>)
2161 ty_generics.types.map(
2162 |def| ccx.tcx.mk_param_from_def(def));
2165 ty_generics.regions.map(
2166 |def| def.to_early_bound_region());
2168 Substs::new(types, regions)
2171 /// Checks that all the type parameters on an impl
2172 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2173 ast_generics: &hir::Generics,
2174 impl_predicates: &mut ty::GenericPredicates<'tcx>,
2177 let impl_scheme = tcx.lookup_item_type(impl_def_id);
2178 let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
2180 assert!(impl_predicates.predicates.is_empty_in(FnSpace));
2181 assert!(impl_predicates.predicates.is_empty_in(SelfSpace));
2183 // The trait reference is an input, so find all type parameters
2184 // reachable from there, to start (if this is an inherent impl,
2185 // then just examine the self type).
2186 let mut input_parameters: HashSet<_> =
2187 ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
2188 if let Some(ref trait_ref) = impl_trait_ref {
2189 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
2192 ctp::setup_constraining_predicates(tcx,
2193 impl_predicates.predicates.get_mut_slice(TypeSpace),
2195 &mut input_parameters);
2197 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2198 let param_ty = ty::ParamTy { space: TypeSpace,
2200 name: ty_param.name };
2201 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
2202 report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.to_string());
2207 fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2208 ast_generics: &hir::Generics,
2210 impl_items: &[hir::ImplItem])
2212 // Every lifetime used in an associated type must be constrained.
2213 let impl_scheme = tcx.lookup_item_type(impl_def_id);
2214 let impl_predicates = tcx.lookup_predicates(impl_def_id);
2215 let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
2217 let mut input_parameters: HashSet<_> =
2218 ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
2219 if let Some(ref trait_ref) = impl_trait_ref {
2220 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
2222 ctp::identify_constrained_type_params(tcx,
2223 &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
2225 let lifetimes_in_associated_types: HashSet<_> =
2227 .map(|item| tcx.impl_or_trait_item(tcx.map.local_def_id(item.id)))
2228 .filter_map(|item| match item {
2229 ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
2230 ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
2232 .flat_map(|ty| ctp::parameters_for_type(ty, true))
2233 .filter_map(|p| match p {
2234 ctp::Parameter::Type(_) => None,
2235 ctp::Parameter::Region(r) => Some(r),
2239 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2240 let region = ty::EarlyBoundRegion { space: TypeSpace,
2241 index: index as u32,
2242 name: lifetime_def.lifetime.name };
2244 lifetimes_in_associated_types.contains(®ion) && // (*)
2245 !input_parameters.contains(&ctp::Parameter::Region(region))
2247 report_unused_parameter(tcx, lifetime_def.lifetime.span,
2248 "lifetime", ®ion.name.to_string());
2252 // (*) This is a horrible concession to reality. I think it'd be
2253 // better to just ban unconstrianed lifetimes outright, but in
2254 // practice people do non-hygenic macros like:
2257 // macro_rules! __impl_slice_eq1 {
2258 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2259 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2266 // In a concession to backwards compatbility, we continue to
2267 // permit those, so long as the lifetimes aren't used in
2268 // associated types. I believe this is sound, because lifetimes
2269 // used elsewhere are not projected back out.
2272 fn report_unused_parameter(tcx: &ty::ctxt,
2277 span_err!(tcx.sess, span, E0207,
2278 "the {} parameter `{}` is not constrained by the \
2279 impl trait, self type, or predicates",