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 polytypes. In "layman's terms", this means
24 that they are generic types that may have type parameters (more
25 mathematically phrased, they are universally quantified over a set of
26 type parameters). Polytypes are represented by an instance of
27 `ty::ty_param_bounds_and_ty`. This combines the core type along with
28 a list of the bounds for each parameter. Type parameters themselves
29 are represented as `ty_param()` instances.
34 use metadata::csearch;
35 use middle::resolve_lifetime;
36 use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
37 use middle::ty::{ty_param_bounds_and_ty};
39 use middle::subst::Subst;
40 use middle::typeck::astconv::{AstConv, ty_of_arg};
41 use middle::typeck::astconv::{ast_ty_to_ty};
42 use middle::typeck::astconv;
43 use middle::typeck::rscope::*;
44 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
46 use util::ppaux::Repr;
50 use collections::HashSet;
52 use syntax::abi::AbiSet;
53 use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
56 use syntax::ast_util::{local_def, split_trait_methods};
57 use syntax::codemap::Span;
59 use syntax::parse::token::special_idents;
60 use syntax::parse::token;
61 use syntax::print::pprust::{path_to_str};
63 use syntax::owned_slice::OwnedSlice;
65 struct CollectItemTypesVisitor<'a> {
66 ccx: &'a CrateCtxt<'a>
69 impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
70 fn visit_item(&mut self, i: &ast::Item, _: ()) {
72 visit::walk_item(self, i, ());
74 fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
75 convert_foreign(self.ccx, i);
76 visit::walk_foreign_item(self, i, ());
80 pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
81 fn collect_intrinsic_type(ccx: &CrateCtxt,
82 lang_item: ast::DefId) {
83 let ty::ty_param_bounds_and_ty { ty: ty, .. } =
84 ccx.get_item_ty(lang_item);
85 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
88 match ccx.tcx.lang_items.ty_desc() {
89 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
91 match ccx.tcx.lang_items.opaque() {
92 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
95 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
96 visit::walk_crate(&mut visitor, krate, ());
100 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
103 impl<'a> ToTy for CrateCtxt<'a> {
104 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
105 ast_ty_to_ty(self, rs, ast_ty)
109 impl<'a> AstConv for CrateCtxt<'a> {
110 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
112 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
113 if id.krate != ast::LOCAL_CRATE {
114 return csearch::get_type(self.tcx, id)
117 match self.tcx.map.find(id.node) {
118 Some(ast_map::NodeItem(item)) => ty_of_item(self, item),
119 Some(ast_map::NodeForeignItem(foreign_item)) => {
120 let abis = self.tcx.map.get_foreign_abis(id.node);
121 ty_of_foreign_item(self, foreign_item, abis)
124 self.tcx.sess.bug(format!("unexpected sort of node \
125 in get_item_ty(): {:?}", x));
130 fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
131 get_trait_def(self, id)
134 fn ty_infer(&self, span: Span) -> ty::t {
135 self.tcx.sess.span_err(span, "the type placeholder `_` is not \
136 allowed within types on item signatures.");
141 pub fn get_enum_variant_types(ccx: &CrateCtxt,
143 variants: &[ast::P<ast::Variant>],
144 generics: &ast::Generics) {
147 // Create a set of parameter types shared among all the variants.
148 for variant in variants.iter() {
149 // Nullary enum constructors get turned into constants; n-ary enum
150 // constructors get turned into functions.
151 let scope = variant.node.id;
152 let result_ty = match variant.node.kind {
153 ast::TupleVariantKind(ref args) if args.len() > 0 => {
154 let rs = ExplicitRscope;
155 let input_tys = args.map(|va| ccx.to_ty(&rs, va.ty));
156 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
159 ast::TupleVariantKind(_) => {
163 ast::StructVariantKind(struct_def) => {
164 let tpt = ty_param_bounds_and_ty {
165 generics: ty_generics_for_type(ccx, generics),
169 convert_struct(ccx, struct_def, tpt, variant.node.id);
171 let input_tys = struct_def.fields.map(
172 |f| ty::node_id_to_type(ccx.tcx, f.node.id));
173 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
177 let tpt = ty_param_bounds_and_ty {
178 generics: ty_generics_for_type(ccx, generics),
182 tcx.tcache.borrow_mut().insert(local_def(variant.node.id), tpt);
184 write_ty_to_tcx(tcx, variant.node.id, result_ty);
188 pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
190 match tcx.map.get(trait_id) {
191 ast_map::NodeItem(item) => {
193 ast::ItemTrait(ref generics, _, ref ms) => {
194 let trait_ty_generics = ty_generics_for_type(ccx, generics);
196 // For each method, construct a suitable ty::Method and
197 // store it into the `tcx.methods` table:
199 let ty_method = @match m {
200 &ast::Required(ref m) => {
201 ty_method_of_trait_method(
202 ccx, trait_id, &trait_ty_generics,
203 &m.id, &m.ident, &m.explicit_self,
204 &m.generics, &m.purity, m.decl)
207 &ast::Provided(ref m) => {
208 ty_method_of_trait_method(
209 ccx, trait_id, &trait_ty_generics,
210 &m.id, &m.ident, &m.explicit_self,
211 &m.generics, &m.purity, m.decl)
215 if ty_method.explicit_self == ast::SelfStatic {
216 make_static_method_ty(ccx, trait_id, ty_method,
220 tcx.methods.borrow_mut().insert(ty_method.def_id,
224 // Add an entry mapping
225 let method_def_ids = @ms.map(|m| {
227 &ast::Required(ref ty_method) => {
228 local_def(ty_method.id)
230 &ast::Provided(ref method) => {
236 let trait_def_id = local_def(trait_id);
237 tcx.trait_method_def_ids.borrow_mut()
238 .insert(trait_def_id, @method_def_ids.iter()
242 _ => {} // Ignore things that aren't traits.
245 _ => { /* Ignore things that aren't traits */ }
248 fn make_static_method_ty(ccx: &CrateCtxt,
249 trait_id: ast::NodeId,
251 trait_ty_generics: &ty::Generics) {
254 // trait Trait<'a,'b,'c,a,b,c> {
255 // fn foo<'d,'e,'f,d,e,f>(...) -> Self;
258 // and we will create a function like
260 // fn foo<'a,'b,'c, // First the lifetime params from trait
261 // 'd,'e,'f, // Then lifetime params from `foo()`
262 // a,b,c, // Then type params from trait
263 // D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
264 // E,F,G // Then type params from `foo()`, offset by 1
267 // Note that `Self` is replaced with an explicit type
268 // parameter D that is sandwiched in between the trait params
269 // and the method params, and thus the indices of the method
270 // type parameters are offset by 1 (that is, the method
271 // parameters are mapped from d, e, f to E, F, and G). The
272 // choice of this ordering is somewhat arbitrary.
274 // Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
275 // This implies that the lifetime parameters that were inherited
276 // from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
277 // bound, since they appear in a trait bound.
279 // Also, this system is rather a hack that should be replaced
280 // with a more uniform treatment of Self (which is partly
283 // build up a subst that shifts all of the parameters over
284 // by one and substitute in a new type param for self
288 let dummy_defid = ast::DefId {krate: 0, node: 0};
290 // Represents [A',B',C']
291 let num_trait_bounds = trait_ty_generics.type_param_defs().len();
292 let non_shifted_trait_tps = Vec::from_fn(num_trait_bounds, |i| {
293 ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
297 let self_param = ty::mk_param(tcx, num_trait_bounds,
300 // Represents [E',F',G']
301 let num_method_bounds = m.generics.type_param_defs().len();
302 let shifted_method_tps = Vec::from_fn(num_method_bounds, |i| {
303 ty::mk_param(tcx, i + num_trait_bounds + 1,
304 m.generics.type_param_defs()[i].def_id)
307 // Convert the regions 'a, 'b, 'c defined on the trait into
308 // bound regions on the fn. Note that because these appear in the
309 // bound for `Self` they must be early bound.
310 let new_early_region_param_defs = trait_ty_generics.region_param_defs.clone();
312 trait_ty_generics.region_param_defs().iter().
314 map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.name)).
317 // build up the substitution from
318 // 'a,'b,'c => 'a,'b,'c
322 let substs = substs {
323 regions: ty::NonerasedRegions(rps_from_trait),
324 self_ty: Some(self_param),
325 tps: vec::append(non_shifted_trait_tps,
326 shifted_method_tps.as_slice())
329 // create the type of `foo`, applying the substitution above
330 let ty = ty::subst(tcx,
332 ty::mk_bare_fn(tcx, m.fty.clone()));
334 // create the type parameter definitions for `foo`, applying
335 // the substitution to any traits that appear in their bounds.
337 // add in the type parameters from the trait
338 let mut new_type_param_defs = Vec::new();
339 let substd_type_param_defs =
340 trait_ty_generics.type_param_defs.subst(tcx, &substs);
341 new_type_param_defs.push_all(substd_type_param_defs.as_slice());
343 // add in the "self" type parameter
344 let self_trait_def = get_trait_def(ccx, local_def(trait_id));
345 let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
346 new_type_param_defs.push(ty::TypeParameterDef {
347 ident: special_idents::self_,
349 bounds: @ty::ParamBounds {
350 builtin_bounds: ty::EmptyBuiltinBounds(),
351 trait_bounds: vec!(self_trait_ref)
356 // add in the type parameters from the method
357 let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
358 new_type_param_defs.push_all(substd_type_param_defs.as_slice());
360 debug!("static method {} type_param_defs={} ty={}, substs={}",
362 new_type_param_defs.repr(tcx),
366 tcx.tcache.borrow_mut().insert(m.def_id,
367 ty_param_bounds_and_ty {
368 generics: ty::Generics {
369 type_param_defs: Rc::new(new_type_param_defs),
370 region_param_defs: new_early_region_param_defs
376 fn ty_method_of_trait_method(this: &CrateCtxt,
377 trait_id: ast::NodeId,
378 trait_generics: &ty::Generics,
380 m_ident: &ast::Ident,
381 m_explicit_self: &ast::ExplicitSelf,
382 m_generics: &ast::Generics,
383 m_purity: &ast::Purity,
384 m_decl: &ast::FnDecl) -> ty::Method
386 let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
387 let fty = astconv::ty_of_method(this, *m_id, *m_purity, trait_self_ty,
388 *m_explicit_self, m_decl);
389 let num_trait_type_params = trait_generics.type_param_defs().len();
390 let ty_generics = ty_generics_for_fn_or_method(this, m_generics,
391 num_trait_type_params);
396 m_explicit_self.node,
397 // assume public, because this is only invoked on trait methods
400 TraitContainer(local_def(trait_id)),
406 pub fn ensure_supertraits(ccx: &CrateCtxt,
409 ast_trait_refs: &[ast::TraitRef])
414 // Called only the first time trait_def_of_item is called.
415 // Supertraits are ensured at the same time.
416 assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
418 let self_ty = ty::mk_self(ccx.tcx, local_def(id));
419 let mut ty_trait_refs: Vec<@ty::TraitRef> = Vec::new();
420 let mut bounds = ty::EmptyBuiltinBounds();
421 for ast_trait_ref in ast_trait_refs.iter() {
422 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
423 // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
424 // builtin trait, so that the trait's node id appears in the tcx trait_ref
425 // map. This is only needed for metadata; see the similar fixme in encoder.rs.
426 let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
427 if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
429 // FIXME(#5527) Could have same trait multiple times
430 if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) {
431 // This means a trait inherited from the same supertrait more
433 tcx.sess.span_err(sp, "duplicate supertrait in trait declaration");
436 ty_trait_refs.push(trait_ref);
441 tcx.supertraits.borrow_mut().insert(local_def(id), @ty_trait_refs);
445 pub fn convert_field(ccx: &CrateCtxt,
446 struct_generics: &ty::Generics,
447 v: &ast::StructField) {
448 let tt = ccx.to_ty(&ExplicitRscope, v.node.ty);
449 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
450 /* add the field to the tcache */
451 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
452 ty::ty_param_bounds_and_ty {
453 generics: struct_generics.clone(),
458 fn convert_methods(ccx: &CrateCtxt,
459 container: MethodContainer,
461 untransformed_rcvr_ty: ty::t,
462 rcvr_ty_generics: &ty::Generics,
463 rcvr_ast_generics: &ast::Generics,
464 rcvr_visibility: ast::Visibility)
467 let mut seen_methods = HashSet::new();
469 if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
470 tcx.sess.span_err(m.span, "duplicate method in trait impl");
473 let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
474 let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
476 let mty = @ty_of_method(ccx,
479 untransformed_rcvr_ty,
482 let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
483 debug!("method {} (id {}) has type {}",
484 m.ident.repr(ccx.tcx),
487 tcx.tcache.borrow_mut().insert(
490 // n.b.: the type of a method is parameterized by both
491 // the parameters on the receiver and those on the method
493 ty_param_bounds_and_ty {
494 generics: ty::Generics {
495 type_param_defs: Rc::new(vec::append(
497 rcvr_ty_generics.type_param_defs()),
498 m_ty_generics.type_param_defs())),
499 region_param_defs: Rc::new(vec::append(
500 Vec::from_slice(rcvr_ty_generics.region_param_defs()),
501 m_ty_generics.region_param_defs())),
506 write_ty_to_tcx(tcx, m.id, fty);
508 tcx.methods.borrow_mut().insert(mty.def_id, mty);
511 fn ty_of_method(ccx: &CrateCtxt,
512 container: MethodContainer,
514 untransformed_rcvr_ty: ty::t,
515 rcvr_generics: &ast::Generics,
516 rcvr_visibility: ast::Visibility) -> ty::Method
518 let fty = astconv::ty_of_method(ccx, m.id, m.purity,
519 untransformed_rcvr_ty,
520 m.explicit_self, m.decl);
522 // if the method specifies a visibility, use that, otherwise
523 // inherit the visibility from the impl (so `foo` in `pub impl
524 // { fn foo(); }` is public, but private in `priv impl { fn
526 let method_vis = m.vis.inherit_from(rcvr_visibility);
528 let num_rcvr_type_params = rcvr_generics.ty_params.len();
530 ty_generics_for_fn_or_method(ccx, &m.generics, num_rcvr_type_params);
535 m.explicit_self.node,
544 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
546 generics: &ast::Generics,
547 thing: &'static str) {
548 for ty_param in generics.ty_params.iter() {
549 if ty_param.bounds.len() > 0 {
550 ccx.tcx.sess.span_err(
552 format!("trait bounds are not allowed in {} definitions",
558 fn ensure_generics_abi(ccx: &CrateCtxt,
561 generics: &ast::Generics) {
562 if generics.ty_params.len() > 0 &&
563 !(abis.is_rust() || abis.is_intrinsic()) {
564 ccx.tcx.sess.span_err(span,
565 "foreign functions may not use type parameters");
569 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
571 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
573 // These don't define types.
574 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
575 ast::ItemEnum(ref enum_definition, ref generics) => {
576 ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
577 let tpt = ty_of_item(ccx, it);
578 write_ty_to_tcx(tcx, it.id, tpt.ty);
579 get_enum_variant_types(ccx,
581 enum_definition.variants.as_slice(),
584 ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
585 let ty_generics = ty_generics_for_type(ccx, generics);
586 let selfty = ccx.to_ty(&ExplicitRscope, selfty);
587 write_ty_to_tcx(tcx, it.id, selfty);
589 tcx.tcache.borrow_mut().insert(local_def(it.id),
590 ty_param_bounds_and_ty {
591 generics: ty_generics.clone(),
594 // If there is a trait reference, treat the methods as always public.
595 // This is to work around some incorrect behavior in privacy checking:
596 // when the method belongs to a trait, it should acquire the privacy
597 // from the trait, not the impl. Forcing the visibility to be public
598 // makes things sorta work.
599 let parent_visibility = if opt_trait_ref.is_some() {
606 ImplContainer(local_def(it.id)),
613 for trait_ref in opt_trait_ref.iter() {
614 let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
616 // Prevent the builtin kind traits from being manually implemented.
617 if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
618 tcx.sess.span_err(it.span,
619 "cannot provide an explicit implementation \
620 for a builtin kind");
624 ast::ItemTrait(ref generics, _, ref trait_methods) => {
625 let trait_def = trait_def_of_item(ccx, it);
627 // Run convert_methods on the provided methods.
628 let (_, provided_methods) =
629 split_trait_methods(trait_methods.as_slice());
630 let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
632 TraitContainer(local_def(it.id)),
633 provided_methods.as_slice(),
634 untransformed_rcvr_ty,
639 // We need to do this *after* converting methods, since
640 // convert_methods produces a tcache entry that is wrong for
641 // static trait methods. This is somewhat unfortunate.
642 ensure_trait_methods(ccx, it.id);
644 ast::ItemStruct(struct_def, ref generics) => {
645 ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
647 // Write the class type
648 let tpt = ty_of_item(ccx, it);
649 write_ty_to_tcx(tcx, it.id, tpt.ty);
651 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
653 convert_struct(ccx, struct_def, tpt, it.id);
655 ast::ItemTy(_, ref generics) => {
656 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
657 let tpt = ty_of_item(ccx, it);
658 write_ty_to_tcx(tcx, it.id, tpt.ty);
660 ast::ItemFn(_, _, abi, ref generics, _) => {
661 ensure_generics_abi(ccx, it.span, abi, generics);
662 let tpt = ty_of_item(ccx, it);
663 write_ty_to_tcx(tcx, it.id, tpt.ty);
666 // This call populates the type cache with the converted type
667 // of the item in passing. All we have to do here is to write
668 // it into the node type table.
669 let tpt = ty_of_item(ccx, it);
670 write_ty_to_tcx(tcx, it.id, tpt.ty);
675 pub fn convert_struct(ccx: &CrateCtxt,
676 struct_def: &ast::StructDef,
677 tpt: ty::ty_param_bounds_and_ty,
681 // Write the type of each of the members
682 for f in struct_def.fields.iter() {
683 convert_field(ccx, &tpt.generics, f);
685 let substs = mk_item_substs(ccx, &tpt.generics, None);
686 let selfty = ty::mk_struct(tcx, local_def(id), substs);
688 // If this struct is enum-like or tuple-like, create the type of its
690 match struct_def.ctor_id {
693 if struct_def.fields.len() == 0 {
695 write_ty_to_tcx(tcx, ctor_id, selfty);
697 tcx.tcache.borrow_mut().insert(local_def(ctor_id), tpt);
698 } else if struct_def.fields.get(0).node.kind ==
701 let inputs = struct_def.fields.map(
702 |field| tcx.tcache.borrow().get(
703 &local_def(field.node.id)).ty);
704 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
708 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
709 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
710 ty_param_bounds_and_ty {
711 generics: tpt.generics,
719 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
720 // As above, this call populates the type table with the converted
721 // type of the foreign item. We simply write it into the node type
724 // For reasons I cannot fully articulate, I do so hate the AST
725 // map, and I regard each time that I use it as a personal and
726 // moral failing, but at the moment it seems like the only
727 // convenient way to extract the ABI. - ndm
728 let abis = ccx.tcx.map.get_foreign_abis(i.id);
730 let tpt = ty_of_foreign_item(ccx, i, abis);
731 write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
733 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), tpt);
736 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
737 ast_trait_ref: &ast::TraitRef,
738 self_ty: ty::t) -> @ty::TraitRef
741 * Instantiates the path for the given trait reference, assuming that
742 * it's bound to a valid trait type. Returns the def_id for the defining
743 * trait. Fails if the type is a type other than a trait type.
746 // FIXME(#5121) -- distinguish early vs late lifetime params
747 let rscope = ExplicitRscope;
749 match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
750 ast::DefTrait(trait_did) => {
752 astconv::ast_path_to_trait_ref(
753 ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
755 ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
760 ccx.tcx.sess.span_fatal(
761 ast_trait_ref.path.span,
762 format!("`{}` is not a trait",
763 path_to_str(&ast_trait_ref.path)));
768 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
769 if trait_id.krate != ast::LOCAL_CRATE {
770 return ty::lookup_trait_def(ccx.tcx, trait_id)
773 match ccx.tcx.map.get(trait_id.node) {
774 ast_map::NodeItem(item) => trait_def_of_item(ccx, item),
775 _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
780 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
781 let def_id = local_def(it.id);
783 match tcx.trait_defs.borrow().find(&def_id) {
784 Some(&def) => return def,
789 ast::ItemTrait(ref generics, ref supertraits, _) => {
790 let self_ty = ty::mk_self(tcx, def_id);
791 let ty_generics = ty_generics_for_type(ccx, generics);
792 let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
793 let bounds = ensure_supertraits(ccx,
796 supertraits.as_slice());
797 let trait_ref = @ty::TraitRef {def_id: def_id,
799 let trait_def = @ty::TraitDef {generics: ty_generics,
801 trait_ref: trait_ref};
802 tcx.trait_defs.borrow_mut().insert(def_id, trait_def);
808 format!("trait_def_of_item invoked on {:?}", s));
813 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
814 -> ty::ty_param_bounds_and_ty {
815 let def_id = local_def(it.id);
817 match tcx.tcache.borrow().find(&def_id) {
818 Some(tpt) => return tpt.clone(),
822 ast::ItemStatic(t, _, _) => {
823 let typ = ccx.to_ty(&ExplicitRscope, t);
824 let tpt = no_params(typ);
826 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
829 ast::ItemFn(decl, purity, abi, ref generics, _) => {
830 let ty_generics = ty_generics_for_fn_or_method(ccx, generics, 0);
831 let tofd = astconv::ty_of_bare_fn(ccx,
836 let tpt = ty_param_bounds_and_ty {
837 generics: ty_generics,
838 ty: ty::mk_bare_fn(ccx.tcx, tofd)
840 debug!("type of {} (id {}) is {}",
841 token::get_ident(it.ident),
843 ppaux::ty_to_str(tcx, tpt.ty));
845 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
848 ast::ItemTy(t, ref generics) => {
849 match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
850 Some(tpt) => return tpt.clone(),
855 let ty = ccx.to_ty(&ExplicitRscope, t);
856 ty_param_bounds_and_ty {
857 generics: ty_generics_for_type(ccx, generics),
862 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
865 ast::ItemEnum(_, ref generics) => {
866 // Create a new generic polytype.
867 let ty_generics = ty_generics_for_type(ccx, generics);
868 let substs = mk_item_substs(ccx, &ty_generics, None);
869 let t = ty::mk_enum(tcx, local_def(it.id), substs);
870 let tpt = ty_param_bounds_and_ty {
871 generics: ty_generics,
875 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
878 ast::ItemTrait(..) => {
881 format!("invoked ty_of_item on trait"));
883 ast::ItemStruct(_, ref generics) => {
884 let ty_generics = ty_generics_for_type(ccx, generics);
885 let substs = mk_item_substs(ccx, &ty_generics, None);
886 let t = ty::mk_struct(tcx, local_def(it.id), substs);
887 let tpt = ty_param_bounds_and_ty {
888 generics: ty_generics,
892 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
895 ast::ItemImpl(..) | ast::ItemMod(_) |
896 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
900 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
901 it: &ast::ForeignItem,
902 abis: AbiSet) -> ty::ty_param_bounds_and_ty
905 ast::ForeignItemFn(fn_decl, ref generics) => {
906 ty_of_foreign_fn_decl(ccx,
912 ast::ForeignItemStatic(t, _) => {
913 ty::ty_param_bounds_and_ty {
914 generics: ty::Generics {
915 type_param_defs: Rc::new(Vec::new()),
916 region_param_defs: Rc::new(Vec::new()),
918 ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
924 pub fn ty_generics_for_type(ccx: &CrateCtxt,
925 generics: &ast::Generics)
927 ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
930 pub fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
931 generics: &ast::Generics,
934 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
935 ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
938 pub fn ty_generics(ccx: &CrateCtxt,
939 lifetimes: &Vec<ast::Lifetime>,
940 ty_params: &OwnedSlice<ast::TyParam>,
941 base_index: uint) -> ty::Generics {
942 return ty::Generics {
943 region_param_defs: Rc::new(lifetimes.iter().map(|l| {
944 ty::RegionParameterDef { name: l.name,
945 def_id: local_def(l.id) }
947 type_param_defs: Rc::new(ty_params.iter().enumerate().map(|(offset, param)| {
948 let existing_def_opt = {
949 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
950 ty_param_defs.find(¶m.id).map(|&def| def)
952 existing_def_opt.unwrap_or_else(|| {
953 let param_ty = ty::param_ty {idx: base_index + offset,
954 def_id: local_def(param.id)};
955 let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
956 let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
957 let def = ty::TypeParameterDef {
959 def_id: local_def(param.id),
963 debug!("def for param: {}", def.repr(ccx.tcx));
964 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def);
972 param_ty: ty::param_ty,
973 ast_bounds: &OwnedSlice<ast::TyParamBound>) -> ty::ParamBounds
976 * Translate the AST's notion of ty param bounds (which are an
977 * enum consisting of a newtyped Ty or a region) to ty's
978 * notion of ty param bounds, which can either be user-defined
979 * traits, or the built-in trait (formerly known as kind): Send.
982 let mut param_bounds = ty::ParamBounds {
983 builtin_bounds: ty::EmptyBuiltinBounds(),
984 trait_bounds: Vec::new()
986 for ast_bound in ast_bounds.iter() {
988 TraitTyParamBound(ref b) => {
989 let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
990 let trait_ref = instantiate_trait_ref(ccx, b, ty);
991 if !ty::try_add_builtin_trait(
992 ccx.tcx, trait_ref.def_id,
993 &mut param_bounds.builtin_bounds)
995 // Must be a user-defined trait
996 param_bounds.trait_bounds.push(trait_ref);
1000 RegionTyParamBound => {
1001 param_bounds.builtin_bounds.add(ty::BoundStatic);
1010 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1013 ast_generics: &ast::Generics,
1015 -> ty::ty_param_bounds_and_ty {
1017 for i in decl.inputs.iter() {
1018 match (*i).pat.node {
1019 ast::PatIdent(_, _, _) => (),
1021 _ => ccx.tcx.sess.span_err((*i).pat.span,
1022 "patterns aren't allowed in foreign function declarations")
1026 let ty_generics_for_fn_or_method =
1027 ty_generics_for_fn_or_method(ccx, ast_generics, 0);
1028 let rb = BindingRscope::new(def_id.node);
1029 let input_tys = decl.inputs
1031 .map(|a| ty_of_arg(ccx, &rb, a, None))
1034 let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
1036 let t_fn = ty::mk_bare_fn(
1040 purity: ast::UnsafeFn,
1041 sig: ty::FnSig {binder_id: def_id.node,
1044 variadic: decl.variadic}
1046 let tpt = ty_param_bounds_and_ty {
1047 generics: ty_generics_for_fn_or_method,
1051 ccx.tcx.tcache.borrow_mut().insert(def_id, tpt.clone());
1055 pub fn mk_item_substs(ccx: &CrateCtxt,
1056 ty_generics: &ty::Generics,
1057 self_ty: Option<ty::t>) -> ty::substs
1059 let params: Vec<ty::t> =
1060 ty_generics.type_param_defs().iter().enumerate().map(
1061 |(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
1063 let regions: OwnedSlice<ty::Region> =
1064 ty_generics.region_param_defs().iter().enumerate().map(
1065 |(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.name)).collect();
1067 substs {regions: ty::NonerasedRegions(regions),