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::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
76 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
77 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
80 use util::common::{ErrorReported, memoized};
81 use util::nodemap::{FnvHashMap, FnvHashSet};
83 use util::ppaux::{Repr,UserString};
86 use std::cell::RefCell;
87 use std::collections::HashSet;
93 use syntax::ast_util::local_def;
94 use syntax::codemap::Span;
95 use syntax::parse::token::special_idents;
96 use syntax::parse::token;
100 ///////////////////////////////////////////////////////////////////////////
103 pub fn collect_item_types(tcx: &ty::ctxt) {
104 let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
106 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
107 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
109 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
110 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
113 ///////////////////////////////////////////////////////////////////////////
115 struct CrateCtxt<'a,'tcx:'a> {
116 tcx: &'a ty::ctxt<'tcx>,
118 // This stack is used to identify cycles in the user's source.
119 // Note that these cycles can cross multiple items.
120 stack: RefCell<Vec<AstConvRequest>>,
123 /// Context specific to some particular item. This is what implements
124 /// AstConv. It has information about the predicates that are defined
125 /// on the trait. Unfortunately, this predicate information is
126 /// available in various different forms at various points in the
127 /// process. So we can't just store a pointer to e.g. the AST or the
128 /// parsed ty form, we have to be more flexible. To this end, the
129 /// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
130 /// that it uses to satisfy `get_type_parameter_bounds` requests.
131 /// This object might draw the information from the AST
132 /// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
133 /// or both (a tuple).
134 struct ItemCtxt<'a,'tcx:'a> {
135 ccx: &'a CrateCtxt<'a,'tcx>,
136 param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
139 #[derive(Copy, Clone, PartialEq, Eq)]
140 enum AstConvRequest {
141 GetItemTypeScheme(ast::DefId),
142 GetTraitDef(ast::DefId),
143 EnsureSuperPredicates(ast::DefId),
144 GetTypeParameterBounds(ast::NodeId),
147 ///////////////////////////////////////////////////////////////////////////
148 // First phase: just collect *trait definitions* -- basically, the set
149 // of type parameters and supertraits. This is information we need to
150 // know later when parsing field defs.
152 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
153 ccx: &'a CrateCtxt<'a, 'tcx>
156 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
157 fn visit_item(&mut self, i: &ast::Item) {
159 ast::ItemTrait(..) => {
160 // computing the trait def also fills in the table
161 let _ = trait_def_of_item(self.ccx, i);
166 visit::walk_item(self, i);
170 ///////////////////////////////////////////////////////////////////////////
171 // Second phase: collection proper.
173 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
174 ccx: &'a CrateCtxt<'a, 'tcx>
177 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
178 fn visit_item(&mut self, i: &ast::Item) {
179 convert_item(self.ccx, i);
180 visit::walk_item(self, i);
182 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
183 convert_foreign_item(self.ccx, i);
184 visit::walk_foreign_item(self, i);
188 ///////////////////////////////////////////////////////////////////////////
189 // Utility types and common code for the above passes.
191 impl<'a,'tcx> CrateCtxt<'a,'tcx> {
192 fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
193 ItemCtxt { ccx: self, param_bounds: param_bounds }
196 fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
197 let def_id = local_def(method_id);
198 match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
199 ty::MethodTraitItem(ref mty) => mty.clone(),
201 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
206 fn cycle_check<F,R>(&self,
208 request: AstConvRequest,
210 -> Result<R,ErrorReported>
211 where F: FnOnce() -> Result<R,ErrorReported>
214 let mut stack = self.stack.borrow_mut();
215 match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
218 let cycle = &stack[i..];
219 self.report_cycle(span, cycle);
220 return Err(ErrorReported);
228 self.stack.borrow_mut().pop();
232 fn report_cycle(&self,
234 cycle: &[AstConvRequest])
236 assert!(!cycle.is_empty());
241 &format!("unsupported cyclic reference between types/traits detected"));
244 AstConvRequest::GetItemTypeScheme(def_id) |
245 AstConvRequest::GetTraitDef(def_id) => {
247 &format!("the cycle begins when processing `{}`...",
248 ty::item_path_str(tcx, def_id)));
250 AstConvRequest::EnsureSuperPredicates(def_id) => {
252 &format!("the cycle begins when computing the supertraits of `{}`...",
253 ty::item_path_str(tcx, def_id)));
255 AstConvRequest::GetTypeParameterBounds(id) => {
256 let def = tcx.type_parameter_def(id);
258 &format!("the cycle begins when computing the bounds \
259 for type parameter `{}`...",
260 def.name.user_string(tcx)));
264 for request in cycle[1..].iter() {
266 AstConvRequest::GetItemTypeScheme(def_id) |
267 AstConvRequest::GetTraitDef(def_id) => {
269 &format!("...which then requires processing `{}`...",
270 ty::item_path_str(tcx, def_id)));
272 AstConvRequest::EnsureSuperPredicates(def_id) => {
274 &format!("...which then requires computing the supertraits of `{}`...",
275 ty::item_path_str(tcx, def_id)));
277 AstConvRequest::GetTypeParameterBounds(id) => {
278 let def = tcx.type_parameter_def(id);
280 &format!("...which then requires computing the bounds \
281 for type parameter `{}`...",
282 def.name.user_string(tcx)));
288 AstConvRequest::GetItemTypeScheme(def_id) |
289 AstConvRequest::GetTraitDef(def_id) => {
291 &format!("...which then again requires processing `{}`, completing the cycle.",
292 ty::item_path_str(tcx, def_id)));
294 AstConvRequest::EnsureSuperPredicates(def_id) => {
296 &format!("...which then again requires computing the supertraits of `{}`, \
297 completing the cycle.",
298 ty::item_path_str(tcx, def_id)));
300 AstConvRequest::GetTypeParameterBounds(id) => {
301 let def = tcx.type_parameter_def(id);
303 &format!("...which then again requires computing the bounds \
304 for type parameter `{}`, completing the cycle.",
305 def.name.user_string(tcx)));
310 /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
311 fn get_trait_def(&self, trait_id: ast::DefId)
312 -> Rc<ty::TraitDef<'tcx>>
316 if trait_id.krate != ast::LOCAL_CRATE {
317 return ty::lookup_trait_def(tcx, trait_id)
320 let item = match tcx.map.get(trait_id.node) {
321 ast_map::NodeItem(item) => item,
322 _ => tcx.sess.bug(&format!("get_trait_def({}): not an item", trait_id.repr(tcx)))
325 trait_def_of_item(self, &*item)
328 /// Ensure that the (transitive) super predicates for
329 /// `trait_def_id` are available. This will report a cycle error
330 /// if a trait `X` (transitively) extends itself in some form.
331 fn ensure_super_predicates(&self, span: Span, trait_def_id: ast::DefId)
332 -> Result<(), ErrorReported>
334 self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || {
335 let def_ids = ensure_super_predicates_step(self, trait_def_id);
337 for def_id in def_ids {
338 try!(self.ensure_super_predicates(span, def_id));
346 impl<'a,'tcx> ItemCtxt<'a,'tcx> {
347 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
348 ast_ty_to_ty(self, rs, ast_ty)
352 impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
353 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
355 fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
356 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
358 self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
359 Ok(type_scheme_of_def_id(self.ccx, id))
363 fn get_trait_def(&self, span: Span, id: ast::DefId)
364 -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
366 self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
367 Ok(self.ccx.get_trait_def(id))
371 fn ensure_super_predicates(&self,
373 trait_def_id: ast::DefId)
374 -> Result<(), ErrorReported>
376 debug!("ensure_super_predicates(trait_def_id={})",
377 trait_def_id.repr(self.tcx()));
379 self.ccx.ensure_super_predicates(span, trait_def_id)
383 fn get_type_parameter_bounds(&self,
385 node_id: ast::NodeId)
386 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
388 self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
389 let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id)
391 .filter_map(|p| p.to_opt_poly_trait_ref())
397 fn trait_defines_associated_type_named(&self,
398 trait_def_id: ast::DefId,
399 assoc_name: ast::Name)
402 if trait_def_id.krate == ast::LOCAL_CRATE {
403 trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
405 let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
406 trait_def.associated_type_names.contains(&assoc_name)
410 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
411 span_err!(self.tcx().sess, span, E0121,
412 "the type placeholder `_` is not allowed within types on item signatures");
416 fn projected_ty(&self,
418 trait_ref: Rc<ty::TraitRef<'tcx>>,
419 item_name: ast::Name)
422 ty::mk_projection(self.tcx(), trait_ref, item_name)
426 /// Interface used to find the bounds on a type parameter from within
427 /// an `ItemCtxt`. This allows us to use multiple kinds of sources.
428 trait GetTypeParameterBounds<'tcx> {
429 fn get_type_parameter_bounds(&self,
430 astconv: &AstConv<'tcx>,
432 node_id: ast::NodeId)
433 -> Vec<ty::Predicate<'tcx>>;
436 /// Find bounds from both elements of the tuple.
437 impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
438 where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
440 fn get_type_parameter_bounds(&self,
441 astconv: &AstConv<'tcx>,
443 node_id: ast::NodeId)
444 -> Vec<ty::Predicate<'tcx>>
446 let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
447 v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id).into_iter());
452 /// Empty set of bounds.
453 impl<'tcx> GetTypeParameterBounds<'tcx> for () {
454 fn get_type_parameter_bounds(&self,
455 _astconv: &AstConv<'tcx>,
457 _node_id: ast::NodeId)
458 -> Vec<ty::Predicate<'tcx>>
464 /// Find bounds from the parsed and converted predicates. This is
465 /// used when converting methods, because by that time the predicates
466 /// from the trait/impl have been fully converted.
467 impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
468 fn get_type_parameter_bounds(&self,
469 astconv: &AstConv<'tcx>,
471 node_id: ast::NodeId)
472 -> Vec<ty::Predicate<'tcx>>
474 let def = astconv.tcx().type_parameter_def(node_id);
478 .filter(|predicate| {
480 ty::Predicate::Trait(ref data) => {
481 data.skip_binder().self_ty().is_param(def.space, def.index)
483 ty::Predicate::TypeOutlives(ref data) => {
484 data.skip_binder().0.is_param(def.space, def.index)
486 ty::Predicate::Equate(..) |
487 ty::Predicate::RegionOutlives(..) |
488 ty::Predicate::Projection(..) => {
498 /// Find bounds from ast::Generics. This requires scanning through the
499 /// AST. We do this to avoid having to convert *all* the bounds, which
500 /// would create artificial cycles. Instead we can only convert the
501 /// bounds for those a type parameter `X` if `X::Foo` is used.
502 impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
503 fn get_type_parameter_bounds(&self,
504 astconv: &AstConv<'tcx>,
506 node_id: ast::NodeId)
507 -> Vec<ty::Predicate<'tcx>>
509 // In the AST, bounds can derive from two places. Either
510 // written inline like `<T:Foo>` or in a where clause like
513 let def = astconv.tcx().type_parameter_def(node_id);
514 let ty = ty::mk_param_from_def(astconv.tcx(), &def);
519 .filter(|p| p.id == node_id)
520 .flat_map(|p| p.bounds.iter())
521 .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter());
523 let from_where_clauses =
527 .filter_map(|wp| match *wp {
528 ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
531 .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
532 .flat_map(|bp| bp.bounds.iter())
533 .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter());
535 from_ty_params.chain(from_where_clauses).collect()
539 /// Tests whether this is the AST for a reference to the type
540 /// parameter with id `param_id`. We use this so as to avoid running
541 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
542 /// conversion of the type to avoid inducing unnecessary cycles.
543 fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
545 param_id: ast::NodeId)
548 if let ast::TyPath(None, _) = ast_ty.node {
549 let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
550 match path_res.base_def {
551 def::DefSelfTy(Some(def_id), None) => {
552 path_res.depth == 0 && def_id.node == param_id
554 def::DefTyParam(_, _, def_id, _) => {
555 path_res.depth == 0 && def_id == local_def(param_id)
566 fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
567 enum_scheme: ty::TypeScheme<'tcx>,
568 enum_predicates: ty::GenericPredicates<'tcx>,
569 variants: &[P<ast::Variant>]) {
571 let icx = ccx.icx(&enum_predicates);
573 // Create a set of parameter types shared among all the variants.
574 for variant in variants {
575 let variant_def_id = local_def(variant.node.id);
577 // Nullary enum constructors get turned into constants; n-ary enum
578 // constructors get turned into functions.
579 let result_ty = match variant.node.kind {
580 ast::TupleVariantKind(ref args) if !args.is_empty() => {
581 let rs = ExplicitRscope;
582 let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
583 ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty)
586 ast::TupleVariantKind(_) => {
590 ast::StructVariantKind(ref struct_def) => {
591 convert_struct(ccx, &**struct_def, enum_scheme.clone(),
592 enum_predicates.clone(), variant.node.id);
597 let variant_scheme = TypeScheme {
598 generics: enum_scheme.generics.clone(),
602 tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
603 tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
604 write_ty_to_tcx(tcx, variant.node.id, result_ty);
608 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
609 container: ImplOrTraitItemContainer,
610 sig: &ast::MethodSig,
613 vis: ast::Visibility,
614 untransformed_rcvr_ty: Ty<'tcx>,
615 rcvr_ty_generics: &ty::Generics<'tcx>,
616 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
617 let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics);
619 let ty_generic_predicates =
620 ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
622 let (fty, explicit_self_category) =
623 astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
624 sig, untransformed_rcvr_ty);
626 let def_id = local_def(id);
627 let ty_method = ty::Method::new(ident.name,
629 ty_generic_predicates,
631 explicit_self_category,
637 let fty = ty::mk_bare_fn(ccx.tcx, Some(def_id),
638 ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
639 debug!("method {} (id {}) has type {}",
640 ident.repr(ccx.tcx), id, fty.repr(ccx.tcx));
641 ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
642 generics: ty_method.generics.clone(),
645 ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
647 write_ty_to_tcx(ccx.tcx, id, fty);
649 debug!("writing method type: def_id={:?} mty={}",
650 def_id, ty_method.repr(ccx.tcx));
652 ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id,
653 ty::MethodTraitItem(Rc::new(ty_method)));
656 fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
657 struct_generics: &ty::Generics<'tcx>,
658 struct_predicates: &ty::GenericPredicates<'tcx>,
659 v: &ast::StructField,
663 let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
664 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
666 /* add the field to the tcache */
667 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
669 generics: struct_generics.clone(),
672 ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
673 struct_predicates.clone());
676 ast::NamedField(ident, visibility) => {
679 id: local_def(v.node.id),
684 ast::UnnamedField(visibility) => {
686 name: special_idents::unnamed_field.name,
687 id: local_def(v.node.id),
695 fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
696 container: ImplOrTraitItemContainer,
699 vis: ast::Visibility,
701 default: Option<&ast::Expr>)
703 ccx.tcx.predicates.borrow_mut().insert(local_def(id),
704 ty::GenericPredicates::empty());
706 write_ty_to_tcx(ccx.tcx, id, ty);
707 let default_id = default.map(|expr| local_def(expr.id));
709 let associated_const = Rc::new(ty::AssociatedConst {
712 def_id: local_def(id),
713 container: container,
717 ccx.tcx.impl_or_trait_items.borrow_mut()
718 .insert(local_def(id), ty::ConstTraitItem(associated_const));
721 fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
722 container: ImplOrTraitItemContainer,
725 vis: ast::Visibility)
727 let associated_type = Rc::new(ty::AssociatedType {
730 def_id: local_def(id),
733 ccx.tcx.impl_or_trait_items.borrow_mut()
734 .insert(local_def(id), ty::TypeTraitItem(associated_type));
737 fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
738 container: ImplOrTraitItemContainer,
740 untransformed_rcvr_ty: Ty<'tcx>,
741 rcvr_ty_generics: &ty::Generics<'tcx>,
742 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
743 where I: Iterator<Item=(&'i ast::MethodSig, ast::NodeId, ast::Ident, ast::Visibility, Span)>
745 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={}, rcvr_ty_predicates={})",
746 untransformed_rcvr_ty.repr(ccx.tcx),
747 rcvr_ty_generics.repr(ccx.tcx),
748 rcvr_ty_predicates.repr(ccx.tcx));
751 let mut seen_methods = FnvHashSet();
752 for (sig, id, ident, vis, span) in methods {
753 if !seen_methods.insert(ident.name) {
754 span_err!(tcx.sess, span, E0201, "duplicate method");
763 untransformed_rcvr_ty,
769 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
771 generics: &ast::Generics,
772 thing: &'static str) {
773 let mut warn = false;
775 for ty_param in &*generics.ty_params {
776 for bound in &*ty_param.bounds {
778 ast::TraitTyParamBound(..) => {
781 ast::RegionTyParamBound(..) => { }
787 // According to accepted RFC #XXX, we should
788 // eventually accept these, but it will not be
789 // part of this PR. Still, convert to warning to
790 // make bootstrapping easier.
791 span_warn!(ccx.tcx.sess, span, E0122,
792 "trait bounds are not (yet) enforced \
798 fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
800 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
802 // These don't define types.
803 ast::ItemExternCrate(_) | ast::ItemUse(_) |
804 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
806 ast::ItemEnum(ref enum_definition, _) => {
807 let (scheme, predicates) = convert_typed_item(ccx, it);
808 write_ty_to_tcx(tcx, it.id, scheme.ty);
809 get_enum_variant_types(ccx,
812 &enum_definition.variants);
814 ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
816 astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
821 ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
823 tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
830 // Create generics from the generics specified in the impl head.
832 debug!("convert: ast_generics={:?}", generics);
833 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
834 let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
836 debug!("convert: impl_bounds={:?}", ty_predicates);
838 let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
839 write_ty_to_tcx(tcx, it.id, selfty);
841 tcx.tcache.borrow_mut().insert(local_def(it.id),
842 TypeScheme { generics: ty_generics.clone(),
844 tcx.predicates.borrow_mut().insert(local_def(it.id),
845 ty_predicates.clone());
847 // If there is a trait reference, treat the methods as always public.
848 // This is to work around some incorrect behavior in privacy checking:
849 // when the method belongs to a trait, it should acquire the privacy
850 // from the trait, not the impl. Forcing the visibility to be public
851 // makes things sorta work.
852 let parent_visibility = if opt_trait_ref.is_some() {
858 // Convert all the associated consts.
859 for impl_item in impl_items {
860 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
861 let ty = ccx.icx(&ty_predicates)
862 .to_ty(&ExplicitRscope, &*ty);
863 tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
865 generics: ty_generics.clone(),
868 convert_associated_const(ccx, ImplContainer(local_def(it.id)),
869 impl_item.ident, impl_item.id,
870 impl_item.vis.inherit_from(parent_visibility),
875 // Convert all the associated types.
876 for impl_item in impl_items {
877 if let ast::TypeImplItem(ref ty) = impl_item.node {
878 if opt_trait_ref.is_none() {
879 span_err!(tcx.sess, impl_item.span, E0202,
880 "associated items are not allowed in inherent impls");
883 as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
884 impl_item.ident, impl_item.id, impl_item.vis);
886 let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
887 tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
889 generics: ty::Generics::empty(),
892 tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
893 ty::GenericPredicates::empty());
894 write_ty_to_tcx(tcx, impl_item.id, typ);
898 let methods = impl_items.iter().filter_map(|ii| {
899 if let ast::MethodImplItem(ref sig, _) = ii.node {
900 // if the method specifies a visibility, use that, otherwise
901 // inherit the visibility from the impl (so `foo` in `pub impl
902 // { fn foo(); }` is public, but private in `priv impl { fn
904 let method_vis = ii.vis.inherit_from(parent_visibility);
905 Some((sig, ii.id, ii.ident, method_vis, ii.span))
911 ImplContainer(local_def(it.id)),
917 for impl_item in impl_items {
918 if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
919 let body_id = body.id;
920 check_method_self_type(ccx,
921 &BindingRscope::new(),
922 ccx.method_ty(impl_item.id),
929 if let Some(ref ast_trait_ref) = *opt_trait_ref {
931 astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
936 tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
939 enforce_impl_params_are_constrained(tcx,
944 ast::ItemTrait(_, _, _, ref trait_items) => {
945 let trait_def = trait_def_of_item(ccx, it);
946 let _: Result<(), ErrorReported> = // any error is already reported, can ignore
947 ccx.ensure_super_predicates(it.span, local_def(it.id));
948 convert_trait_predicates(ccx, it);
949 let trait_predicates = ty::lookup_predicates(tcx, local_def(it.id));
951 debug!("convert: trait_bounds={:?}", trait_predicates);
953 // Convert all the associated types.
954 for trait_item in trait_items {
955 match trait_item.node {
956 ast::ConstTraitItem(ref ty, ref default) => {
957 let ty = ccx.icx(&trait_predicates)
958 .to_ty(&ExplicitRscope, ty);
959 tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
961 generics: trait_def.generics.clone(),
964 convert_associated_const(ccx, TraitContainer(local_def(it.id)),
965 trait_item.ident, trait_item.id,
966 ast::Public, ty, default.as_ref().map(|d| &**d));
972 // Convert all the associated types.
973 for trait_item in trait_items {
974 match trait_item.node {
975 ast::TypeTraitItem(..) => {
976 as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
977 trait_item.ident, trait_item.id, ast::Public);
983 let methods = trait_items.iter().filter_map(|ti| {
984 let sig = match ti.node {
985 ast::MethodTraitItem(ref sig, _) => sig,
988 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
991 // Run convert_methods on the trait methods.
993 TraitContainer(local_def(it.id)),
995 ty::mk_self_type(tcx),
999 // Add an entry mapping
1000 let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
1001 let def_id = local_def(trait_item.id);
1002 match trait_item.node {
1003 ast::ConstTraitItem(..) => {
1004 ty::ConstTraitItemId(def_id)
1006 ast::MethodTraitItem(..) => {
1007 ty::MethodTraitItemId(def_id)
1009 ast::TypeTraitItem(..) => {
1010 ty::TypeTraitItemId(def_id)
1014 tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids);
1016 // This must be done after `collect_trait_methods` so that
1017 // we have a method type stored for every method.
1018 for trait_item in trait_items {
1019 let sig = match trait_item.node {
1020 ast::MethodTraitItem(ref sig, _) => sig,
1023 check_method_self_type(ccx,
1024 &BindingRscope::new(),
1025 ccx.method_ty(trait_item.id),
1026 ty::mk_self_type(tcx),
1031 ast::ItemStruct(ref struct_def, _) => {
1032 // Write the class type.
1033 let (scheme, predicates) = convert_typed_item(ccx, it);
1034 write_ty_to_tcx(tcx, it.id, scheme.ty);
1035 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
1037 ast::ItemTy(_, ref generics) => {
1038 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
1039 let (scheme, _) = convert_typed_item(ccx, it);
1040 write_ty_to_tcx(tcx, it.id, scheme.ty);
1043 // This call populates the type cache with the converted type
1044 // of the item in passing. All we have to do here is to write
1045 // it into the node type table.
1046 let (scheme, _) = convert_typed_item(ccx, it);
1047 write_ty_to_tcx(tcx, it.id, scheme.ty);
1052 fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1053 struct_def: &ast::StructDef,
1054 scheme: ty::TypeScheme<'tcx>,
1055 predicates: ty::GenericPredicates<'tcx>,
1059 // Write the type of each of the members and check for duplicate fields.
1060 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
1061 let field_tys = struct_def.fields.iter().map(|f| {
1062 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
1064 if result.name != special_idents::unnamed_field.name {
1065 let dup = match seen_fields.get(&result.name) {
1066 Some(prev_span) => {
1067 span_err!(tcx.sess, f.span, E0124,
1068 "field `{}` is already declared",
1069 token::get_name(result.name));
1070 span_note!(tcx.sess, *prev_span, "previously declared here");
1075 // FIXME(#6393) this whole dup thing is just to satisfy
1076 // the borrow checker :-(
1078 seen_fields.insert(result.name, f.span);
1085 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
1087 let substs = mk_item_substs(ccx, &scheme.generics);
1088 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
1090 // If this struct is enum-like or tuple-like, create the type of its
1092 match struct_def.ctor_id {
1095 if struct_def.fields.is_empty() {
1097 write_ty_to_tcx(tcx, ctor_id, selfty);
1099 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
1100 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1101 } else if struct_def.fields[0].node.kind.is_unnamed() {
1103 let inputs: Vec<_> =
1106 .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
1110 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
1114 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
1115 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
1117 generics: scheme.generics,
1120 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
1126 /// Ensures that the super-predicates of the trait with def-id
1127 /// trait_def_id are converted and stored. This does NOT ensure that
1128 /// the transitive super-predicates are converted; that is the job of
1129 /// the `ensure_super_predicates()` method in the `AstConv` impl
1130 /// above. Returns a list of trait def-ids that must be ensured as
1131 /// well to guarantee that the transitive superpredicates are
1133 fn ensure_super_predicates_step(ccx: &CrateCtxt,
1134 trait_def_id: ast::DefId)
1139 debug!("ensure_super_predicates_step(trait_def_id={})", trait_def_id.repr(tcx));
1141 if trait_def_id.krate != ast::LOCAL_CRATE {
1142 // If this trait comes from an external crate, then all of the
1143 // supertraits it may depend on also must come from external
1144 // crates, and hence all of them already have their
1145 // super-predicates "converted" (and available from crate
1146 // meta-data), so there is no need to transitively test them.
1150 let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned();
1151 let superpredicates = superpredicates.unwrap_or_else(|| {
1152 let trait_node_id = trait_def_id.node;
1154 let item = match ccx.tcx.map.get(trait_node_id) {
1155 ast_map::NodeItem(item) => item,
1156 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1159 let (generics, bounds) = match item.node {
1160 ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
1161 _ => tcx.sess.span_bug(item.span,
1162 "ensure_super_predicates_step invoked on non-trait"),
1165 // In-scope when converting the superbounds for `Trait` are
1166 // that `Self:Trait` as well as any bounds that appear on the
1168 let trait_def = trait_def_of_item(ccx, item);
1169 let self_predicate = ty::GenericPredicates {
1170 predicates: VecPerParamSpace::new(vec![],
1171 vec![trait_def.trait_ref.as_predicate()],
1174 let scope = &(generics, &self_predicate);
1176 // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
1177 let self_param_ty = ty::mk_self_type(tcx);
1178 let superbounds1 = compute_bounds(&ccx.icx(scope), self_param_ty, bounds,
1179 SizedByDefault::No, item.span);
1180 let superbounds1 = ty::predicates(tcx, self_param_ty, &superbounds1);
1182 // Convert any explicit superbounds in the where clause,
1183 // e.g. `trait Foo where Self : Bar`:
1184 let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id);
1186 // Combine the two lists to form the complete set of superbounds:
1187 let superbounds = superbounds1.into_iter().chain(superbounds2.into_iter()).collect();
1188 let superpredicates = ty::GenericPredicates {
1189 predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
1191 debug!("superpredicates for trait {} = {}",
1192 local_def(item.id).repr(ccx.tcx),
1193 superpredicates.repr(ccx.tcx));
1195 tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
1200 let def_ids: Vec<_> = superpredicates.predicates
1202 .filter_map(|p| p.to_opt_poly_trait_ref())
1203 .map(|tr| tr.def_id())
1206 debug!("ensure_super_predicates_step: def_ids={}", def_ids.repr(tcx));
1211 fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1213 -> Rc<ty::TraitDef<'tcx>>
1215 let def_id = local_def(it.id);
1218 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
1222 let (unsafety, generics, items) = match it.node {
1223 ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
1224 _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
1227 let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
1228 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
1229 ccx.tcx.sess.span_err(
1231 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
1232 which traits can use parenthetical notation");
1233 fileline_help!(ccx.tcx.sess, it.span,
1234 "add `#![feature(unboxed_closures)]` to \
1235 the crate attributes to use it");
1238 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
1240 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
1242 let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
1243 match trait_item.node {
1244 ast::TypeTraitItem(..) => Some(trait_item.ident.name),
1249 let trait_ref = Rc::new(ty::TraitRef {
1254 let trait_def = Rc::new(ty::TraitDef {
1255 paren_sugar: paren_sugar,
1257 generics: ty_generics,
1258 trait_ref: trait_ref,
1259 associated_type_names: associated_type_names,
1262 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
1266 fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1267 generics: &ast::Generics)
1272 // Creates a no-op substitution for the trait's type parameters.
1277 .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
1278 param_id: def.lifetime.id,
1281 name: def.lifetime.name
1285 // Start with the generics in the type parameters...
1290 .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
1291 i as u32, def.ident.name))
1294 // ...and also create the `Self` parameter.
1295 let self_ty = ty::mk_self_type(tcx);
1297 Substs::new_trait(types, regions, self_ty)
1301 fn trait_defines_associated_type_named(ccx: &CrateCtxt,
1302 trait_node_id: ast::NodeId,
1303 assoc_name: ast::Name)
1306 let item = match ccx.tcx.map.get(trait_node_id) {
1307 ast_map::NodeItem(item) => item,
1308 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
1311 let trait_items = match item.node {
1312 ast::ItemTrait(_, _, _, ref trait_items) => trait_items,
1313 _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
1316 trait_items.iter().any(|trait_item| {
1317 match trait_item.node {
1318 ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
1324 fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
1326 let trait_def = trait_def_of_item(ccx, it);
1328 let def_id = local_def(it.id);
1330 let (generics, items) = match it.node {
1331 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1335 &format!("trait_def_of_item invoked on {:?}", s));
1339 let super_predicates = ty::lookup_super_predicates(ccx.tcx, def_id);
1341 // `ty_generic_predicates` below will consider the bounds on the type
1342 // parameters (including `Self`) and the explicit where-clauses,
1343 // but to get the full set of predicates on a trait we need to add
1344 // in the supertrait bounds and anything declared on the
1345 // associated types.
1346 let mut base_predicates = super_predicates;
1348 // Add in a predicate that `Self:Trait` (where `Trait` is the
1349 // current trait). This is needed for builtin bounds.
1350 let self_predicate = trait_def.trait_ref.to_poly_trait_ref().as_predicate();
1351 base_predicates.predicates.push(SelfSpace, self_predicate);
1353 // add in the explicit where-clauses
1354 let mut trait_predicates =
1355 ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
1357 let assoc_predicates = predicates_for_associated_types(ccx,
1360 &trait_def.trait_ref,
1362 trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
1364 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1365 assert!(prev_predicates.is_none());
1369 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1370 ast_generics: &ast::Generics,
1371 trait_predicates: &ty::GenericPredicates<'tcx>,
1372 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1373 trait_items: &[P<ast::TraitItem>])
1374 -> Vec<ty::Predicate<'tcx>>
1376 trait_items.iter().flat_map(|trait_item| {
1377 let bounds = match trait_item.node {
1378 ast::TypeTraitItem(ref bounds, _) => bounds,
1380 return vec!().into_iter();
1384 let assoc_ty = ty::mk_projection(ccx.tcx,
1385 self_trait_ref.clone(),
1386 trait_item.ident.name);
1388 let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
1391 SizedByDefault::Yes,
1394 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1399 fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1401 -> ty::TypeScheme<'tcx>
1403 if def_id.krate != ast::LOCAL_CRATE {
1404 return ty::lookup_item_type(ccx.tcx, def_id);
1407 match ccx.tcx.map.find(def_id.node) {
1408 Some(ast_map::NodeItem(item)) => {
1409 type_scheme_of_item(ccx, &*item)
1411 Some(ast_map::NodeForeignItem(foreign_item)) => {
1412 let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
1413 type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
1416 ccx.tcx.sess.bug(&format!("unexpected sort of node \
1417 in get_item_type_scheme(): {:?}",
1423 fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1425 -> ty::TypeScheme<'tcx>
1427 memoized(&ccx.tcx.tcache,
1429 |_| compute_type_scheme_of_item(ccx, it))
1432 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1434 -> ty::TypeScheme<'tcx>
1438 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
1439 let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
1440 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1442 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
1443 let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
1444 let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
1445 let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
1446 ty::TypeScheme { ty: ty, generics: ty_generics }
1448 ast::ItemTy(ref t, ref generics) => {
1449 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1450 let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
1451 ty::TypeScheme { ty: ty, generics: ty_generics }
1453 ast::ItemEnum(_, ref generics) => {
1454 // Create a new generic polytype.
1455 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1456 let substs = mk_item_substs(ccx, &ty_generics);
1457 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
1458 ty::TypeScheme { ty: t, generics: ty_generics }
1460 ast::ItemStruct(_, ref generics) => {
1461 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1462 let substs = mk_item_substs(ccx, &ty_generics);
1463 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
1464 ty::TypeScheme { ty: t, generics: ty_generics }
1466 ast::ItemDefaultImpl(..) |
1467 ast::ItemTrait(..) |
1470 ast::ItemForeignMod(..) |
1471 ast::ItemExternCrate(..) |
1473 ast::ItemMac(..) => {
1476 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1482 fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1484 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1488 let tag = type_scheme_of_item(ccx, it);
1489 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1490 let predicates = match it.node {
1491 ast::ItemStatic(..) | ast::ItemConst(..) => {
1492 ty::GenericPredicates::empty()
1494 ast::ItemFn(_, _, _, ref ast_generics, _) => {
1495 ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
1497 ast::ItemTy(_, ref generics) => {
1498 ty_generic_predicates_for_type_or_impl(ccx, generics)
1500 ast::ItemEnum(_, ref generics) => {
1501 ty_generic_predicates_for_type_or_impl(ccx, generics)
1503 ast::ItemStruct(_, ref generics) => {
1504 ty_generic_predicates_for_type_or_impl(ccx, generics)
1506 ast::ItemDefaultImpl(..) |
1507 ast::ItemTrait(..) |
1508 ast::ItemExternCrate(..) |
1512 ast::ItemForeignMod(..) |
1513 ast::ItemMac(..) => {
1516 &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1521 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1522 predicates.clone());
1523 assert!(prev_predicates.is_none());
1526 if ty::has_attr(tcx, local_def(it.id), "rustc_object_lifetime_default") {
1527 let object_lifetime_default_reprs: String =
1528 scheme.generics.types.iter()
1529 .map(|t| match t.object_lifetime_default {
1530 Some(ty::ObjectLifetimeDefault::Specific(r)) =>
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 it: &ast::ForeignItem,
1548 -> ty::TypeScheme<'tcx>
1550 memoized(&ccx.tcx.tcache,
1552 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1555 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
1556 ccx: &CrateCtxt<'a, 'tcx>,
1557 it: &ast::ForeignItem,
1559 -> ty::TypeScheme<'tcx>
1562 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1563 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1565 ast::ForeignItemStatic(ref t, _) => {
1567 generics: ty::Generics::empty(),
1568 ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
1574 fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1575 it: &ast::ForeignItem)
1577 // For reasons I cannot fully articulate, I do so hate the AST
1578 // map, and I regard each time that I use it as a personal and
1579 // moral failing, but at the moment it seems like the only
1580 // convenient way to extract the ABI. - ndm
1582 let abi = tcx.map.get_foreign_abi(it.id);
1584 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1585 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1587 let predicates = match it.node {
1588 ast::ForeignItemFn(_, ref generics) => {
1589 ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
1591 ast::ForeignItemStatic(..) => {
1592 ty::GenericPredicates::empty()
1596 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1597 assert!(prev_predicates.is_none());
1600 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1601 generics: &ast::Generics)
1602 -> ty::Generics<'tcx> {
1603 ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
1606 fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1607 generics: &ast::Generics)
1608 -> ty::GenericPredicates<'tcx>
1610 ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
1613 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1614 trait_id: ast::NodeId,
1615 substs: &'tcx Substs<'tcx>,
1616 ast_generics: &ast::Generics)
1617 -> ty::Generics<'tcx>
1619 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1620 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1622 let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
1624 // Add in the self type parameter.
1626 // Something of a hack: use the node id for the trait, also as
1627 // the node id for the Self type parameter.
1628 let param_id = trait_id;
1630 let def = ty::TypeParameterDef {
1633 name: special_idents::type_self.name,
1634 def_id: local_def(param_id),
1636 object_lifetime_default: None,
1639 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1641 generics.types.push(SelfSpace, def);
1646 fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1647 generics: &ast::Generics,
1648 base_generics: &ty::Generics<'tcx>)
1649 -> ty::Generics<'tcx>
1651 ty_generics(ccx, FnSpace, generics, base_generics)
1654 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1655 generics: &ast::Generics,
1656 base_predicates: &ty::GenericPredicates<'tcx>)
1657 -> ty::GenericPredicates<'tcx>
1659 ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
1662 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1663 fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
1664 bounds: &mut ty::BuiltinBounds,
1665 ast_bounds: &[ast::TyParamBound],
1668 let tcx = astconv.tcx();
1670 // Try to find an unbound in bounds.
1671 let mut unbound = None;
1672 for ab in ast_bounds {
1673 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1674 if unbound.is_none() {
1675 assert!(ptr.bound_lifetimes.is_empty());
1676 unbound = Some(ptr.trait_ref.clone());
1678 span_err!(tcx.sess, span, E0203,
1679 "type parameter has more than one relaxed default \
1680 bound, only one is supported");
1685 let kind_id = tcx.lang_items.require(SizedTraitLangItem);
1688 // FIXME(#8559) currently requires the unbound to be built-in.
1689 let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
1691 Ok(kind_id) if trait_def_id != kind_id => {
1692 tcx.sess.span_warn(span,
1693 "default bound relaxed for a type parameter, but \
1694 this does nothing because the given bound is not \
1695 a default. Only `?Sized` is supported");
1696 ty::try_add_builtin_trait(tcx, kind_id, bounds);
1701 _ if kind_id.is_ok() => {
1702 ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
1704 // No lang item for Sized, so we can't add it as a bound.
1709 /// Returns the early-bound lifetimes declared in this generics
1710 /// listing. For anything other than fns/methods, this is just all
1711 /// the lifetimes that are declared. For fns or methods, we have to
1712 /// screen out those that do not appear in any where-clauses etc using
1713 /// `resolve_lifetime::early_bound_lifetimes`.
1714 fn early_bound_lifetimes_from_generics(space: ParamSpace,
1715 ast_generics: &ast::Generics)
1716 -> Vec<ast::LifetimeDef>
1719 SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
1720 FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
1724 fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1726 ast_generics: &ast::Generics,
1727 base_predicates: &ty::GenericPredicates<'tcx>)
1728 -> ty::GenericPredicates<'tcx>
1731 let mut result = base_predicates.clone();
1733 // Collect the predicates that were written inline by the user on each
1734 // type parameter (e.g., `<T:Foo>`).
1735 for (index, param) in ast_generics.ty_params.iter().enumerate() {
1736 let index = index as u32;
1737 let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
1738 let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
1741 SizedByDefault::Yes,
1743 let predicates = ty::predicates(ccx.tcx, param_ty, &bounds);
1744 result.predicates.extend(space, predicates.into_iter());
1747 // Collect the region predicates that were declared inline as
1748 // well. In the case of parameters declared on a fn or method, we
1749 // have to be careful to only iterate over early-bound regions.
1750 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1751 for (index, param) in early_lifetimes.iter().enumerate() {
1752 let index = index as u32;
1754 ty::ReEarlyBound(ty::EarlyBoundRegion {
1755 param_id: param.lifetime.id,
1758 name: param.lifetime.name
1760 for bound in ¶m.bounds {
1761 let bound_region = ast_region_to_region(ccx.tcx, bound);
1762 let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
1763 result.predicates.push(space, outlives.as_predicate());
1767 // Add in the bounds that appear in the where-clause
1768 let where_clause = &ast_generics.where_clause;
1769 for predicate in &where_clause.predicates {
1771 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1772 let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
1774 &*bound_pred.bounded_ty);
1776 for bound in &*bound_pred.bounds {
1778 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1779 let mut projections = Vec::new();
1782 conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
1787 result.predicates.push(space, trait_ref.as_predicate());
1789 for projection in &projections {
1790 result.predicates.push(space, projection.as_predicate());
1794 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1795 let region = ast_region_to_region(tcx, lifetime);
1796 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1797 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1803 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1804 let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime);
1805 for bound in ®ion_pred.bounds {
1806 let r2 = ast_region_to_region(tcx, bound);
1807 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1808 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1812 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1814 tcx.sess.span_bug(eq_pred.span,
1815 "Equality constraints are not yet \
1816 implemented (#20041)")
1824 fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1826 ast_generics: &ast::Generics,
1827 base_generics: &ty::Generics<'tcx>)
1828 -> ty::Generics<'tcx>
1831 let mut result = base_generics.clone();
1833 let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
1834 for (i, l) in early_lifetimes.iter().enumerate() {
1835 let bounds = l.bounds.iter()
1836 .map(|l| ast_region_to_region(tcx, l))
1838 let def = ty::RegionParameterDef { name: l.lifetime.name,
1841 def_id: local_def(l.lifetime.id),
1843 result.regions.push(space, def);
1846 assert!(result.types.is_empty_in(space));
1848 // Now create the real type parameters.
1849 for i in 0..ast_generics.ty_params.len() {
1850 let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
1851 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1852 result.types.push(space, def);
1858 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1859 ast_generics: &ast::Generics,
1862 -> ty::TypeParameterDef<'tcx>
1864 let param = &ast_generics.ty_params[index as usize];
1867 match tcx.ty_param_defs.borrow().get(¶m.id) {
1868 Some(d) => { return d.clone(); }
1872 let default = match param.default {
1875 let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
1876 let cur_idx = index;
1878 ty::walk_ty(ty, |t| {
1880 ty::ty_param(p) => if p.idx > cur_idx {
1881 span_err!(tcx.sess, path.span, E0128,
1882 "type parameters with a default cannot use \
1883 forward declared identifiers");
1893 let object_lifetime_default =
1894 compute_object_lifetime_default(ccx, param.id,
1895 ¶m.bounds, &ast_generics.where_clause);
1897 let def = ty::TypeParameterDef {
1900 name: param.ident.name,
1901 def_id: local_def(param.id),
1903 object_lifetime_default: object_lifetime_default,
1906 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1911 /// Scan the bounds and where-clauses on a parameter to extract bounds
1912 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1913 /// This runs as part of computing the minimal type scheme, so we
1914 /// intentionally avoid just asking astconv to convert all the where
1915 /// clauses into a `ty::Predicate`. This is because that could induce
1916 /// artificial cycles.
1917 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1918 param_id: ast::NodeId,
1919 param_bounds: &[ast::TyParamBound],
1920 where_clause: &ast::WhereClause)
1921 -> Option<ty::ObjectLifetimeDefault>
1923 let inline_bounds = from_bounds(ccx, param_bounds);
1924 let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
1925 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1926 .chain(where_bounds.into_iter())
1928 return if all_bounds.len() > 1 {
1929 Some(ty::ObjectLifetimeDefault::Ambiguous)
1931 all_bounds.into_iter()
1933 .map(ty::ObjectLifetimeDefault::Specific)
1936 fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1937 bounds: &[ast::TyParamBound])
1941 .filter_map(|bound| {
1943 ast::TraitTyParamBound(..) =>
1945 ast::RegionTyParamBound(ref lifetime) =>
1946 Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
1952 fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
1953 param_id: ast::NodeId,
1954 predicates: &[ast::WherePredicate])
1958 .flat_map(|predicate| {
1960 ast::WherePredicate::BoundPredicate(ref data) => {
1961 if data.bound_lifetimes.is_empty() &&
1962 is_param(ccx.tcx, &data.bounded_ty, param_id)
1964 from_bounds(ccx, &data.bounds).into_iter()
1966 Vec::new().into_iter()
1969 ast::WherePredicate::RegionPredicate(..) |
1970 ast::WherePredicate::EqPredicate(..) => {
1971 Vec::new().into_iter()
1979 enum SizedByDefault { Yes, No, }
1981 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1982 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1983 /// built-in trait (formerly known as kind): Send.
1984 fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
1985 param_ty: ty::Ty<'tcx>,
1986 ast_bounds: &[ast::TyParamBound],
1987 sized_by_default: SizedByDefault,
1989 -> ty::ParamBounds<'tcx>
1991 let mut param_bounds = conv_param_bounds(astconv,
1996 if let SizedByDefault::Yes = sized_by_default {
1997 add_unsized_bound(astconv,
1998 &mut param_bounds.builtin_bounds,
2003 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
2008 /// Converts a specific TyParamBound from the AST into a set of
2009 /// predicates that apply to the self-type. A vector is returned
2010 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
2011 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
2012 /// and `<T as Bar>::X == i32`).
2013 fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
2015 bound: &ast::TyParamBound)
2016 -> Vec<ty::Predicate<'tcx>>
2019 ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
2020 let mut projections = Vec::new();
2021 let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
2022 projections.into_iter()
2023 .map(|p| p.as_predicate())
2024 .chain(Some(pred.as_predicate()).into_iter())
2027 ast::RegionTyParamBound(ref lifetime) => {
2028 let region = ast_region_to_region(astconv.tcx(), lifetime);
2029 let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
2030 vec![ty::Predicate::TypeOutlives(pred)]
2032 ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {
2038 fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
2040 trait_ref: &ast::PolyTraitRef,
2041 projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
2042 -> ty::PolyTraitRef<'tcx>
2044 astconv::instantiate_poly_trait_ref(astconv,
2051 fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
2053 param_ty: ty::Ty<'tcx>,
2054 ast_bounds: &[ast::TyParamBound])
2055 -> ty::ParamBounds<'tcx>
2057 let tcx = astconv.tcx();
2058 let astconv::PartitionedBounds {
2062 } = astconv::partition_bounds(tcx, span, &ast_bounds);
2064 let mut projection_bounds = Vec::new();
2066 let trait_bounds: Vec<ty::PolyTraitRef> =
2068 .map(|bound| conv_poly_trait_ref(astconv,
2071 &mut projection_bounds))
2074 let region_bounds: Vec<ty::Region> =
2075 region_bounds.into_iter()
2076 .map(|r| ast_region_to_region(tcx, r))
2080 region_bounds: region_bounds,
2081 builtin_bounds: builtin_bounds,
2082 trait_bounds: trait_bounds,
2083 projection_bounds: projection_bounds,
2087 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
2088 ccx: &CrateCtxt<'a, 'tcx>,
2090 ast_generics: &ast::Generics,
2092 -> ty::TypeScheme<'tcx>
2094 for i in decl.inputs.iter() {
2095 match (*i).pat.node {
2096 ast::PatIdent(_, _, _) => (),
2097 ast::PatWild(ast::PatWildSingle) => (),
2099 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
2100 "patterns aren't allowed in foreign function declarations");
2105 let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
2107 let rb = BindingRscope::new();
2108 let input_tys = decl.inputs
2110 .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
2113 let output = match decl.output {
2114 ast::Return(ref ty) =>
2115 ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
2116 ast::DefaultReturn(..) =>
2117 ty::FnConverging(ty::mk_nil(ccx.tcx)),
2118 ast::NoReturn(..) =>
2122 let t_fn = ty::mk_bare_fn(
2125 ccx.tcx.mk_bare_fn(ty::BareFnTy {
2127 unsafety: ast::Unsafety::Unsafe,
2128 sig: ty::Binder(ty::FnSig {inputs: input_tys,
2130 variadic: decl.variadic}),
2134 generics: ty_generics,
2139 fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
2140 ty_generics: &ty::Generics<'tcx>)
2144 ty_generics.types.map(
2145 |def| ty::mk_param_from_def(ccx.tcx, def));
2148 ty_generics.regions.map(
2149 |def| def.to_early_bound_region());
2151 Substs::new(types, regions)
2154 /// Verifies that the explicit self type of a method matches the impl
2155 /// or trait. This is a bit weird but basically because right now we
2156 /// don't handle the general case, but instead map it to one of
2157 /// several pre-defined options using various heuristics, this method
2158 /// comes back to check after the fact that explicit type the user
2159 /// wrote actually matches what the pre-defined option said.
2160 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2161 ccx: &CrateCtxt<'a, 'tcx>,
2163 method_type: Rc<ty::Method<'tcx>>,
2164 required_type: Ty<'tcx>,
2165 explicit_self: &ast::ExplicitSelf,
2166 body_id: ast::NodeId)
2169 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
2170 let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
2171 let base_type = match typ.sty {
2172 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
2173 ty::ty_uniq(typ) => typ,
2177 let body_scope = region::DestructionScopeData::new(body_id);
2179 // "Required type" comes from the trait definition. It may
2180 // contain late-bound regions from the method, but not the
2181 // trait (since traits only have early-bound region
2183 assert!(!base_type.has_regions_escaping_depth(1));
2184 let required_type_free =
2185 liberate_early_bound_regions(
2187 &ty::liberate_late_bound_regions(
2188 tcx, body_scope, &ty::Binder(required_type)));
2190 // The "base type" comes from the impl. It too may have late-bound
2191 // regions from the method.
2192 assert!(!base_type.has_regions_escaping_depth(1));
2193 let base_type_free =
2194 liberate_early_bound_regions(
2196 &ty::liberate_late_bound_regions(
2197 tcx, body_scope, &ty::Binder(base_type)));
2199 debug!("required_type={} required_type_free={} \
2200 base_type={} base_type_free={}",
2201 required_type.repr(tcx),
2202 required_type_free.repr(tcx),
2203 base_type.repr(tcx),
2204 base_type_free.repr(tcx));
2206 let infcx = infer::new_infer_ctxt(tcx);
2207 drop(::require_same_types(tcx,
2214 format!("mismatched self type: expected `{}`",
2215 ppaux::ty_to_string(tcx, required_type))
2218 // We could conceviably add more free-reion relations here,
2219 // but since this code is just concerned with checking that
2220 // the `&Self` types etc match up, it's not really necessary.
2221 // It would just allow people to be more approximate in some
2222 // cases. In any case, we can do it later as we feel the need;
2223 // I'd like this function to go away eventually.
2224 let free_regions = FreeRegionMap::new();
2226 infcx.resolve_regions_and_report_errors(&free_regions, body_id);
2229 fn liberate_early_bound_regions<'tcx,T>(
2230 tcx: &ty::ctxt<'tcx>,
2231 scope: region::DestructionScopeData,
2234 where T : TypeFoldable<'tcx> + Repr<'tcx>
2237 * Convert early-bound regions into free regions; normally this is done by
2238 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
2239 * method-self-type check is kind of hacky and done very early in the process,
2240 * before we really have a `ParameterEnvironment` to check.
2243 ty_fold::fold_regions(tcx, value, |region, _| {
2245 ty::ReEarlyBound(data) => {
2246 let def_id = local_def(data.param_id);
2247 ty::ReFree(ty::FreeRegion { scope: scope,
2248 bound_region: ty::BrNamed(def_id, data.name) })
2256 /// Checks that all the type parameters on an impl
2257 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2258 ast_generics: &ast::Generics,
2259 impl_def_id: ast::DefId,
2260 impl_items: &[P<ast::ImplItem>])
2262 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
2263 let impl_predicates = ty::lookup_predicates(tcx, impl_def_id);
2264 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
2266 // The trait reference is an input, so find all type parameters
2267 // reachable from there, to start (if this is an inherent impl,
2268 // then just examine the self type).
2269 let mut input_parameters: HashSet<_> =
2270 ctp::parameters_for_type(impl_scheme.ty).into_iter().collect();
2271 if let Some(ref trait_ref) = impl_trait_ref {
2272 input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref));
2275 ctp::identify_constrained_type_params(tcx,
2276 impl_predicates.predicates.as_slice(),
2278 &mut input_parameters);
2280 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
2281 let param_ty = ty::ParamTy { space: TypeSpace,
2283 name: ty_param.ident.name };
2284 if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
2285 report_unused_parameter(tcx, ty_param.span, "type", ¶m_ty.user_string(tcx));
2289 // Every lifetime used in an associated type must be constrained.
2291 let lifetimes_in_associated_types: HashSet<_> =
2293 .filter_map(|item| match item.node {
2294 ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
2295 ast::ConstImplItem(..) | ast::MethodImplItem(..) |
2296 ast::MacImplItem(..) => None,
2298 .flat_map(|ty| ctp::parameters_for_type(ty).into_iter())
2299 .filter_map(|p| match p {
2300 ctp::Parameter::Type(_) => None,
2301 ctp::Parameter::Region(r) => Some(r),
2305 for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
2306 let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
2308 index: index as u32,
2309 name: lifetime_def.lifetime.name };
2311 lifetimes_in_associated_types.contains(®ion) && // (*)
2312 !input_parameters.contains(&ctp::Parameter::Region(region))
2314 report_unused_parameter(tcx, lifetime_def.lifetime.span,
2315 "lifetime", ®ion.name.user_string(tcx));
2319 // (*) This is a horrible concession to reality. I think it'd be
2320 // better to just ban unconstrianed lifetimes outright, but in
2321 // practice people do non-hygenic macros like:
2324 // macro_rules! __impl_slice_eq1 {
2325 // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2326 // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2333 // In a concession to backwards compatbility, we continue to
2334 // permit those, so long as the lifetimes aren't used in
2335 // associated types. I believe this is sound, because lifetimes
2336 // used elsewhere are not projected back out.
2339 fn report_unused_parameter(tcx: &ty::ctxt,
2344 span_err!(tcx.sess, span, E0207,
2345 "the {} parameter `{}` is not constrained by the \
2346 impl trait, self type, or predicates",