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 are a
30 number of possible cycles that can arise.
32 Converting types can require:
34 1. `Foo<X>` where `Foo` is a type alias, or trait requires knowing:
35 - number of region / type parameters
36 - for type parameters, `T:'a` annotations to control defaults for object lifetimes
37 - defaults for type parameters (which are themselves types!)
38 2. `Foo<X>` where `Foo` is a type alias requires knowing what `Foo` expands to
39 3. Translating `SomeTrait` with no explicit lifetime bound requires knowing
40 - supertraits of `SomeTrait`
41 4. Translating `T::X` (vs `<T as Trait>::X`) requires knowing
43 - supertraits of those bounds
45 So as you can see, in general translating types requires knowing the
46 trait hierarchy. But this gets a bit tricky because translating the
47 trait hierarchy requires converting the types that appear in trait
48 references. One potential saving grace is that in general knowing the
49 trait hierarchy is only necessary for shorthands like `T::X` or
50 handling omitted lifetime bounds on object types. Therefore, if we are
51 lazy about expanding out the trait hierachy, users can sever cycles if
52 necessary. Lazy expansion is also needed for type aliases.
54 This system is not perfect yet. Currently, we "convert" types and
55 traits in three phases (note that conversion only affects the types of
56 items / enum variants / methods; it does not e.g. compute the types of
57 individual expressions):
63 Conversion itself is done by simply walking each of the items in turn
64 and invoking an appropriate function (e.g., `trait_def_of_item` or
65 `convert_item`). However, it is possible that while converting an
66 item, we may need to compute the *type scheme* or *trait definition*
67 for other items. This is a kind of shallow conversion that is
68 triggered on demand by calls to `AstConv::get_item_type_scheme` or
69 `AstConv::lookup_trait_def`. It is possible for cycles to result from
70 this (e.g., `type A = B; type B = A;`), in which case astconv
71 (currently) reports the error.
73 There are some shortcomings in this design:
75 - Cycles through trait definitions (e.g. supertraits) are not currently
76 detected by astconv. (#12511)
77 - Because the type scheme includes defaults, cycles through type
78 parameter defaults are illegal even if those defaults are never
79 employed. This is not necessarily a bug.
80 - The phasing of trait definitions before type definitions does not
81 seem to be necessary, sufficient, or particularly helpful, given that
82 processing a trait definition can trigger processing a type def and
83 vice versa. However, if I remove it, I get ICEs, so some more work is
84 needed in that area. -nmatsakis
88 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
90 use constrained_type_params::identify_constrained_type_params;
91 use middle::lang_items::SizedTraitLangItem;
93 use middle::resolve_lifetime;
95 use middle::subst::{Substs, SelfSpace, TypeSpace, VecPerParamSpace};
96 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
97 use middle::ty::{self, RegionEscape, Ty, TypeScheme};
98 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
101 use util::common::memoized;
102 use util::nodemap::{FnvHashMap, FnvHashSet};
104 use util::ppaux::{Repr,UserString};
107 use std::collections::HashSet;
113 use syntax::ast_util::{local_def, PostExpansionMethod};
114 use syntax::codemap::Span;
115 use syntax::parse::token::{special_idents};
116 use syntax::parse::token;
120 ///////////////////////////////////////////////////////////////////////////
123 pub fn collect_item_types(tcx: &ty::ctxt) {
124 let ccx = &CollectCtxt { tcx: tcx };
126 match ccx.tcx.lang_items.ty_desc() {
127 Some(id) => { collect_intrinsic_type(ccx, id); }
130 match ccx.tcx.lang_items.opaque() {
131 Some(id) => { collect_intrinsic_type(ccx, id); }
135 let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
136 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
138 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
139 visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
142 ///////////////////////////////////////////////////////////////////////////
144 struct CollectCtxt<'a,'tcx:'a> {
145 tcx: &'a ty::ctxt<'tcx>,
148 ///////////////////////////////////////////////////////////////////////////
149 // Zeroth phase: collect types of intrinsics
151 fn collect_intrinsic_type(ccx: &CollectCtxt,
152 lang_item: ast::DefId) {
153 let ty::TypeScheme { ty, .. } =
154 ccx.get_item_type_scheme(lang_item);
155 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
158 ///////////////////////////////////////////////////////////////////////////
159 // First phase: just collect *trait definitions* -- basically, the set
160 // of type parameters and supertraits. This is information we need to
161 // know later when parsing field defs.
163 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
164 ccx: &'a CollectCtxt<'a, 'tcx>
167 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
168 fn visit_item(&mut self, i: &ast::Item) {
170 ast::ItemTrait(..) => {
171 // computing the trait def also fills in the table
172 let _ = trait_def_of_item(self.ccx, i);
177 visit::walk_item(self, i);
181 ///////////////////////////////////////////////////////////////////////////
182 // Second phase: collection proper.
184 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
185 ccx: &'a CollectCtxt<'a, 'tcx>
188 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
189 fn visit_item(&mut self, i: &ast::Item) {
190 convert_item(self.ccx, i);
191 visit::walk_item(self, i);
193 fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
194 convert_foreign_item(self.ccx, i);
195 visit::walk_foreign_item(self, i);
199 ///////////////////////////////////////////////////////////////////////////
200 // Utility types and common code for the above passes.
202 pub trait ToTy<'tcx> {
203 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
206 impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
207 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
208 ast_ty_to_ty(self, rs, ast_ty)
212 impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
213 fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
215 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
216 if id.krate != ast::LOCAL_CRATE {
217 return ty::lookup_item_type(self.tcx, id);
220 match self.tcx.map.find(id.node) {
221 Some(ast_map::NodeItem(item)) => {
222 type_scheme_of_item(self, &*item)
224 Some(ast_map::NodeForeignItem(foreign_item)) => {
225 let abi = self.tcx.map.get_foreign_abi(id.node);
226 type_scheme_of_foreign_item(self, &*foreign_item, abi)
229 self.tcx.sess.bug(&format!("unexpected sort of node \
230 in get_item_type_scheme(): {:?}",
236 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
237 get_trait_def(self, id)
240 fn ty_infer(&self, span: Span) -> Ty<'tcx> {
241 span_err!(self.tcx().sess, span, E0121,
242 "the type placeholder `_` is not allowed within types on item signatures");
246 fn projected_ty(&self,
248 trait_ref: Rc<ty::TraitRef<'tcx>>,
249 item_name: ast::Name)
252 ty::mk_projection(self.tcx(), trait_ref, item_name)
256 fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
257 enum_scheme: ty::TypeScheme<'tcx>,
258 enum_predicates: ty::GenericPredicates<'tcx>,
259 variants: &[P<ast::Variant>]) {
262 // Create a set of parameter types shared among all the variants.
263 for variant in variants {
264 let variant_def_id = local_def(variant.node.id);
266 // Nullary enum constructors get turned into constants; n-ary enum
267 // constructors get turned into functions.
268 let result_ty = match variant.node.kind {
269 ast::TupleVariantKind(ref args) if args.len() > 0 => {
270 let rs = ExplicitRscope;
271 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
272 ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[..], enum_scheme.ty)
275 ast::TupleVariantKind(_) => {
279 ast::StructVariantKind(ref struct_def) => {
280 convert_struct(ccx, &**struct_def, enum_scheme.clone(),
281 enum_predicates.clone(), variant.node.id);
286 let variant_scheme = TypeScheme {
287 generics: enum_scheme.generics.clone(),
291 tcx.tcache.borrow_mut().insert(variant_def_id, variant_scheme.clone());
292 tcx.predicates.borrow_mut().insert(variant_def_id, enum_predicates.clone());
293 write_ty_to_tcx(tcx, variant.node.id, result_ty);
297 fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
298 trait_id: ast::NodeId,
299 trait_def: &ty::TraitDef<'tcx>,
300 trait_predicates: &ty::GenericPredicates<'tcx>) {
302 if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
303 if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
304 // For each method, construct a suitable ty::Method and
305 // store it into the `tcx.impl_or_trait_items` table:
306 for trait_item in trait_items {
308 ast::RequiredMethod(_) |
309 ast::ProvidedMethod(_) => {
310 let ty_method = Rc::new(match *trait_item {
311 ast::RequiredMethod(ref m) => {
312 ty_method_of_trait_method(
326 ast::ProvidedMethod(ref m) => {
327 ty_method_of_trait_method(
335 m.pe_explicit_self(),
341 ast::TypeTraitItem(ref at) => {
342 tcx.sess.span_bug(at.ty_param.span,
343 "there shouldn't be a type trait item here")
347 debug!("ty_method_of_trait_method yielded {} for method {} of trait {}",
348 ty_method.repr(ccx.tcx),
349 trait_item.repr(ccx.tcx),
350 local_def(trait_id).repr(ccx.tcx));
352 make_method_ty(ccx, &*ty_method);
354 tcx.impl_or_trait_items
356 .insert(ty_method.def_id, ty::MethodTraitItem(ty_method));
358 ast::TypeTraitItem(ref ast_associated_type) => {
359 let trait_did = local_def(trait_id);
360 let associated_type = ty::AssociatedType {
361 name: ast_associated_type.ty_param.ident.name,
363 def_id: local_def(ast_associated_type.ty_param.id),
364 container: TraitContainer(trait_did),
367 let trait_item = ty::TypeTraitItem(Rc::new(associated_type));
368 tcx.impl_or_trait_items
370 .insert(associated_type.def_id, trait_item);
375 // Add an entry mapping
376 let trait_item_def_ids =
377 Rc::new(trait_items.iter().map(|ti| {
379 ast::RequiredMethod(ref ty_method) => {
380 ty::MethodTraitItemId(local_def(ty_method.id))
382 ast::ProvidedMethod(ref method) => {
383 ty::MethodTraitItemId(local_def(method.id))
385 ast::TypeTraitItem(ref typedef) => {
386 ty::TypeTraitItemId(local_def(typedef.ty_param.id))
391 let trait_def_id = local_def(trait_id);
392 tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids);
396 fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
397 ccx.tcx.tcache.borrow_mut().insert(
400 generics: m.generics.clone(),
401 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone()))
403 ccx.tcx.predicates.borrow_mut().insert(
405 m.predicates.clone());
408 fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
409 trait_id: ast::NodeId,
410 trait_generics: &ty::Generics<'tcx>,
411 trait_bounds: &ty::GenericPredicates<'tcx>,
412 _trait_items: &[ast::TraitItem],
415 m_explicit_self: &ast::ExplicitSelf,
417 m_generics: &ast::Generics,
418 m_unsafety: &ast::Unsafety,
419 m_decl: &ast::FnDecl)
420 -> ty::Method<'tcx> {
422 ty_generics_for_fn_or_method(ccx,
424 trait_generics.clone());
427 ty_generic_bounds_for_fn_or_method(ccx,
430 trait_bounds.clone());
432 let (fty, explicit_self_category) = {
433 let trait_self_ty = ty::mk_self_type(ccx.tcx);
434 astconv::ty_of_method(ccx,
447 explicit_self_category,
448 // assume public, because this is only invoked on trait methods
451 TraitContainer(local_def(trait_id)),
457 fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
458 struct_generics: &ty::Generics<'tcx>,
459 struct_predicates: &ty::GenericPredicates<'tcx>,
460 v: &ast::StructField,
461 origin: ast::DefId) -> ty::field_ty {
462 let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
463 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
465 /* add the field to the tcache */
466 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
468 generics: struct_generics.clone(),
471 ccx.tcx.predicates.borrow_mut().insert(local_def(v.node.id),
472 struct_predicates.clone());
475 ast::NamedField(ident, visibility) => {
478 id: local_def(v.node.id),
483 ast::UnnamedField(visibility) => {
485 name: special_idents::unnamed_field.name,
486 id: local_def(v.node.id),
494 fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
495 trait_def: &ty::TraitDef<'tcx>,
496 associated_type: &ast::AssociatedType)
498 let associated_type = Rc::new(ty::AssociatedType {
499 name: associated_type.ty_param.ident.name,
501 def_id: local_def(associated_type.ty_param.id),
502 container: TraitContainer(trait_def.trait_ref.def_id),
507 .insert(associated_type.def_id,
508 ty::TypeTraitItem(associated_type));
511 fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
512 container: ImplOrTraitItemContainer,
514 untransformed_rcvr_ty: Ty<'tcx>,
515 rcvr_ty_generics: &ty::Generics<'tcx>,
516 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
517 rcvr_visibility: ast::Visibility)
518 where I: Iterator<Item=&'i ast::Method> {
519 debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
520 untransformed_rcvr_ty.repr(ccx.tcx),
521 rcvr_ty_generics.repr(ccx.tcx));
524 let mut seen_methods = FnvHashSet();
526 if !seen_methods.insert(m.pe_ident().repr(tcx)) {
527 span_err!(tcx.sess, m.span, E0201, "duplicate method in trait impl");
530 let m_def_id = local_def(m.id);
532 let mty = Rc::new(ty_of_method(ccx,
535 untransformed_rcvr_ty,
539 let fty = ty::mk_bare_fn(tcx, Some(m_def_id), tcx.mk_bare_fn(mty.fty.clone()));
540 debug!("method {} (id {}) has type {}",
541 m.pe_ident().repr(tcx),
544 tcx.tcache.borrow_mut().insert(
547 generics: mty.generics.clone(),
550 tcx.predicates.borrow_mut().insert(m_def_id, mty.predicates.clone());
552 write_ty_to_tcx(tcx, m.id, fty);
554 debug!("writing method type: def_id={:?} mty={}",
555 mty.def_id, mty.repr(ccx.tcx));
557 tcx.impl_or_trait_items
559 .insert(mty.def_id, ty::MethodTraitItem(mty));
562 fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
563 container: ImplOrTraitItemContainer,
565 untransformed_rcvr_ty: Ty<'tcx>,
566 rcvr_ty_generics: &ty::Generics<'tcx>,
567 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
568 rcvr_visibility: ast::Visibility)
569 -> ty::Method<'tcx> {
571 ty_generics_for_fn_or_method(ccx,
573 rcvr_ty_generics.clone());
576 ty_generic_bounds_for_fn_or_method(ccx,
579 rcvr_ty_predicates.clone());
581 let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
583 untransformed_rcvr_ty,
584 m.pe_explicit_self(),
588 // if the method specifies a visibility, use that, otherwise
589 // inherit the visibility from the impl (so `foo` in `pub impl
590 // { fn foo(); }` is public, but private in `priv impl { fn
592 let method_vis = m.pe_vis().inherit_from(rcvr_visibility);
594 ty::Method::new(m.pe_ident().name,
598 explicit_self_category,
606 fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
608 generics: &ast::Generics,
609 thing: &'static str) {
610 let mut warn = false;
612 for ty_param in &*generics.ty_params {
613 for bound in &*ty_param.bounds {
615 ast::TraitTyParamBound(..) => {
618 ast::RegionTyParamBound(..) => { }
624 // According to accepted RFC #XXX, we should
625 // eventually accept these, but it will not be
626 // part of this PR. Still, convert to warning to
627 // make bootstrapping easier.
628 span_warn!(ccx.tcx.sess, span, E0122,
629 "trait bounds are not (yet) enforced \
635 fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
637 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
639 // These don't define types.
640 ast::ItemExternCrate(_) | ast::ItemUse(_) |
641 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {
643 ast::ItemEnum(ref enum_definition, _) => {
644 let (scheme, predicates) = convert_typed_item(ccx, it);
645 write_ty_to_tcx(tcx, it.id, scheme.ty);
646 get_enum_variant_types(ccx,
649 &enum_definition.variants);
656 // Create generics from the generics specified in the impl head.
658 debug!("convert: ast_generics={:?}", generics);
659 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
660 let ty_predicates = ty_generic_bounds_for_type_or_impl(ccx, &ty_generics, generics);
662 debug!("convert: impl_bounds={:?}", ty_predicates);
664 let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
665 write_ty_to_tcx(tcx, it.id, selfty);
667 tcx.tcache.borrow_mut().insert(local_def(it.id),
668 TypeScheme { generics: ty_generics.clone(),
670 tcx.predicates.borrow_mut().insert(local_def(it.id),
671 ty_predicates.clone());
673 // If there is a trait reference, treat the methods as always public.
674 // This is to work around some incorrect behavior in privacy checking:
675 // when the method belongs to a trait, it should acquire the privacy
676 // from the trait, not the impl. Forcing the visibility to be public
677 // makes things sorta work.
678 let parent_visibility = if opt_trait_ref.is_some() {
684 let mut methods = Vec::new();
685 for impl_item in impl_items {
687 ast::MethodImplItem(ref method) => {
688 let body_id = method.pe_body().id;
689 check_method_self_type(ccx,
690 &BindingRscope::new(),
692 method.pe_explicit_self(),
694 methods.push(&**method);
696 ast::TypeImplItem(ref typedef) => {
697 if opt_trait_ref.is_none() {
698 span_err!(tcx.sess, typedef.span, E0202,
699 "associated items are not allowed in inherent impls");
702 let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
703 tcx.tcache.borrow_mut().insert(local_def(typedef.id),
705 generics: ty::Generics::empty(),
708 tcx.predicates.borrow_mut().insert(local_def(typedef.id),
709 ty::GenericPredicates::empty());
710 write_ty_to_tcx(tcx, typedef.id, typ);
712 let associated_type = Rc::new(ty::AssociatedType {
713 name: typedef.ident.name,
715 def_id: local_def(typedef.id),
716 container: ty::ImplContainer(local_def(it.id)),
718 tcx.impl_or_trait_items
720 .insert(local_def(typedef.id),
721 ty::TypeTraitItem(associated_type));
727 ImplContainer(local_def(it.id)),
734 if let Some(ref trait_ref) = *opt_trait_ref {
735 astconv::instantiate_trait_ref(ccx,
742 enforce_impl_ty_params_are_constrained(tcx,
746 ast::ItemTrait(_, _, _, ref trait_methods) => {
747 let trait_def = trait_def_of_item(ccx, it);
748 convert_trait_predicates(ccx, it);
749 let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(it.id));
751 debug!("convert: trait_bounds={:?}", trait_predicates);
753 for trait_method in trait_methods {
754 let self_type = ty::mk_self_type(tcx);
755 match *trait_method {
756 ast::RequiredMethod(ref type_method) => {
757 let rscope = BindingRscope::new();
758 check_method_self_type(ccx,
761 &type_method.explicit_self,
764 ast::ProvidedMethod(ref method) => {
765 check_method_self_type(ccx,
766 &BindingRscope::new(),
768 method.pe_explicit_self(),
771 ast::TypeTraitItem(ref associated_type) => {
772 convert_associated_type(ccx,
779 // Run convert_methods on the provided methods.
780 let untransformed_rcvr_ty = ty::mk_self_type(tcx);
782 TraitContainer(local_def(it.id)),
783 trait_methods.iter().filter_map(|m| match *m {
784 ast::RequiredMethod(_) => None,
785 ast::ProvidedMethod(ref m) => Some(&**m),
786 ast::TypeTraitItem(_) => None,
788 untransformed_rcvr_ty,
793 // We need to do this *after* converting methods, since
794 // convert_methods produces a tcache entry that is wrong for
795 // static trait methods. This is somewhat unfortunate.
796 collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates);
798 ast::ItemStruct(ref struct_def, _) => {
799 // Write the class type.
800 let (scheme, predicates) = convert_typed_item(ccx, it);
801 write_ty_to_tcx(tcx, it.id, scheme.ty);
802 convert_struct(ccx, &**struct_def, scheme, predicates, it.id);
804 ast::ItemTy(_, ref generics) => {
805 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
806 let (scheme, _) = convert_typed_item(ccx, it);
807 write_ty_to_tcx(tcx, it.id, scheme.ty);
810 // This call populates the type cache with the converted type
811 // of the item in passing. All we have to do here is to write
812 // it into the node type table.
813 let (scheme, _) = convert_typed_item(ccx, it);
814 write_ty_to_tcx(tcx, it.id, scheme.ty);
819 fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
820 struct_def: &ast::StructDef,
821 scheme: ty::TypeScheme<'tcx>,
822 predicates: ty::GenericPredicates<'tcx>,
826 // Write the type of each of the members and check for duplicate fields.
827 let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
828 let field_tys = struct_def.fields.iter().map(|f| {
829 let result = convert_field(ccx, &scheme.generics, &predicates, f, local_def(id));
831 if result.name != special_idents::unnamed_field.name {
832 let dup = match seen_fields.get(&result.name) {
834 span_err!(tcx.sess, f.span, E0124,
835 "field `{}` is already declared",
836 token::get_name(result.name));
837 span_note!(tcx.sess, *prev_span, "previously declared here");
842 // FIXME(#6393) this whole dup thing is just to satisfy
843 // the borrow checker :-(
845 seen_fields.insert(result.name, f.span);
852 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
854 let substs = mk_item_substs(ccx, &scheme.generics);
855 let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
857 // If this struct is enum-like or tuple-like, create the type of its
859 match struct_def.ctor_id {
862 if struct_def.fields.len() == 0 {
864 write_ty_to_tcx(tcx, ctor_id, selfty);
866 tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
867 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
868 } else if struct_def.fields[0].node.kind.is_unnamed() {
870 let inputs: Vec<_> = struct_def.fields.iter().map(
871 |field| (*tcx.tcache.borrow())[
872 local_def(field.node.id)].ty).collect();
873 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
877 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
878 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
880 generics: scheme.generics,
883 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
889 fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
890 trait_id: ast::DefId)
891 -> Rc<ty::TraitDef<'tcx>> {
894 if trait_id.krate != ast::LOCAL_CRATE {
895 return ty::lookup_trait_def(tcx, trait_id)
898 match tcx.map.get(trait_id.node) {
899 ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
901 tcx.sess.bug(&format!("get_trait_def({}): not an item",
907 fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
909 -> Rc<ty::TraitDef<'tcx>>
911 let def_id = local_def(it.id);
914 if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
918 let (unsafety, generics, bounds, items) = match it.node {
919 ast::ItemTrait(unsafety,
923 (unsafety, generics, supertraits, items)
928 &format!("trait_def_of_item invoked on {:?}", s)[]);
932 let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
933 if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
934 ccx.tcx.sess.span_err(
936 "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
937 which traits can use parenthetical notation");
938 span_help!(ccx.tcx.sess, it.span,
939 "add `#![feature(unboxed_closures)]` to \
940 the crate attributes to use it");
943 let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
945 let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
947 let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx);
950 let bounds = compute_bounds(ccx,
956 let associated_type_names: Vec<_> =
960 ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
961 ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
966 let trait_ref = Rc::new(ty::TraitRef {
971 let trait_def = Rc::new(ty::TraitDef {
972 paren_sugar: paren_sugar,
974 generics: ty_generics,
976 trait_ref: trait_ref,
977 associated_type_names: associated_type_names,
980 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
984 fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
985 generics: &ast::Generics)
986 -> subst::Substs<'tcx>
990 // Creates a no-op substitution for the trait's type parameters.
995 .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
1001 // Start with the generics in the type parameters...
1006 .map(|(i, def)| ty::mk_param(tcx, subst::TypeSpace,
1007 i as u32, def.ident.name))
1010 // ...and also create the `Self` parameter.
1011 let self_ty = ty::mk_self_type(tcx);
1013 subst::Substs::new_trait(types, regions, self_ty)
1017 fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item) {
1019 let trait_def = trait_def_of_item(ccx, it);
1021 let def_id = local_def(it.id);
1023 let (generics, items) = match it.node {
1024 ast::ItemTrait(_, ref generics, _, ref items) => (generics, items),
1028 &format!("trait_def_of_item invoked on {:?}", s)[]);
1032 let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx);
1034 let super_predicates = ty::predicates(ccx.tcx, self_param_ty, &trait_def.bounds);
1036 let assoc_predicates = predicates_for_associated_types(ccx, &trait_def.trait_ref, items);
1038 // `ty_generic_bounds` below will consider the bounds on the type
1039 // parameters (including `Self`) and the explicit where-clauses,
1040 // but to get the full set of predicates on a trait we need to add
1041 // in the supertrait bounds and anything declared on the
1042 // associated types.
1043 let mut base_predicates =
1044 ty::GenericPredicates {
1045 predicates: VecPerParamSpace::new(super_predicates, vec![], vec![])
1047 base_predicates.predicates.extend(subst::TypeSpace, assoc_predicates.into_iter());
1049 let self_bounds = &trait_def.generics.types.get_self().unwrap().bounds;
1050 base_predicates.predicates.extend(
1052 ty::predicates(ccx.tcx, self_param_ty, self_bounds).into_iter());
1054 // add in the explicit where-clauses
1055 let trait_predicates =
1056 ty_generic_bounds(ccx,
1058 &trait_def.generics,
1060 &generics.where_clause);
1062 let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
1063 assert!(prev_predicates.is_none());
1067 fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1068 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
1069 trait_items: &[ast::TraitItem])
1070 -> Vec<ty::Predicate<'tcx>>
1074 .flat_map(|trait_item| {
1075 let assoc_type_def = match *trait_item {
1076 ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
1077 ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
1078 return vec!().into_iter();
1082 let assoc_ty = ty::mk_projection(ccx.tcx,
1083 self_trait_ref.clone(),
1084 assoc_type_def.ident.name);
1086 let bounds = compute_bounds(ccx,
1088 &*assoc_type_def.bounds,
1089 SizedByDefault::Yes,
1090 assoc_type_def.span);
1092 ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
1098 fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1100 -> ty::TypeScheme<'tcx>
1102 memoized(&ccx.tcx.tcache,
1104 |_| compute_type_scheme_of_item(ccx, it))
1108 fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1110 -> ty::TypeScheme<'tcx>
1114 ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
1115 let ty = ccx.to_ty(&ExplicitRscope, &**t);
1116 ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
1118 ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
1119 let ty_generics = ty_generics_for_fn_or_method(ccx,
1121 ty::Generics::empty());
1122 let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
1123 let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
1124 ty::TypeScheme { ty: ty, generics: ty_generics }
1126 ast::ItemTy(ref t, ref generics) => {
1127 let ty = ccx.to_ty(&ExplicitRscope, &**t);
1128 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1129 ty::TypeScheme { ty: ty, generics: ty_generics }
1131 ast::ItemEnum(_, ref generics) => {
1132 // Create a new generic polytype.
1133 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1134 let substs = mk_item_substs(ccx, &ty_generics);
1135 let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
1136 ty::TypeScheme { ty: t, generics: ty_generics }
1138 ast::ItemStruct(_, ref generics) => {
1139 let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
1140 let substs = mk_item_substs(ccx, &ty_generics);
1141 let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
1142 ty::TypeScheme { ty: t, generics: ty_generics }
1144 ast::ItemTrait(..) |
1147 ast::ItemForeignMod(..) |
1148 ast::ItemExternCrate(..) |
1150 ast::ItemMac(..) => {
1153 format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1154 it.node).as_slice());
1159 fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1161 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
1165 let tag = type_scheme_of_item(ccx, it);
1166 let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
1167 let predicates = match it.node {
1168 ast::ItemStatic(..) | ast::ItemConst(..) => {
1169 ty::GenericPredicates::empty()
1171 ast::ItemFn(_, _, _, ref ast_generics, _) => {
1172 ty_generic_bounds_for_fn_or_method(ccx,
1175 ty::GenericPredicates::empty())
1177 ast::ItemTy(_, ref generics) => {
1178 ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
1180 ast::ItemEnum(_, ref generics) => {
1181 ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
1183 ast::ItemStruct(_, ref generics) => {
1184 ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
1186 ast::ItemTrait(..) |
1187 ast::ItemExternCrate(..) |
1191 ast::ItemForeignMod(..) |
1192 ast::ItemMac(..) => {
1195 format!("compute_type_scheme_of_item: unexpected item type: {:?}",
1196 it.node).as_slice());
1200 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id),
1201 predicates.clone());
1202 assert!(prev_predicates.is_none());
1205 if ty::has_attr(tcx, local_def(it.id), "rustc_object_lifetime_default") {
1206 let object_lifetime_default_reprs: String =
1207 scheme.generics.types.iter()
1208 .map(|t| match t.object_lifetime_default {
1209 Some(ty::ObjectLifetimeDefault::Specific(r)) =>
1214 .collect::<Vec<String>>()
1217 tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
1220 return (scheme, predicates);
1223 fn type_scheme_of_foreign_item<'a, 'tcx>(
1224 ccx: &CollectCtxt<'a, 'tcx>,
1225 it: &ast::ForeignItem,
1227 -> ty::TypeScheme<'tcx>
1229 memoized(&ccx.tcx().tcache,
1231 |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
1234 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
1235 ccx: &CollectCtxt<'a, 'tcx>,
1236 it: &ast::ForeignItem,
1238 -> ty::TypeScheme<'tcx>
1241 ast::ForeignItemFn(ref fn_decl, ref generics) => {
1242 compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
1244 ast::ForeignItemStatic(ref t, _) => {
1246 generics: ty::Generics::empty(),
1247 ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
1253 fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1254 it: &ast::ForeignItem)
1256 // For reasons I cannot fully articulate, I do so hate the AST
1257 // map, and I regard each time that I use it as a personal and
1258 // moral failing, but at the moment it seems like the only
1259 // convenient way to extract the ABI. - ndm
1261 let abi = tcx.map.get_foreign_abi(it.id);
1263 let scheme = type_scheme_of_foreign_item(ccx, it, abi);
1264 write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
1266 let predicates = match it.node {
1267 ast::ForeignItemFn(_, ref generics) => {
1268 ty_generic_bounds_for_fn_or_method(ccx,
1271 ty::GenericPredicates::empty())
1273 ast::ForeignItemStatic(..) => {
1274 ty::GenericPredicates::empty()
1278 let prev_predicates = tcx.predicates.borrow_mut().insert(local_def(it.id), predicates);
1279 assert!(prev_predicates.is_none());
1282 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1283 generics: &ast::Generics)
1284 -> ty::Generics<'tcx> {
1287 &generics.lifetimes[],
1288 &generics.ty_params[],
1289 &generics.where_clause,
1290 ty::Generics::empty())
1293 fn ty_generic_bounds_for_type_or_impl<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1294 ty_generics: &ty::Generics<'tcx>,
1295 generics: &ast::Generics)
1296 -> ty::GenericPredicates<'tcx>
1298 ty_generic_bounds(ccx,
1301 ty::GenericPredicates::empty(),
1302 &generics.where_clause)
1305 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1306 trait_id: ast::NodeId,
1307 substs: &'tcx subst::Substs<'tcx>,
1308 ast_generics: &ast::Generics)
1309 -> ty::Generics<'tcx>
1311 debug!("ty_generics_for_trait(trait_id={}, substs={})",
1312 local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
1317 &ast_generics.lifetimes[],
1318 &ast_generics.ty_params[],
1319 &ast_generics.where_clause,
1320 ty::Generics::empty());
1322 // Add in the self type parameter.
1324 // Something of a hack: use the node id for the trait, also as
1325 // the node id for the Self type parameter.
1326 let param_id = trait_id;
1328 let self_trait_ref =
1329 Rc::new(ty::TraitRef { def_id: local_def(trait_id),
1332 let def = ty::TypeParameterDef {
1333 space: subst::SelfSpace,
1335 name: special_idents::type_self.name,
1336 def_id: local_def(param_id),
1337 bounds: ty::ParamBounds {
1338 region_bounds: vec!(),
1339 builtin_bounds: ty::empty_builtin_bounds(),
1340 trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
1341 projection_bounds: vec!(),
1344 object_lifetime_default: None,
1347 ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
1349 generics.types.push(subst::SelfSpace, def);
1354 fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1355 generics: &ast::Generics,
1356 base_generics: ty::Generics<'tcx>)
1357 -> ty::Generics<'tcx>
1359 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1362 &early_lifetimes[..],
1363 &generics.ty_params[],
1364 &generics.where_clause,
1368 fn ty_generic_bounds_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1369 generics: &ast::Generics,
1370 ty_generics: &ty::Generics<'tcx>,
1371 base: ty::GenericPredicates<'tcx>)
1372 -> ty::GenericPredicates<'tcx>
1374 ty_generic_bounds(ccx,
1378 &generics.where_clause)
1381 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
1382 fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1383 bounds: &mut ty::BuiltinBounds,
1384 ast_bounds: &[ast::TyParamBound],
1387 // Try to find an unbound in bounds.
1388 let mut unbound = None;
1389 for ab in ast_bounds {
1390 if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
1391 if unbound.is_none() {
1392 assert!(ptr.bound_lifetimes.is_empty());
1393 unbound = Some(ptr.trait_ref.clone());
1395 span_err!(ccx.tcx.sess, span, E0203,
1396 "type parameter has more than one relaxed default \
1397 bound, only one is supported");
1402 let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
1405 // FIXME(#8559) currently requires the unbound to be built-in.
1406 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
1408 Ok(kind_id) if trait_def_id != kind_id => {
1409 ccx.tcx.sess.span_warn(span,
1410 "default bound relaxed for a type parameter, but \
1411 this does nothing because the given bound is not \
1412 a default. Only `?Sized` is supported");
1413 ty::try_add_builtin_trait(ccx.tcx,
1420 _ if kind_id.is_ok() => {
1421 ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
1423 // No lang item for Sized, so we can't add it as a bound.
1428 fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1429 space: subst::ParamSpace,
1430 generics: &ty::Generics<'tcx>,
1431 base: ty::GenericPredicates<'tcx>,
1432 where_clause: &ast::WhereClause)
1433 -> ty::GenericPredicates<'tcx>
1436 let mut result = base;
1438 // For now, scrape the bounds out of parameters from Generics. This is not great.
1439 for def in generics.regions.get_slice(space) {
1440 let r_a = def.to_early_bound_region();
1441 for &r_b in &def.bounds {
1442 let outlives = ty::Binder(ty::OutlivesPredicate(r_a, r_b));
1443 result.predicates.push(def.space, ty::Predicate::RegionOutlives(outlives));
1446 for def in generics.types.get_slice(space) {
1447 let t = ty::mk_param_from_def(ccx.tcx, def);
1448 result.predicates.extend(def.space, ty::predicates(ccx.tcx, t, &def.bounds).into_iter());
1451 // Add the bounds not associated with a type parameter
1452 for predicate in &where_clause.predicates {
1454 &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
1455 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
1457 for bound in &*bound_pred.bounds {
1459 &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
1460 let mut projections = Vec::new();
1462 let trait_ref = astconv::instantiate_poly_trait_ref(
1470 result.predicates.push(space, trait_ref.as_predicate());
1472 for projection in &projections {
1473 result.predicates.push(space, projection.as_predicate());
1477 &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
1478 let region = ast_region_to_region(tcx, lifetime);
1479 let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
1480 result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
1486 &ast::WherePredicate::RegionPredicate(ref region_pred) => {
1487 let r1 = ast_region_to_region(tcx, ®ion_pred.lifetime);
1488 for bound in ®ion_pred.bounds {
1489 let r2 = ast_region_to_region(tcx, bound);
1490 let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1491 result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1495 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
1497 tcx.sess.span_bug(eq_pred.span,
1498 "Equality constraints are not yet \
1499 implemented (#20041)")
1507 fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1508 space: subst::ParamSpace,
1509 lifetime_defs: &[ast::LifetimeDef],
1510 types: &[ast::TyParam],
1511 where_clause: &ast::WhereClause,
1512 base_generics: ty::Generics<'tcx>)
1513 -> ty::Generics<'tcx>
1516 let mut result = base_generics;
1518 for (i, l) in lifetime_defs.iter().enumerate() {
1519 let bounds = l.bounds.iter()
1520 .map(|l| ast_region_to_region(tcx, l))
1522 let def = ty::RegionParameterDef { name: l.lifetime.name,
1525 def_id: local_def(l.lifetime.id),
1527 // debug!("ty_generics: def for region param: {:?}",
1529 result.regions.push(space, def);
1532 assert!(result.types.is_empty_in(space));
1534 // Now create the real type parameters.
1535 for (i, param) in types.iter().enumerate() {
1536 let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause);
1537 debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
1538 result.types.push(space, def);
1544 fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1545 space: subst::ParamSpace,
1546 param: &ast::TyParam,
1548 where_clause: &ast::WhereClause)
1549 -> ty::TypeParameterDef<'tcx>
1552 match tcx.ty_param_defs.borrow().get(¶m.id) {
1553 Some(d) => { return d.clone(); }
1557 let param_ty = ty::ParamTy::new(space, index, param.ident.name);
1558 let bounds = compute_bounds(ccx,
1559 param_ty.to_ty(ccx.tcx),
1561 SizedByDefault::Yes,
1563 let default = match param.default {
1566 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
1567 let cur_idx = index;
1569 ty::walk_ty(ty, |t| {
1571 ty::ty_param(p) => if p.idx > cur_idx {
1572 span_err!(tcx.sess, path.span, E0128,
1573 "type parameters with a default cannot use \
1574 forward declared identifiers");
1584 let object_lifetime_default =
1585 compute_object_lifetime_default(ccx, space, index, ¶m.bounds, where_clause);
1587 let def = ty::TypeParameterDef {
1590 name: param.ident.name,
1591 def_id: local_def(param.id),
1594 object_lifetime_default: object_lifetime_default,
1597 tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1602 /// Scan the bounds and where-clauses on a parameter to extract bounds
1603 /// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`.
1604 /// This runs as part of computing the minimal type scheme, so we
1605 /// intentionally avoid just asking astconv to convert all the where
1606 /// clauses into a `ty::Predicate`. This is because that could induce
1607 /// artificial cycles.
1608 fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1609 space: subst::ParamSpace,
1611 param_bounds: &[ast::TyParamBound],
1612 where_clause: &ast::WhereClause)
1613 -> Option<ty::ObjectLifetimeDefault>
1615 let inline_bounds = from_bounds(ccx, param_bounds);
1616 let where_bounds = from_predicates(ccx, space, index, &where_clause.predicates);
1617 let all_bounds: HashSet<_> = inline_bounds.into_iter()
1618 .chain(where_bounds.into_iter())
1620 return if all_bounds.len() > 1 {
1621 Some(ty::ObjectLifetimeDefault::Ambiguous)
1623 all_bounds.into_iter()
1625 .map(ty::ObjectLifetimeDefault::Specific)
1628 fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1629 bounds: &[ast::TyParamBound])
1633 .filter_map(|bound| {
1635 ast::TraitTyParamBound(..) =>
1637 ast::RegionTyParamBound(ref lifetime) =>
1638 Some(astconv::ast_region_to_region(ccx.tcx(), lifetime)),
1644 fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1645 space: subst::ParamSpace,
1647 predicates: &[ast::WherePredicate])
1651 .flat_map(|predicate| {
1653 ast::WherePredicate::BoundPredicate(ref data) => {
1654 if data.bound_lifetimes.len() == 0 &&
1655 is_param(ccx, &data.bounded_ty, space, index)
1657 from_bounds(ccx, &data.bounds).into_iter()
1659 Vec::new().into_iter()
1662 ast::WherePredicate::RegionPredicate(..) |
1663 ast::WherePredicate::EqPredicate(..) => {
1664 Vec::new().into_iter()
1671 fn is_param(ccx: &CollectCtxt,
1673 space: subst::ParamSpace,
1678 ast::TyPath(_, id) => {
1679 match ccx.tcx.def_map.borrow()[id] {
1680 def::DefTyParam(s, i, _, _) => {
1681 space == s && index == i
1695 enum SizedByDefault { Yes, No }
1697 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
1698 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
1699 /// built-in trait (formerly known as kind): Send.
1700 fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1701 param_ty: ty::Ty<'tcx>,
1702 ast_bounds: &[ast::TyParamBound],
1703 sized_by_default: SizedByDefault,
1705 -> ty::ParamBounds<'tcx>
1707 let mut param_bounds = conv_param_bounds(ccx,
1712 if let SizedByDefault::Yes = sized_by_default {
1713 add_unsized_bound(ccx,
1714 &mut param_bounds.builtin_bounds,
1718 check_bounds_compatible(ccx,
1724 param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
1729 fn check_bounds_compatible<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1731 param_bounds: &ty::ParamBounds<'tcx>,
1733 if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
1734 ty::each_bound_trait_and_supertraits(
1736 ¶m_bounds.trait_bounds[],
1738 let trait_def = ccx.get_trait_def(trait_ref.def_id());
1739 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
1740 span_err!(ccx.tcx.sess, span, E0129,
1741 "incompatible bounds on `{}`, \
1742 bound `{}` does not allow unsized type",
1743 param_ty.user_string(ccx.tcx),
1744 trait_ref.user_string(ccx.tcx));
1751 fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
1753 param_ty: ty::Ty<'tcx>,
1754 ast_bounds: &[ast::TyParamBound])
1755 -> ty::ParamBounds<'tcx>
1758 let astconv::PartitionedBounds {
1762 } = astconv::partition_bounds(tcx, span, ast_bounds.as_slice());
1764 let mut projection_bounds = Vec::new();
1766 let trait_bounds: Vec<ty::PolyTraitRef> =
1767 trait_bounds.into_iter()
1769 astconv::instantiate_poly_trait_ref(ccx,
1773 &mut projection_bounds)
1777 let region_bounds: Vec<ty::Region> =
1778 region_bounds.into_iter()
1779 .map(|r| ast_region_to_region(ccx.tcx, r))
1783 region_bounds: region_bounds,
1784 builtin_bounds: builtin_bounds,
1785 trait_bounds: trait_bounds,
1786 projection_bounds: projection_bounds,
1790 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
1791 ccx: &CollectCtxt<'a, 'tcx>,
1793 ast_generics: &ast::Generics,
1795 -> ty::TypeScheme<'tcx>
1797 for i in decl.inputs.iter() {
1798 match (*i).pat.node {
1799 ast::PatIdent(_, _, _) => (),
1800 ast::PatWild(ast::PatWildSingle) => (),
1802 span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
1803 "patterns aren't allowed in foreign function declarations");
1808 let ty_generics = ty_generics_for_fn_or_method(ccx, ast_generics, ty::Generics::empty());
1810 let rb = BindingRscope::new();
1811 let input_tys = decl.inputs
1813 .map(|a| ty_of_arg(ccx, &rb, a, None))
1816 let output = match decl.output {
1817 ast::Return(ref ty) =>
1818 ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
1819 ast::DefaultReturn(..) =>
1820 ty::FnConverging(ty::mk_nil(ccx.tcx)),
1821 ast::NoReturn(..) =>
1825 let t_fn = ty::mk_bare_fn(
1828 ccx.tcx.mk_bare_fn(ty::BareFnTy {
1830 unsafety: ast::Unsafety::Unsafe,
1831 sig: ty::Binder(ty::FnSig {inputs: input_tys,
1833 variadic: decl.variadic}),
1837 generics: ty_generics,
1842 fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
1843 ty_generics: &ty::Generics<'tcx>)
1844 -> subst::Substs<'tcx>
1847 ty_generics.types.map(
1848 |def| ty::mk_param_from_def(ccx.tcx, def));
1851 ty_generics.regions.map(
1852 |def| def.to_early_bound_region());
1854 subst::Substs::new(types, regions)
1857 /// Verifies that the explicit self type of a method matches the impl
1858 /// or trait. This is a bit weird but basically because right now we
1859 /// don't handle the general case, but instead map it to one of
1860 /// several pre-defined options using various heuristics, this method
1861 /// comes back to check after the fact that explicit type the user
1862 /// wrote actually matches what the pre-defined option said.
1863 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
1864 ccx: &CollectCtxt<'a, 'tcx>,
1866 required_type: Ty<'tcx>,
1867 explicit_self: &ast::ExplicitSelf,
1868 body_id: ast::NodeId)
1871 if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
1872 let typ = ccx.to_ty(rs, &**ast_type);
1873 let base_type = match typ.sty {
1874 ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
1875 ty::ty_uniq(typ) => typ,
1879 let body_scope = region::DestructionScopeData::new(body_id);
1881 // "Required type" comes from the trait definition. It may
1882 // contain late-bound regions from the method, but not the
1883 // trait (since traits only have early-bound region
1885 assert!(!base_type.has_regions_escaping_depth(1));
1886 let required_type_free =
1887 liberate_early_bound_regions(
1889 &ty::liberate_late_bound_regions(
1890 tcx, body_scope, &ty::Binder(required_type)));
1892 // The "base type" comes from the impl. It too may have late-bound
1893 // regions from the method.
1894 assert!(!base_type.has_regions_escaping_depth(1));
1895 let base_type_free =
1896 liberate_early_bound_regions(
1898 &ty::liberate_late_bound_regions(
1899 tcx, body_scope, &ty::Binder(base_type)));
1901 debug!("required_type={} required_type_free={} \
1902 base_type={} base_type_free={}",
1903 required_type.repr(tcx),
1904 required_type_free.repr(tcx),
1905 base_type.repr(tcx),
1906 base_type_free.repr(tcx));
1908 let infcx = infer::new_infer_ctxt(tcx);
1909 drop(::require_same_types(tcx,
1916 format!("mismatched self type: expected `{}`",
1917 ppaux::ty_to_string(tcx, required_type))
1919 infcx.resolve_regions_and_report_errors(body_id);
1922 fn liberate_early_bound_regions<'tcx,T>(
1923 tcx: &ty::ctxt<'tcx>,
1924 scope: region::DestructionScopeData,
1927 where T : TypeFoldable<'tcx> + Repr<'tcx>
1930 * Convert early-bound regions into free regions; normally this is done by
1931 * applying the `free_substs` from the `ParameterEnvironment`, but this particular
1932 * method-self-type check is kind of hacky and done very early in the process,
1933 * before we really have a `ParameterEnvironment` to check.
1936 ty_fold::fold_regions(tcx, value, |region, _| {
1938 ty::ReEarlyBound(id, _, _, name) => {
1939 let def_id = local_def(id);
1940 ty::ReFree(ty::FreeRegion { scope: scope,
1941 bound_region: ty::BrNamed(def_id, name) })
1949 /// Checks that all the type parameters on an impl
1950 fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
1951 ast_generics: &ast::Generics,
1952 impl_def_id: ast::DefId)
1954 let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
1955 let impl_predicates = ty::lookup_predicates(tcx, impl_def_id);
1956 let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
1958 // The trait reference is an input, so find all type parameters
1959 // reachable from there, to start (if this is an inherent impl,
1960 // then just examine the self type).
1961 let mut input_parameters: HashSet<_> =
1962 impl_trait_ref.iter()
1963 .flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
1964 .chain(Some(impl_scheme.ty).iter()) // Self type, always
1965 .flat_map(|t| t.walk())
1966 .filter_map(|t| t.as_opt_param_ty())
1969 identify_constrained_type_params(tcx,
1970 impl_predicates.predicates.as_slice(),
1972 &mut input_parameters);
1974 for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
1975 let param_ty = ty::ParamTy { space: TypeSpace,
1977 name: ty_param.ident.name };
1978 if !input_parameters.contains(¶m_ty) {
1979 if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
1982 &format!("the type parameter `{}` is not constrained by the \
1983 impl trait, self type, or predicates",
1984 param_ty.user_string(tcx)));
1986 span_err!(tcx.sess, ty_param.span, E0207,
1987 "the type parameter `{}` is not constrained by the \
1988 impl trait, self type, or predicates",
1989 param_ty.user_string(tcx));