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::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
36 use middle::ty::{ty_param_bounds_and_ty};
38 use middle::subst::Subst;
39 use middle::typeck::astconv::{AstConv, ty_of_arg};
40 use middle::typeck::astconv::{ast_ty_to_ty};
41 use middle::typeck::astconv;
42 use middle::typeck::rscope::*;
43 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
45 use util::ppaux::Repr;
49 use syntax::abi::AbiSet;
50 use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
53 use syntax::ast_util::{local_def, split_trait_methods};
54 use syntax::codemap::Span;
56 use syntax::parse::token::special_idents;
57 use syntax::parse::token;
58 use syntax::print::pprust::{path_to_str};
60 use syntax::opt_vec::OptVec;
62 struct CollectItemTypesVisitor {
66 impl visit::Visitor<()> for CollectItemTypesVisitor {
67 fn visit_item(&mut self, i: &ast::Item, _: ()) {
69 visit::walk_item(self, i, ());
71 fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
72 convert_foreign(self.ccx, i);
73 visit::walk_foreign_item(self, i, ());
77 pub fn collect_item_types(ccx: @CrateCtxt, krate: &ast::Crate) {
78 fn collect_intrinsic_type(ccx: &CrateCtxt,
79 lang_item: ast::DefId) {
80 let ty::ty_param_bounds_and_ty { ty: ty, .. } =
81 ccx.get_item_ty(lang_item);
82 let mut intrinsic_defs = ccx.tcx.intrinsic_defs.borrow_mut();
83 intrinsic_defs.get().insert(lang_item, ty);
86 match ccx.tcx.lang_items.ty_desc() {
87 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
89 match ccx.tcx.lang_items.opaque() {
90 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
93 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
94 visit::walk_crate(&mut visitor, krate, ());
98 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
101 impl ToTy for CrateCtxt {
102 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
103 ast_ty_to_ty(self, rs, ast_ty)
107 impl AstConv for CrateCtxt {
108 fn tcx(&self) -> ty::ctxt { self.tcx }
110 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
111 if id.krate != ast::LOCAL_CRATE {
112 return csearch::get_type(self.tcx, id)
115 match self.tcx.map.find(id.node) {
116 Some(ast_map::NodeItem(item)) => ty_of_item(self, item),
117 Some(ast_map::NodeForeignItem(foreign_item)) => {
118 let abis = self.tcx.map.get_foreign_abis(id.node);
119 ty_of_foreign_item(self, foreign_item, abis)
122 self.tcx.sess.bug(format!("unexpected sort of node \
123 in get_item_ty(): {:?}", x));
128 fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
129 get_trait_def(self, id)
132 fn ty_infer(&self, span: Span) -> ty::t {
133 self.tcx.sess.span_bug(span, "found `ty_infer` in unexpected place");
137 pub fn get_enum_variant_types(ccx: &CrateCtxt,
139 variants: &[ast::P<ast::Variant>],
140 generics: &ast::Generics) {
143 // Create a set of parameter types shared among all the variants.
144 for variant in variants.iter() {
145 // Nullary enum constructors get turned into constants; n-ary enum
146 // constructors get turned into functions.
147 let scope = variant.node.id;
148 let result_ty = match variant.node.kind {
149 ast::TupleVariantKind(ref args) if args.len() > 0 => {
150 let rs = ExplicitRscope;
151 let input_tys = args.map(|va| ccx.to_ty(&rs, va.ty));
152 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
155 ast::TupleVariantKind(_) => {
159 ast::StructVariantKind(struct_def) => {
160 let tpt = ty_param_bounds_and_ty {
161 generics: ty_generics(ccx, generics, 0),
165 convert_struct(ccx, struct_def, tpt, variant.node.id);
167 let input_tys = struct_def.fields.map(
168 |f| ty::node_id_to_type(ccx.tcx, f.node.id));
169 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
173 let tpt = ty_param_bounds_and_ty {
174 generics: ty_generics(ccx, generics, 0),
179 let mut tcache = tcx.tcache.borrow_mut();
180 tcache.get().insert(local_def(variant.node.id), tpt);
183 write_ty_to_tcx(tcx, variant.node.id, result_ty);
187 pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
189 match tcx.map.get(trait_id) {
190 ast_map::NodeItem(item) => {
192 ast::ItemTrait(ref generics, _, ref ms) => {
193 let trait_ty_generics = ty_generics(ccx, generics, 0);
195 // For each method, construct a suitable ty::Method and
196 // store it into the `tcx.methods` table:
198 let ty_method = @match m {
199 &ast::Required(ref m) => {
200 ty_method_of_trait_method(
201 ccx, trait_id, &trait_ty_generics,
202 &m.id, &m.ident, &m.explicit_self,
203 &m.generics, &m.purity, m.decl)
206 &ast::Provided(ref m) => {
207 ty_method_of_trait_method(
208 ccx, trait_id, &trait_ty_generics,
209 &m.id, &m.ident, &m.explicit_self,
210 &m.generics, &m.purity, m.decl)
214 if ty_method.explicit_self == ast::SelfStatic {
215 make_static_method_ty(ccx, trait_id, ty_method,
219 let mut methods = tcx.methods.borrow_mut();
220 methods.get().insert(ty_method.def_id, ty_method);
223 // Add an entry mapping
224 let method_def_ids = @ms.map(|m| {
226 &ast::Required(ref ty_method) => {
227 local_def(ty_method.id)
229 &ast::Provided(ref method) => {
235 let trait_def_id = local_def(trait_id);
236 let mut trait_method_def_ids = tcx.trait_method_def_ids
238 trait_method_def_ids.get()
239 .insert(trait_def_id,
240 @method_def_ids.iter()
244 _ => {} // Ignore things that aren't traits.
247 _ => { /* Ignore things that aren't traits */ }
250 fn make_static_method_ty(ccx: &CrateCtxt,
251 trait_id: ast::NodeId,
253 trait_ty_generics: &ty::Generics) {
256 // trait Trait<'a,'b,'c,a,b,c> {
257 // fn foo<'d,'e,'f,d,e,f>(...) -> Self;
260 // and we will create a function like
262 // fn foo<'a,'b,'c, // First the lifetime params from trait
263 // 'd,'e,'f, // Then lifetime params from `foo()`
264 // a,b,c, // Then type params from trait
265 // D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
266 // E,F,G // Then type params from `foo()`, offset by 1
269 // Note that `Self` is replaced with an explicit type
270 // parameter D that is sandwiched in between the trait params
271 // and the method params, and thus the indices of the method
272 // type parameters are offset by 1 (that is, the method
273 // parameters are mapped from d, e, f to E, F, and G). The
274 // choice of this ordering is somewhat arbitrary.
276 // Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
277 // This implies that the lifetime parameters that were inherited
278 // from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
279 // bound, since they appear in a trait bound.
281 // Also, this system is rather a hack that should be replaced
282 // with a more uniform treatment of Self (which is partly
285 // build up a subst that shifts all of the parameters over
286 // by one and substitute in a new type param for self
290 let dummy_defid = ast::DefId {krate: 0, node: 0};
292 // Represents [A',B',C']
293 let num_trait_bounds = trait_ty_generics.type_param_defs().len();
294 let non_shifted_trait_tps = vec::from_fn(num_trait_bounds, |i| {
295 ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
299 let self_param = ty::mk_param(tcx, num_trait_bounds,
302 // Represents [E',F',G']
303 let num_method_bounds = m.generics.type_param_defs().len();
304 let shifted_method_tps = vec::from_fn(num_method_bounds, |i| {
305 ty::mk_param(tcx, i + num_trait_bounds + 1,
306 m.generics.type_param_defs()[i].def_id)
309 // Convert the regions 'a, 'b, 'c defined on the trait into
310 // bound regions on the fn. Note that because these appear in the
311 // bound for `Self` they must be early bound.
312 let new_early_region_param_defs = trait_ty_generics.region_param_defs.clone();
314 trait_ty_generics.region_param_defs().iter().
316 map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.ident)).
319 // build up the substitution from
320 // 'a,'b,'c => 'a,'b,'c
324 let substs = substs {
325 regions: ty::NonerasedRegions(rps_from_trait),
326 self_ty: Some(self_param),
327 tps: non_shifted_trait_tps + shifted_method_tps
330 // create the type of `foo`, applying the substitution above
331 let ty = ty::subst(tcx,
333 ty::mk_bare_fn(tcx, m.fty.clone()));
335 // create the type parameter definitions for `foo`, applying
336 // the substitution to any traits that appear in their bounds.
338 // add in the type parameters from the trait
339 let mut new_type_param_defs = ~[];
340 let substd_type_param_defs =
341 trait_ty_generics.type_param_defs.subst(tcx, &substs);
342 new_type_param_defs.push_all(*substd_type_param_defs.borrow());
344 // add in the "self" type parameter
345 let self_trait_def = get_trait_def(ccx, local_def(trait_id));
346 let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
347 new_type_param_defs.push(ty::TypeParameterDef {
348 ident: special_idents::self_,
350 bounds: @ty::ParamBounds {
351 builtin_bounds: ty::EmptyBuiltinBounds(),
352 trait_bounds: ~[self_trait_ref]
357 // add in the type parameters from the method
358 let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
359 new_type_param_defs.push_all(*substd_type_param_defs.borrow());
361 debug!("static method {} type_param_defs={} ty={}, substs={}",
363 new_type_param_defs.repr(tcx),
367 let mut tcache = tcx.tcache.borrow_mut();
368 tcache.get().insert(m.def_id,
369 ty_param_bounds_and_ty {
370 generics: ty::Generics {
371 type_param_defs: Rc::new(new_type_param_defs),
372 region_param_defs: new_early_region_param_defs
378 fn ty_method_of_trait_method(this: &CrateCtxt,
379 trait_id: ast::NodeId,
380 trait_generics: &ty::Generics,
382 m_ident: &ast::Ident,
383 m_explicit_self: &ast::ExplicitSelf,
384 m_generics: &ast::Generics,
385 m_purity: &ast::Purity,
386 m_decl: &ast::FnDecl) -> ty::Method
388 let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
389 let fty = astconv::ty_of_method(this, *m_id, *m_purity, trait_self_ty,
390 *m_explicit_self, m_decl);
391 let num_trait_type_params = trait_generics.type_param_defs().len();
394 // FIXME(#5121) -- distinguish early vs late lifetime params
395 ty_generics(this, m_generics, num_trait_type_params),
397 m_explicit_self.node,
398 // assume public, because this is only invoked on trait methods
401 TraitContainer(local_def(trait_id)),
407 pub fn ensure_supertraits(ccx: &CrateCtxt,
410 ast_trait_refs: &[ast::TraitRef])
415 // Called only the first time trait_def_of_item is called.
416 // Supertraits are ensured at the same time.
418 let supertraits = tcx.supertraits.borrow();
419 assert!(!supertraits.get().contains_key(&local_def(id)));
422 let self_ty = ty::mk_self(ccx.tcx, local_def(id));
423 let mut ty_trait_refs: ~[@ty::TraitRef] = ~[];
424 let mut bounds = ty::EmptyBuiltinBounds();
425 for ast_trait_ref in ast_trait_refs.iter() {
426 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
427 // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
428 // builtin trait, so that the trait's node id appears in the tcx trait_ref
429 // map. This is only needed for metadata; see the similar fixme in encoder.rs.
430 let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
431 if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
433 // FIXME(#5527) Could have same trait multiple times
434 if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) {
435 // This means a trait inherited from the same supertrait more
437 tcx.sess.span_err(sp, "duplicate supertrait in trait declaration");
440 ty_trait_refs.push(trait_ref);
445 let mut supertraits = tcx.supertraits.borrow_mut();
446 supertraits.get().insert(local_def(id), @ty_trait_refs);
450 pub fn convert_field(ccx: &CrateCtxt,
451 struct_generics: &ty::Generics,
452 v: &ast::StructField) {
453 let tt = ccx.to_ty(&ExplicitRscope, v.node.ty);
454 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
455 /* add the field to the tcache */
456 let mut tcache = ccx.tcx.tcache.borrow_mut();
457 tcache.get().insert(local_def(v.node.id),
458 ty::ty_param_bounds_and_ty {
459 generics: struct_generics.clone(),
464 fn convert_methods(ccx: &CrateCtxt,
465 container: MethodContainer,
467 untransformed_rcvr_ty: ty::t,
468 rcvr_ty_generics: &ty::Generics,
469 rcvr_ast_generics: &ast::Generics,
470 rcvr_visibility: ast::Visibility)
474 let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
475 let m_ty_generics = ty_generics(ccx, &m.generics, num_rcvr_ty_params);
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),
488 let mut tcache = tcx.tcache.borrow_mut();
492 // n.b.: the type of a method is parameterized by both
493 // the parameters on the receiver and those on the method
495 ty_param_bounds_and_ty {
496 generics: ty::Generics {
497 type_param_defs: Rc::new(vec::append(
498 rcvr_ty_generics.type_param_defs().to_owned(),
499 m_ty_generics.type_param_defs())),
500 region_param_defs: rcvr_ty_generics.region_param_defs.clone(),
506 write_ty_to_tcx(tcx, m.id, fty);
508 let mut methods = tcx.methods.borrow_mut();
509 methods.get().insert(mty.def_id, mty);
512 fn ty_of_method(ccx: &CrateCtxt,
513 container: MethodContainer,
515 untransformed_rcvr_ty: ty::t,
516 rcvr_generics: &ast::Generics,
517 rcvr_visibility: ast::Visibility) -> ty::Method
519 let fty = astconv::ty_of_method(ccx, m.id, m.purity,
520 untransformed_rcvr_ty,
521 m.explicit_self, m.decl);
523 // if the method specifies a visibility, use that, otherwise
524 // inherit the visibility from the impl (so `foo` in `pub impl
525 // { fn foo(); }` is public, but private in `priv impl { fn
527 let method_vis = m.vis.inherit_from(rcvr_visibility);
529 let num_rcvr_type_params = rcvr_generics.ty_params.len();
532 // FIXME(#5121) -- distinguish early vs late lifetime params
533 ty_generics(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 i_ty_generics = ty_generics(ccx, generics, 0);
586 let selfty = ccx.to_ty(&ExplicitRscope, selfty);
587 write_ty_to_tcx(tcx, it.id, selfty);
590 let mut tcache = tcx.tcache.borrow_mut();
591 tcache.get().insert(local_def(it.id),
592 ty_param_bounds_and_ty {
593 generics: i_ty_generics.clone(),
597 // If there is a trait reference, treat the methods as always public.
598 // This is to work around some incorrect behavior in privacy checking:
599 // when the method belongs to a trait, it should acquire the privacy
600 // from the trait, not the impl. Forcing the visibility to be public
601 // makes things sorta work.
602 let parent_visibility = if opt_trait_ref.is_some() {
609 ImplContainer(local_def(it.id)),
616 for trait_ref in opt_trait_ref.iter() {
617 let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
619 // Prevent the builtin kind traits from being manually implemented.
620 if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
621 tcx.sess.span_err(it.span,
622 "cannot provide an explicit implementation \
623 for a builtin kind");
627 ast::ItemTrait(ref generics, _, ref trait_methods) => {
628 let trait_def = trait_def_of_item(ccx, it);
630 // Run convert_methods on the provided methods.
631 let (_, provided_methods) =
632 split_trait_methods(trait_methods.as_slice());
633 let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
635 TraitContainer(local_def(it.id)),
636 provided_methods.as_slice(),
637 untransformed_rcvr_ty,
642 // We need to do this *after* converting methods, since
643 // convert_methods produces a tcache entry that is wrong for
644 // static trait methods. This is somewhat unfortunate.
645 ensure_trait_methods(ccx, it.id);
647 ast::ItemStruct(struct_def, ref generics) => {
648 ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
650 // Write the class type
651 let tpt = ty_of_item(ccx, it);
652 write_ty_to_tcx(tcx, it.id, tpt.ty);
655 let mut tcache = tcx.tcache.borrow_mut();
656 tcache.get().insert(local_def(it.id), tpt.clone());
659 convert_struct(ccx, struct_def, tpt, it.id);
661 ast::ItemTy(_, ref generics) => {
662 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
663 let tpt = ty_of_item(ccx, it);
664 write_ty_to_tcx(tcx, it.id, tpt.ty);
666 ast::ItemFn(_, _, abi, ref generics, _) => {
667 ensure_generics_abi(ccx, it.span, abi, generics);
668 let tpt = ty_of_item(ccx, it);
669 write_ty_to_tcx(tcx, it.id, tpt.ty);
672 // This call populates the type cache with the converted type
673 // of the item in passing. All we have to do here is to write
674 // it into the node type table.
675 let tpt = ty_of_item(ccx, it);
676 write_ty_to_tcx(tcx, it.id, tpt.ty);
681 pub fn convert_struct(ccx: &CrateCtxt,
682 struct_def: &ast::StructDef,
683 tpt: ty::ty_param_bounds_and_ty,
687 // Write the type of each of the members
688 for f in struct_def.fields.iter() {
689 convert_field(ccx, &tpt.generics, f);
691 let substs = mk_item_substs(ccx, &tpt.generics, None);
692 let selfty = ty::mk_struct(tcx, local_def(id), substs);
694 // If this struct is enum-like or tuple-like, create the type of its
696 match struct_def.ctor_id {
699 if struct_def.fields.len() == 0 {
701 write_ty_to_tcx(tcx, ctor_id, selfty);
704 let mut tcache = tcx.tcache.borrow_mut();
705 tcache.get().insert(local_def(ctor_id), tpt);
707 } else if struct_def.fields.get(0).node.kind ==
711 let tcache = tcx.tcache.borrow();
712 struct_def.fields.map(
713 |field| tcache.get().get(
714 &local_def(field.node.id)).ty)
716 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
720 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
722 let mut tcache = tcx.tcache.borrow_mut();
723 tcache.get().insert(local_def(ctor_id),
724 ty_param_bounds_and_ty {
725 generics: tpt.generics,
734 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
735 // As above, this call populates the type table with the converted
736 // type of the foreign item. We simply write it into the node type
739 // For reasons I cannot fully articulate, I do so hate the AST
740 // map, and I regard each time that I use it as a personal and
741 // moral failing, but at the moment it seems like the only
742 // convenient way to extract the ABI. - ndm
743 let abis = ccx.tcx.map.get_foreign_abis(i.id);
745 let tpt = ty_of_foreign_item(ccx, i, abis);
746 write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
748 let mut tcache = ccx.tcx.tcache.borrow_mut();
749 tcache.get().insert(local_def(i.id), tpt);
752 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
753 ast_trait_ref: &ast::TraitRef,
754 self_ty: ty::t) -> @ty::TraitRef
757 * Instantiates the path for the given trait reference, assuming that
758 * it's bound to a valid trait type. Returns the def_id for the defining
759 * trait. Fails if the type is a type other than a trait type.
762 // FIXME(#5121) -- distinguish early vs late lifetime params
763 let rscope = ExplicitRscope;
765 match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
766 ast::DefTrait(trait_did) => {
768 astconv::ast_path_to_trait_ref(
769 ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
771 let mut trait_refs = ccx.tcx.trait_refs.borrow_mut();
772 trait_refs.get().insert(ast_trait_ref.ref_id, trait_ref);
776 ccx.tcx.sess.span_fatal(
777 ast_trait_ref.path.span,
778 format!("`{}` is not a trait",
779 path_to_str(&ast_trait_ref.path)));
784 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
785 if trait_id.krate != ast::LOCAL_CRATE {
786 return ty::lookup_trait_def(ccx.tcx, trait_id)
789 match ccx.tcx.map.get(trait_id.node) {
790 ast_map::NodeItem(item) => trait_def_of_item(ccx, item),
791 _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
796 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
797 let def_id = local_def(it.id);
800 let trait_defs = tcx.trait_defs.borrow();
801 match trait_defs.get().find(&def_id) {
802 Some(&def) => return def,
808 ast::ItemTrait(ref generics, ref supertraits, _) => {
809 let self_ty = ty::mk_self(tcx, def_id);
810 let ty_generics = ty_generics(ccx, generics, 0);
811 let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
812 let bounds = ensure_supertraits(ccx,
815 supertraits.as_slice());
816 let trait_ref = @ty::TraitRef {def_id: def_id,
818 let trait_def = @ty::TraitDef {generics: ty_generics,
820 trait_ref: trait_ref};
821 let mut trait_defs = tcx.trait_defs.borrow_mut();
822 trait_defs.get().insert(def_id, trait_def);
828 format!("trait_def_of_item invoked on {:?}", s));
833 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
834 -> ty::ty_param_bounds_and_ty {
835 let def_id = local_def(it.id);
838 let tcache = tcx.tcache.borrow();
839 match tcache.get().find(&def_id) {
840 Some(tpt) => return tpt.clone(),
845 ast::ItemStatic(t, _, _) => {
846 let typ = ccx.to_ty(&ExplicitRscope, t);
847 let tpt = no_params(typ);
849 let mut tcache = tcx.tcache.borrow_mut();
850 tcache.get().insert(local_def(it.id), tpt.clone());
853 ast::ItemFn(decl, purity, abi, ref generics, _) => {
854 let ty_generics = ty_generics(ccx, generics, 0);
855 let tofd = astconv::ty_of_bare_fn(ccx,
860 let tpt = ty_param_bounds_and_ty {
861 generics: ty::Generics {
862 type_param_defs: ty_generics.type_param_defs.clone(),
863 region_param_defs: Rc::new(~[]),
865 ty: ty::mk_bare_fn(ccx.tcx, tofd)
867 debug!("type of {} (id {}) is {}",
868 token::get_ident(it.ident),
870 ppaux::ty_to_str(tcx, tpt.ty));
872 let mut tcache = ccx.tcx.tcache.borrow_mut();
873 tcache.get().insert(local_def(it.id), tpt.clone());
876 ast::ItemTy(t, ref generics) => {
878 let mut tcache = tcx.tcache.borrow_mut();
879 match tcache.get().find(&local_def(it.id)) {
880 Some(tpt) => return tpt.clone(),
886 let ty = ccx.to_ty(&ExplicitRscope, t);
887 ty_param_bounds_and_ty {
888 generics: ty_generics(ccx, generics, 0),
893 let mut tcache = tcx.tcache.borrow_mut();
894 tcache.get().insert(local_def(it.id), tpt.clone());
897 ast::ItemEnum(_, ref generics) => {
898 // Create a new generic polytype.
899 let ty_generics = ty_generics(ccx, generics, 0);
900 let substs = mk_item_substs(ccx, &ty_generics, None);
901 let t = ty::mk_enum(tcx, local_def(it.id), substs);
902 let tpt = ty_param_bounds_and_ty {
903 generics: ty_generics,
907 let mut tcache = tcx.tcache.borrow_mut();
908 tcache.get().insert(local_def(it.id), tpt.clone());
911 ast::ItemTrait(..) => {
914 format!("invoked ty_of_item on trait"));
916 ast::ItemStruct(_, ref generics) => {
917 let ty_generics = ty_generics(ccx, generics, 0);
918 let substs = mk_item_substs(ccx, &ty_generics, None);
919 let t = ty::mk_struct(tcx, local_def(it.id), substs);
920 let tpt = ty_param_bounds_and_ty {
921 generics: ty_generics,
925 let mut tcache = tcx.tcache.borrow_mut();
926 tcache.get().insert(local_def(it.id), tpt.clone());
929 ast::ItemImpl(..) | ast::ItemMod(_) |
930 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
934 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
935 it: &ast::ForeignItem,
936 abis: AbiSet) -> ty::ty_param_bounds_and_ty
939 ast::ForeignItemFn(fn_decl, ref generics) => {
940 ty_of_foreign_fn_decl(ccx,
946 ast::ForeignItemStatic(t, _) => {
947 ty::ty_param_bounds_and_ty {
948 generics: ty::Generics {
949 type_param_defs: Rc::new(~[]),
950 region_param_defs: Rc::new(~[]),
952 ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
958 pub fn ty_generics(ccx: &CrateCtxt,
959 generics: &ast::Generics,
960 base_index: uint) -> ty::Generics {
961 return ty::Generics {
962 region_param_defs: Rc::new(generics.lifetimes.iter().map(|l| {
963 ty::RegionParameterDef { ident: l.ident,
964 def_id: local_def(l.id) }
966 type_param_defs: Rc::new(generics.ty_params.mapi_to_vec(|offset, param| {
967 let existing_def_opt = {
968 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
969 ty_param_defs.get().find(¶m.id).map(|def| *def)
971 match existing_def_opt {
974 let param_ty = ty::param_ty {idx: base_index + offset,
975 def_id: local_def(param.id)};
976 let bounds = @compute_bounds(ccx, param_ty, ¶m.bounds);
977 let default = param.default.map(|x| ast_ty_to_ty(ccx, &ExplicitRscope, x));
978 let def = ty::TypeParameterDef {
980 def_id: local_def(param.id),
984 debug!("def for param: {}", def.repr(ccx.tcx));
986 let mut ty_param_defs = ccx.tcx
989 ty_param_defs.get().insert(param.id, def);
993 }).move_iter().collect())
998 param_ty: ty::param_ty,
999 ast_bounds: &OptVec<ast::TyParamBound>) -> ty::ParamBounds
1002 * Translate the AST's notion of ty param bounds (which are an
1003 * enum consisting of a newtyped Ty or a region) to ty's
1004 * notion of ty param bounds, which can either be user-defined
1005 * traits, or one of the two built-in traits (formerly known
1006 * as kinds): Freeze and Send.
1009 let mut param_bounds = ty::ParamBounds {
1010 builtin_bounds: ty::EmptyBuiltinBounds(),
1013 for ast_bound in ast_bounds.iter() {
1015 TraitTyParamBound(ref b) => {
1016 let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
1017 let trait_ref = instantiate_trait_ref(ccx, b, ty);
1018 if !ty::try_add_builtin_trait(
1019 ccx.tcx, trait_ref.def_id,
1020 &mut param_bounds.builtin_bounds)
1022 // Must be a user-defined trait
1023 param_bounds.trait_bounds.push(trait_ref);
1027 RegionTyParamBound => {
1028 param_bounds.builtin_bounds.add(ty::BoundStatic);
1037 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1040 ast_generics: &ast::Generics,
1042 -> ty::ty_param_bounds_and_ty {
1044 for i in decl.inputs.iter() {
1045 match (*i).pat.node {
1046 ast::PatIdent(_, _, _) => (),
1048 _ => ccx.tcx.sess.span_err((*i).pat.span,
1049 "patterns aren't allowed in foreign function declarations")
1053 let ty_generics = ty_generics(ccx, ast_generics, 0);
1054 let rb = BindingRscope::new(def_id.node);
1055 let input_tys = decl.inputs
1057 .map(|a| ty_of_arg(ccx, &rb, a, None))
1060 let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
1062 let t_fn = ty::mk_bare_fn(
1066 purity: ast::UnsafeFn,
1067 sig: ty::FnSig {binder_id: def_id.node,
1070 variadic: decl.variadic}
1072 let tpt = ty_param_bounds_and_ty {
1073 generics: ty_generics,
1077 let mut tcache = ccx.tcx.tcache.borrow_mut();
1078 tcache.get().insert(def_id, tpt.clone());
1082 pub fn mk_item_substs(ccx: &CrateCtxt,
1083 ty_generics: &ty::Generics,
1084 self_ty: Option<ty::t>) -> ty::substs
1086 let params: ~[ty::t] =
1087 ty_generics.type_param_defs().iter().enumerate().map(
1088 |(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
1090 let regions: OptVec<ty::Region> =
1091 ty_generics.region_param_defs().iter().enumerate().map(
1092 |(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.ident)).collect();
1094 substs {regions: ty::NonerasedRegions(regions),