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.
4 //
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.
10
11 /*
12
13 # Collect phase
14
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.
21
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.
30
31 */
32
33
34 use metadata::csearch;
35 use middle::lang_items::SizedTraitLangItem;
36 use middle::resolve_lifetime;
37 use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
38 use middle::ty::{ty_param_bounds_and_ty};
39 use middle::ty;
40 use middle::subst::Subst;
41 use middle::typeck::astconv::{AstConv, ty_of_arg};
42 use middle::typeck::astconv::{ast_ty_to_ty};
43 use middle::typeck::astconv;
44 use middle::typeck::rscope::*;
45 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
46 use util::ppaux;
47 use util::ppaux::Repr;
48
49 use std::rc::Rc;
50 use collections::{HashMap, HashSet};
51
52 use syntax::abi;
53 use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound,
54 TraitTyParamBound};
55 use syntax::ast;
56 use syntax::ast_map;
57 use syntax::ast_util::{local_def, split_trait_methods};
58 use syntax::codemap::Span;
59 use syntax::codemap;
60 use syntax::parse::token::special_idents;
61 use syntax::parse::token;
62 use syntax::print::pprust::{path_to_str};
63 use syntax::visit;
64 use syntax::owned_slice::OwnedSlice;
65
66 struct CollectItemTypesVisitor<'a> {
67 ccx: &'a CrateCtxt<'a>
68 }
69
70 impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
71 fn visit_item(&mut self, i: &ast::Item, _: ()) {
72 convert(self.ccx, i);
73 visit::walk_item(self, i, ());
74 }
75 fn visit_foreign_item(&mut self, i: &ast::ForeignItem, _: ()) {
76 convert_foreign(self.ccx, i);
77 visit::walk_foreign_item(self, i, ());
78 }
79 }
80
81 pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
82 fn collect_intrinsic_type(ccx: &CrateCtxt,
83 lang_item: ast::DefId) {
84 let ty::ty_param_bounds_and_ty { ty: ty, .. } =
85 ccx.get_item_ty(lang_item);
86 ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
87 }
88
89 match ccx.tcx.lang_items.ty_desc() {
90 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
91 }
92 match ccx.tcx.lang_items.opaque() {
93 Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
94 }
95
96 let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
97 visit::walk_crate(&mut visitor, krate, ());
98 }
99
100 pub trait ToTy {
101 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
102 }
103
104 impl<'a> ToTy for CrateCtxt<'a> {
105 fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
106 ast_ty_to_ty(self, rs, ast_ty)
107 }
108 }
109
110 impl<'a> AstConv for CrateCtxt<'a> {
111 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
112
113 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
114 if id.krate != ast::LOCAL_CRATE {
115 return csearch::get_type(self.tcx, id)
116 }
117
118 match self.tcx.map.find(id.node) {
119 Some(ast_map::NodeItem(item)) => ty_of_item(self, item),
120 Some(ast_map::NodeForeignItem(foreign_item)) => {
121 let abi = self.tcx.map.get_foreign_abi(id.node);
122 ty_of_foreign_item(self, foreign_item, abi)
123 }
124 x => {
125 self.tcx.sess.bug(format!("unexpected sort of node \
126 in get_item_ty(): {:?}", x));
127 }
128 }
129 }
130
131 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
132 get_trait_def(self, id)
133 }
134
135 fn ty_infer(&self, span: Span) -> ty::t {
136 self.tcx.sess.span_err(span, "the type placeholder `_` is not \
137 allowed within types on item signatures.");
138 ty::mk_err()
139 }
140 }
141
142 pub fn get_enum_variant_types(ccx: &CrateCtxt,
143 enum_ty: ty::t,
144 variants: &[ast::P<ast::Variant>],
145 generics: &ast::Generics) {
146 let tcx = ccx.tcx;
147
148 // Create a set of parameter types shared among all the variants.
149 for variant in variants.iter() {
150 // Nullary enum constructors get turned into constants; n-ary enum
151 // constructors get turned into functions.
152 let scope = variant.node.id;
153 let result_ty = match variant.node.kind {
154 ast::TupleVariantKind(ref args) if args.len() > 0 => {
155 let rs = ExplicitRscope;
156 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, va.ty)).collect();
157 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
158 }
159
160 ast::TupleVariantKind(_) => {
161 enum_ty
162 }
163
164 ast::StructVariantKind(struct_def) => {
165 let tpt = ty_param_bounds_and_ty {
166 generics: ty_generics_for_type(ccx, generics),
167 ty: enum_ty
168 };
169
170 convert_struct(ccx, struct_def, tpt, variant.node.id);
171
172 let input_tys: Vec<_> = struct_def.fields.iter().map(
173 |f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
174 ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
175 }
176 };
177
178 let tpt = ty_param_bounds_and_ty {
179 generics: ty_generics_for_type(ccx, generics),
180 ty: result_ty
181 };
182
183 tcx.tcache.borrow_mut().insert(local_def(variant.node.id), tpt);
184
185 write_ty_to_tcx(tcx, variant.node.id, result_ty);
186 }
187 }
188
189 pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
190 let tcx = ccx.tcx;
191 match tcx.map.get(trait_id) {
192 ast_map::NodeItem(item) => {
193 match item.node {
194 ast::ItemTrait(ref generics, _, _, ref ms) => {
195 let trait_ty_generics = ty_generics_for_type(ccx, generics);
196
197 // For each method, construct a suitable ty::Method and
198 // store it into the `tcx.methods` table:
199 for m in ms.iter() {
200 let ty_method = Rc::new(match m {
201 &ast::Required(ref m) => {
202 ty_method_of_trait_method(
203 ccx, trait_id, &trait_ty_generics,
204 &m.id, &m.ident, &m.explicit_self,
205 &m.generics, &m.fn_style, m.decl)
206 }
207
208 &ast::Provided(ref m) => {
209 ty_method_of_trait_method(
210 ccx, trait_id, &trait_ty_generics,
211 &m.id, &m.ident, &m.explicit_self,
212 &m.generics, &m.fn_style, m.decl)
213 }
214 });
215
216 if ty_method.explicit_self == ast::SelfStatic {
217 make_static_method_ty(ccx, trait_id, &*ty_method,
218 &trait_ty_generics);
219 }
220
221 tcx.methods.borrow_mut().insert(ty_method.def_id,
222 ty_method);
223 }
224
225 // Add an entry mapping
226 let method_def_ids = Rc::new(ms.iter().map(|m| {
227 match m {
228 &ast::Required(ref ty_method) => {
229 local_def(ty_method.id)
230 }
231 &ast::Provided(ref method) => {
232 local_def(method.id)
233 }
234 }
235 }).collect());
236
237 let trait_def_id = local_def(trait_id);
238 tcx.trait_method_def_ids.borrow_mut()
239 .insert(trait_def_id, method_def_ids);
240 }
241 _ => {} // Ignore things that aren't traits.
242 }
243 }
244 _ => { /* Ignore things that aren't traits */ }
245 }
246
247 fn make_static_method_ty(ccx: &CrateCtxt,
248 trait_id: ast::NodeId,
249 m: &ty::Method,
250 trait_ty_generics: &ty::Generics) {
251 // If declaration is
252 //
253 // trait Trait<'a,'b,'c,a,b,c> {
254 // fn foo<'d,'e,'f,d,e,f>(...) -> Self;
255 // }
256 //
257 // and we will create a function like
258 //
259 // fn foo<'a,'b,'c, // First the lifetime params from trait
260 // 'd,'e,'f, // Then lifetime params from `foo()`
261 // a,b,c, // Then type params from trait
262 // D:Trait<'a,'b,'c,a,b,c>, // Then this sucker
263 // E,F,G // Then type params from `foo()`, offset by 1
264 // >(...) -> D' {}
265 //
266 // Note that `Self` is replaced with an explicit type
267 // parameter D that is sandwiched in between the trait params
268 // and the method params, and thus the indices of the method
269 // type parameters are offset by 1 (that is, the method
270 // parameters are mapped from d, e, f to E, F, and G). The
271 // choice of this ordering is somewhat arbitrary.
272 //
273 // Note also that the bound for `D` is `Trait<'a,'b,'c,a,b,c>`.
274 // This implies that the lifetime parameters that were inherited
275 // from the trait (i.e., `'a`, `'b`, and `'c`) all must be early
276 // bound, since they appear in a trait bound.
277 //
278 // Also, this system is rather a hack that should be replaced
279 // with a more uniform treatment of Self (which is partly
280 // underway).
281
282 // build up a subst that shifts all of the parameters over
283 // by one and substitute in a new type param for self
284
285 let tcx = ccx.tcx;
286
287 let dummy_defid = ast::DefId {krate: 0, node: 0};
288
289 // Represents [A',B',C']
290 let num_trait_bounds = trait_ty_generics.type_param_defs().len();
291 let non_shifted_trait_tps = Vec::from_fn(num_trait_bounds, |i| {
292 ty::mk_param(tcx, i, trait_ty_generics.type_param_defs()[i].def_id)
293 });
294
295 // Represents [D']
296 let self_param = ty::mk_param(tcx, num_trait_bounds,
297 dummy_defid);
298
299 // Represents [E',F',G']
300 let num_method_bounds = m.generics.type_param_defs().len();
301 let shifted_method_tps = Vec::from_fn(num_method_bounds, |i| {
302 ty::mk_param(tcx, i + num_trait_bounds + 1,
303 m.generics.type_param_defs()[i].def_id)
304 });
305
306 // Convert the regions 'a, 'b, 'c defined on the trait into
307 // bound regions on the fn. Note that because these appear in the
308 // bound for `Self` they must be early bound.
309 let new_early_region_param_defs = trait_ty_generics.region_param_defs.clone();
310 let rps_from_trait =
311 trait_ty_generics.region_param_defs().iter().
312 enumerate().
313 map(|(index,d)| ty::ReEarlyBound(d.def_id.node, index, d.name)).
314 collect();
315
316 // build up the substitution from
317 // 'a,'b,'c => 'a,'b,'c
318 // A,B,C => A',B',C'
319 // Self => D'
320 // D,E,F => E',F',G'
321 let substs = substs {
322 regions: ty::NonerasedRegions(rps_from_trait),
323 self_ty: Some(self_param),
324 tps: non_shifted_trait_tps.append(shifted_method_tps.as_slice())
325 };
326
327 // create the type of `foo`, applying the substitution above
328 let ty = ty::subst(tcx,
329 &substs,
330 ty::mk_bare_fn(tcx, m.fty.clone()));
331
332 // create the type parameter definitions for `foo`, applying
333 // the substitution to any traits that appear in their bounds.
334
335 // add in the type parameters from the trait
336 let mut new_type_param_defs = Vec::new();
337 let substd_type_param_defs =
338 trait_ty_generics.type_param_defs.subst(tcx, &substs);
339 new_type_param_defs.push_all(substd_type_param_defs.as_slice());
340
341 // add in the "self" type parameter
342 let self_trait_def = get_trait_def(ccx, local_def(trait_id));
343 let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
344 new_type_param_defs.push(ty::TypeParameterDef {
345 ident: special_idents::self_,
346 def_id: dummy_defid,
347 bounds: Rc::new(ty::ParamBounds {
348 builtin_bounds: ty::EmptyBuiltinBounds(),
349 trait_bounds: vec!(self_trait_ref)
350 }),
351 default: None
352 });
353
354 // add in the type parameters from the method
355 let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
356 new_type_param_defs.push_all(substd_type_param_defs.as_slice());
357
358 debug!("static method {} type_param_defs={} ty={}, substs={}",
359 m.def_id.repr(tcx),
360 new_type_param_defs.repr(tcx),
361 ty.repr(tcx),
362 substs.repr(tcx));
363
364 tcx.tcache.borrow_mut().insert(m.def_id,
365 ty_param_bounds_and_ty {
366 generics: ty::Generics {
367 type_param_defs: Rc::new(new_type_param_defs),
368 region_param_defs: new_early_region_param_defs
369 },
370 ty: ty
371 });
372 }
373
374 fn ty_method_of_trait_method(this: &CrateCtxt,
375 trait_id: ast::NodeId,
376 trait_generics: &ty::Generics,
377 m_id: &ast::NodeId,
378 m_ident: &ast::Ident,
379 m_explicit_self: &ast::ExplicitSelf,
380 m_generics: &ast::Generics,
381 m_fn_style: &ast::FnStyle,
382 m_decl: &ast::FnDecl) -> ty::Method
383 {
384 let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
385 let fty = astconv::ty_of_method(this, *m_id, *m_fn_style, trait_self_ty,
386 *m_explicit_self, m_decl);
387 let num_trait_type_params = trait_generics.type_param_defs().len();
388 let ty_generics = ty_generics_for_fn_or_method(this, m_generics,
389 num_trait_type_params);
390 ty::Method::new(
391 *m_ident,
392 ty_generics,
393 fty,
394 m_explicit_self.node,
395 // assume public, because this is only invoked on trait methods
396 ast::Public,
397 local_def(*m_id),
398 TraitContainer(local_def(trait_id)),
399 None
400 )
401 }
402 }
403
404 pub fn ensure_supertraits(ccx: &CrateCtxt,
405 id: ast::NodeId,
406 sp: codemap::Span,
407 ast_trait_refs: &[ast::TraitRef],
408 sized: ast::Sized)
409 -> ty::BuiltinBounds
410 {
411 let tcx = ccx.tcx;
412
413 // Called only the first time trait_def_of_item is called.
414 // Supertraits are ensured at the same time.
415 assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
416
417 let self_ty = ty::mk_self(ccx.tcx, local_def(id));
418 let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
419 let mut bounds = ty::EmptyBuiltinBounds();
420 for ast_trait_ref in ast_trait_refs.iter() {
421 let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
422 // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
423 // builtin trait, so that the trait's node id appears in the tcx trait_ref
424 // map. This is only needed for metadata; see the similar fixme in encoder.rs.
425 let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
426 if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
427
428 // FIXME(#5527) Could have same trait multiple times
429 if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) {
430 // This means a trait inherited from the same supertrait more
431 // than once.
432 tcx.sess.span_err(sp, "duplicate supertrait in trait declaration");
433 break;
434 } else {
435 ty_trait_refs.push(trait_ref);
436 }
437 }
438 }
439 if sized == ast::StaticSize {
440 match tcx.lang_items.require(SizedTraitLangItem) {
441 Ok(def_id) => { ty::try_add_builtin_trait(tcx, def_id, &mut bounds); },
442 Err(s) => tcx.sess.err(s),
443 };
444 }
445
446 tcx.supertraits.borrow_mut().insert(local_def(id), Rc::new(ty_trait_refs));
447 bounds
448 }
449
450 pub fn convert_field(ccx: &CrateCtxt,
451 struct_generics: &ty::Generics,
452 v: &ast::StructField,
453 origin: ast::DefId) -> ty::field_ty {
454 let tt = ccx.to_ty(&ExplicitRscope, v.node.ty);
455 write_ty_to_tcx(ccx.tcx, v.node.id, tt);
456 /* add the field to the tcache */
457 ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
458 ty::ty_param_bounds_and_ty {
459 generics: struct_generics.clone(),
460 ty: tt
461 });
462
463 match v.node.kind {
464 ast::NamedField(ident, visibility) => {
465 ty::field_ty {
466 name: ident.name,
467 id: local_def(v.node.id),
468 vis: visibility,
469 origin: origin,
470 }
471 }
472 ast::UnnamedField(visibility) => {
473 ty::field_ty {
474 name: special_idents::unnamed_field.name,
475 id: local_def(v.node.id),
476 vis: visibility,
477 origin: origin,
478 }
479 }
480 }
481 }
482
483 fn convert_methods(ccx: &CrateCtxt,
484 container: MethodContainer,
485 ms: &[@ast::Method],
486 untransformed_rcvr_ty: ty::t,
487 rcvr_ty_generics: &ty::Generics,
488 rcvr_ast_generics: &ast::Generics,
489 rcvr_visibility: ast::Visibility)
490 {
491 let tcx = ccx.tcx;
492 let mut seen_methods = HashSet::new();
493 for m in ms.iter() {
494 if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
495 tcx.sess.span_err(m.span, "duplicate method in trait impl");
496 }
497
498 let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
499 let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
500 num_rcvr_ty_params);
501 let mty = Rc::new(ty_of_method(ccx,
502 container,
503 *m,
504 untransformed_rcvr_ty,
505 rcvr_ast_generics,
506 rcvr_visibility));
507 let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
508 debug!("method {} (id {}) has type {}",
509 m.ident.repr(ccx.tcx),
510 m.id,
511 fty.repr(ccx.tcx));
512 tcx.tcache.borrow_mut().insert(
513 local_def(m.id),
514
515 // n.b.: the type of a method is parameterized by both
516 // the parameters on the receiver and those on the method
517 // itself
518 ty_param_bounds_and_ty {
519 generics: ty::Generics {
520 type_param_defs: Rc::new(Vec::from_slice(rcvr_ty_generics.type_param_defs())
521 .append(m_ty_generics.type_param_defs())),
522 region_param_defs: Rc::new(Vec::from_slice(rcvr_ty_generics.region_param_defs())
523 .append(m_ty_generics.region_param_defs())),
524 },
525 ty: fty
526 });
527
528 write_ty_to_tcx(tcx, m.id, fty);
529
530 tcx.methods.borrow_mut().insert(mty.def_id, mty);
531 }
532
533 fn ty_of_method(ccx: &CrateCtxt,
534 container: MethodContainer,
535 m: &ast::Method,
536 untransformed_rcvr_ty: ty::t,
537 rcvr_generics: &ast::Generics,
538 rcvr_visibility: ast::Visibility) -> ty::Method
539 {
540 let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
541 untransformed_rcvr_ty,
542 m.explicit_self, m.decl);
543
544 // if the method specifies a visibility, use that, otherwise
545 // inherit the visibility from the impl (so `foo` in `pub impl
546 // { fn foo(); }` is public, but private in `priv impl { fn
547 // foo(); }`).
548 let method_vis = m.vis.inherit_from(rcvr_visibility);
549
550 let num_rcvr_type_params = rcvr_generics.ty_params.len();
551 let m_ty_generics =
552 ty_generics_for_fn_or_method(ccx, &m.generics, num_rcvr_type_params);
553 ty::Method::new(
554 m.ident,
555 m_ty_generics,
556 fty,
557 m.explicit_self.node,
558 method_vis,
559 local_def(m.id),
560 container,
561 None
562 )
563 }
564 }
565
566 pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
567 span: Span,
568 generics: &ast::Generics,
569 thing: &'static str) {
570 for ty_param in generics.ty_params.iter() {
571 if ty_param.bounds.len() > 0 {
572 ccx.tcx.sess.span_err(
573 span,
574 format!("trait bounds are not allowed in {} definitions", thing));
575 }
576 }
577 }
578
579 fn ensure_generics_abi(ccx: &CrateCtxt,
580 span: Span,
581 abi: abi::Abi,
582 generics: &ast::Generics) {
583 if generics.ty_params.len() > 0 &&
584 !(abi == abi::Rust || abi == abi::RustIntrinsic) {
585 ccx.tcx.sess.span_err(span,
586 "foreign functions may not use type parameters");
587 }
588 }
589
590 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
591 let tcx = ccx.tcx;
592 debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
593 match it.node {
594 // These don't define types.
595 ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
596 ast::ItemEnum(ref enum_definition, ref generics) => {
597 ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
598 let tpt = ty_of_item(ccx, it);
599 write_ty_to_tcx(tcx, it.id, tpt.ty);
600 get_enum_variant_types(ccx,
601 tpt.ty,
602 enum_definition.variants.as_slice(),
603 generics);
604 },
605 ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
606 let ty_generics = ty_generics_for_type(ccx, generics);
607 let selfty = ccx.to_ty(&ExplicitRscope, selfty);
608 write_ty_to_tcx(tcx, it.id, selfty);
609
610 tcx.tcache.borrow_mut().insert(local_def(it.id),
611 ty_param_bounds_and_ty {
612 generics: ty_generics.clone(),
613 ty: selfty});
614
615 // If there is a trait reference, treat the methods as always public.
616 // This is to work around some incorrect behavior in privacy checking:
617 // when the method belongs to a trait, it should acquire the privacy
618 // from the trait, not the impl. Forcing the visibility to be public
619 // makes things sorta work.
620 let parent_visibility = if opt_trait_ref.is_some() {
621 ast::Public
622 } else {
623 it.vis
624 };
625
626 convert_methods(ccx,
627 ImplContainer(local_def(it.id)),
628 ms.as_slice(),
629 selfty,
630 &ty_generics,
631 generics,
632 parent_visibility);
633
634 for trait_ref in opt_trait_ref.iter() {
635 instantiate_trait_ref(ccx, trait_ref, selfty);
636 }
637 },
638 ast::ItemTrait(ref generics, _, _, ref trait_methods) => {
639 let trait_def = trait_def_of_item(ccx, it);
640
641 // Run convert_methods on the provided methods.
642 let (_, provided_methods) =
643 split_trait_methods(trait_methods.as_slice());
644 let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
645 convert_methods(ccx,
646 TraitContainer(local_def(it.id)),
647 provided_methods.as_slice(),
648 untransformed_rcvr_ty,
649 &trait_def.generics,
650 generics,
651 it.vis);
652
653 // We need to do this *after* converting methods, since
654 // convert_methods produces a tcache entry that is wrong for
655 // static trait methods. This is somewhat unfortunate.
656 ensure_trait_methods(ccx, it.id);
657 },
658 ast::ItemStruct(struct_def, ref generics) => {
659 ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
660
661 // Write the class type.
662 let tpt = ty_of_item(ccx, it);
663 write_ty_to_tcx(tcx, it.id, tpt.ty);
664
665 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
666
667 // Write the super-struct type, if it exists.
668 match struct_def.super_struct {
669 Some(ty) => {
670 let supserty = ccx.to_ty(&ExplicitRscope, ty);
671 write_ty_to_tcx(tcx, it.id, supserty);
672 },
673 _ => {},
674 }
675
676 convert_struct(ccx, struct_def, tpt, it.id);
677 },
678 ast::ItemTy(_, ref generics) => {
679 ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
680 let tpt = ty_of_item(ccx, it);
681 write_ty_to_tcx(tcx, it.id, tpt.ty);
682 },
683 ast::ItemFn(_, _, abi, ref generics, _) => {
684 ensure_generics_abi(ccx, it.span, abi, generics);
685 let tpt = ty_of_item(ccx, it);
686 write_ty_to_tcx(tcx, it.id, tpt.ty);
687 },
688 _ => {
689 // This call populates the type cache with the converted type
690 // of the item in passing. All we have to do here is to write
691 // it into the node type table.
692 let tpt = ty_of_item(ccx, it);
693 write_ty_to_tcx(tcx, it.id, tpt.ty);
694 },
695 }
696 }
697
698 pub fn convert_struct(ccx: &CrateCtxt,
699 struct_def: &ast::StructDef,
700 tpt: ty::ty_param_bounds_and_ty,
701 id: ast::NodeId) {
702 let tcx = ccx.tcx;
703
704 // Write the type of each of the members and check for duplicate fields.
705 let mut seen_fields: HashMap<ast::Name, Span> = HashMap::new();
706 let field_tys = struct_def.fields.iter().map(|f| {
707 let result = convert_field(ccx, &tpt.generics, f, local_def(id));
708
709 if result.name != special_idents::unnamed_field.name {
710 let dup = match seen_fields.find(&result.name) {
711 Some(prev_span) => {
712 tcx.sess.span_err(f.span,
713 format!("field `{}` is already declared", token::get_name(result.name)));
714 tcx.sess.span_note(*prev_span,
715 "previously declared here");
716 true
717 },
718 None => false,
719 };
720 // FIXME(#6393) this whole dup thing is just to satisfy
721 // the borrow checker :-(
722 if !dup {
723 seen_fields.insert(result.name, f.span);
724 }
725 }
726
727 result
728 }).collect();
729
730 tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
731
732 let super_struct = match struct_def.super_struct {
733 Some(t) => match t.node {
734 ast::TyPath(_, _, path_id) => {
735 let def_map = tcx.def_map.borrow();
736 match def_map.find(&path_id) {
737 Some(&ast::DefStruct(def_id)) => {
738 // FIXME(#12511) Check for cycles in the inheritance hierarchy.
739 // Check super-struct is virtual.
740 match tcx.map.find(def_id.node) {
741 Some(ast_map::NodeItem(i)) => match i.node {
742 ast::ItemStruct(struct_def, _) => {
743 if !struct_def.is_virtual {
744 tcx.sess.span_err(t.span,
745 "struct inheritance is only \
746 allowed from virtual structs");
747 }
748 },
749 _ => {},
750 },
751 _ => {},
752 }
753
754 Some(def_id)
755 },
756 _ => None,
757 }
758 }
759 _ => None,
760 },
761 None => None,
762 };
763 tcx.superstructs.borrow_mut().insert(local_def(id), super_struct);
764
765 let substs = mk_item_substs(ccx, &tpt.generics, None);
766 let selfty = ty::mk_struct(tcx, local_def(id), substs);
767
768 // If this struct is enum-like or tuple-like, create the type of its
769 // constructor.
770 match struct_def.ctor_id {
771 None => {}
772 Some(ctor_id) => {
773 if struct_def.fields.len() == 0 {
774 // Enum-like.
775 write_ty_to_tcx(tcx, ctor_id, selfty);
776
777 tcx.tcache.borrow_mut().insert(local_def(ctor_id), tpt);
778 } else if struct_def.fields.get(0).node.kind.is_unnamed() {
779 // Tuple-like.
780 let inputs: Vec<_> = struct_def.fields.iter().map(
781 |field| tcx.tcache.borrow().get(
782 &local_def(field.node.id)).ty).collect();
783 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
784 ctor_id,
785 inputs.as_slice(),
786 selfty);
787 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
788 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
789 ty_param_bounds_and_ty {
790 generics: tpt.generics,
791 ty: ctor_fn_ty
792 });
793 }
794 }
795 }
796 }
797
798 pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
799 // As above, this call populates the type table with the converted
800 // type of the foreign item. We simply write it into the node type
801 // table.
802
803 // For reasons I cannot fully articulate, I do so hate the AST
804 // map, and I regard each time that I use it as a personal and
805 // moral failing, but at the moment it seems like the only
806 // convenient way to extract the ABI. - ndm
807 let abi = ccx.tcx.map.get_foreign_abi(i.id);
808
809 let tpt = ty_of_foreign_item(ccx, i, abi);
810 write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
811
812 ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), tpt);
813 }
814
815 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
816 ast_trait_ref: &ast::TraitRef,
817 self_ty: ty::t) -> Rc<ty::TraitRef> {
818 /*!
819 * Instantiates the path for the given trait reference, assuming that
820 * it's bound to a valid trait type. Returns the def_id for the defining
821 * trait. Fails if the type is a type other than a trait type.
822 */
823
824 // FIXME(#5121) -- distinguish early vs late lifetime params
825 let rscope = ExplicitRscope;
826
827 match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
828 ast::DefTrait(trait_did) => {
829 let trait_ref =
830 astconv::ast_path_to_trait_ref(
831 ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
832
833 ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
834 trait_ref.clone());
835 trait_ref
836 }
837 _ => {
838 ccx.tcx.sess.span_fatal(
839 ast_trait_ref.path.span,
840 format!("`{}` is not a trait",
841 path_to_str(&ast_trait_ref.path)));
842 }
843 }
844 }
845
846 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
847 if trait_id.krate != ast::LOCAL_CRATE {
848 return ty::lookup_trait_def(ccx.tcx, trait_id)
849 }
850
851 match ccx.tcx.map.get(trait_id.node) {
852 ast_map::NodeItem(item) => trait_def_of_item(ccx, item),
853 _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
854 trait_id.node))
855 }
856 }
857
858 pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
859 let def_id = local_def(it.id);
860 let tcx = ccx.tcx;
861 match tcx.trait_defs.borrow().find(&def_id) {
862 Some(def) => return def.clone(),
863 _ => {}
864 }
865
866 match it.node {
867 ast::ItemTrait(ref generics, sized, ref supertraits, _) => {
868 let self_ty = ty::mk_self(tcx, def_id);
869 let ty_generics = ty_generics_for_type(ccx, generics);
870 let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
871 let bounds = ensure_supertraits(ccx,
872 it.id,
873 it.span,
874 supertraits.as_slice(),
875 sized);
876 let trait_def = Rc::new(ty::TraitDef {
877 generics: ty_generics,
878 bounds: bounds,
879 trait_ref: Rc::new(ty::TraitRef {
880 def_id: def_id,
881 substs: substs
882 })
883 });
884 tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
885 trait_def
886 }
887 ref s => {
888 tcx.sess.span_bug(
889 it.span,
890 format!("trait_def_of_item invoked on {:?}", s));
891 }
892 }
893 }
894
895 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
896 -> ty::ty_param_bounds_and_ty {
897 let def_id = local_def(it.id);
898 let tcx = ccx.tcx;
899 match tcx.tcache.borrow().find(&def_id) {
900 Some(tpt) => return tpt.clone(),
901 _ => {}
902 }
903 match it.node {
904 ast::ItemStatic(t, _, _) => {
905 let typ = ccx.to_ty(&ExplicitRscope, t);
906 let tpt = no_params(typ);
907
908 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
909 return tpt;
910 }
911 ast::ItemFn(decl, fn_style, abi, ref generics, _) => {
912 let ty_generics = ty_generics_for_fn_or_method(ccx, generics, 0);
913 let tofd = astconv::ty_of_bare_fn(ccx,
914 it.id,
915 fn_style,
916 abi,
917 decl);
918 let tpt = ty_param_bounds_and_ty {
919 generics: ty_generics,
920 ty: ty::mk_bare_fn(ccx.tcx, tofd)
921 };
922 debug!("type of {} (id {}) is {}",
923 token::get_ident(it.ident),
924 it.id,
925 ppaux::ty_to_str(tcx, tpt.ty));
926
927 ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
928 return tpt;
929 }
930 ast::ItemTy(t, ref generics) => {
931 match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
932 Some(tpt) => return tpt.clone(),
933 None => { }
934 }
935
936 let tpt = {
937 let ty = ccx.to_ty(&ExplicitRscope, t);
938 ty_param_bounds_and_ty {
939 generics: ty_generics_for_type(ccx, generics),
940 ty: ty
941 }
942 };
943
944 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
945 return tpt;
946 }
947 ast::ItemEnum(_, ref generics) => {
948 // Create a new generic polytype.
949 let ty_generics = ty_generics_for_type(ccx, generics);
950 let substs = mk_item_substs(ccx, &ty_generics, None);
951 let t = ty::mk_enum(tcx, local_def(it.id), substs);
952 let tpt = ty_param_bounds_and_ty {
953 generics: ty_generics,
954 ty: t
955 };
956
957 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
958 return tpt;
959 }
960 ast::ItemTrait(..) => {
961 tcx.sess.span_bug(
962 it.span,
963 format!("invoked ty_of_item on trait"));
964 }
965 ast::ItemStruct(_, ref generics) => {
966 let ty_generics = ty_generics_for_type(ccx, generics);
967 let substs = mk_item_substs(ccx, &ty_generics, None);
968 let t = ty::mk_struct(tcx, local_def(it.id), substs);
969 let tpt = ty_param_bounds_and_ty {
970 generics: ty_generics,
971 ty: t
972 };
973
974 tcx.tcache.borrow_mut().insert(local_def(it.id), tpt.clone());
975 return tpt;
976 }
977 ast::ItemImpl(..) | ast::ItemMod(_) |
978 ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
979 }
980 }
981
982 pub fn ty_of_foreign_item(ccx: &CrateCtxt,
983 it: &ast::ForeignItem,
984 abi: abi::Abi) -> ty::ty_param_bounds_and_ty
985 {
986 match it.node {
987 ast::ForeignItemFn(fn_decl, ref generics) => {
988 ty_of_foreign_fn_decl(ccx,
989 fn_decl,
990 local_def(it.id),
991 generics,
992 abi)
993 }
994 ast::ForeignItemStatic(t, _) => {
995 ty::ty_param_bounds_and_ty {
996 generics: ty::Generics {
997 type_param_defs: Rc::new(Vec::new()),
998 region_param_defs: Rc::new(Vec::new()),
999 },
1000 ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
1001 }
1002 }
1003 }
1004 }
1005
1006 fn ty_generics_for_type(ccx: &CrateCtxt,
1007 generics: &ast::Generics)
1008 -> ty::Generics {
1009 ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
1010 }
1011
1012 fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
1013 generics: &ast::Generics,
1014 base_index: uint)
1015 -> ty::Generics {
1016 let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1017 ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
1018 }
1019
1020 fn ty_generics(ccx: &CrateCtxt,
1021 lifetimes: &Vec<ast::Lifetime>,
1022 ty_params: &OwnedSlice<ast::TyParam>,
1023 base_index: uint) -> ty::Generics {
1024 return ty::Generics {
1025 region_param_defs: Rc::new(lifetimes.iter().map(|l| {
1026 ty::RegionParameterDef { name: l.name,
1027 def_id: local_def(l.id) }
1028 }).collect()),
1029 type_param_defs: Rc::new(ty_params.iter().enumerate().map(|(offset, param)| {
1030 let existing_def_opt = {
1031 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
1032 ty_param_defs.find(¶m.id).map(|def| def.clone())
1033 };
1034 existing_def_opt.unwrap_or_else(|| {
1035 let param_ty = ty::param_ty {idx: base_index + offset,
1036 def_id: local_def(param.id)};
1037 let bounds = Rc::new(compute_bounds(ccx,
1038 param_ty,
1039 ¶m.bounds,
1040 param.sized,
1041 param.ident,
1042 param.span));
1043 let default = param.default.map(|path| {
1044 let ty = ast_ty_to_ty(ccx, &ExplicitRscope, path);
1045 let cur_idx = param_ty.idx;
1046
1047 ty::walk_ty(ty, |t| {
1048 match ty::get(t).sty {
1049 ty::ty_param(p) => if p.idx > cur_idx {
1050 ccx.tcx.sess.span_err(path.span,
1051 "type parameters with a default cannot use \
1052 forward declared identifiers")
1053 },
1054 _ => {}
1055 }
1056 });
1057
1058 ty
1059 });
1060
1061 let def = ty::TypeParameterDef {
1062 ident: param.ident,
1063 def_id: local_def(param.id),
1064 bounds: bounds,
1065 default: default
1066 };
1067 debug!("def for param: {}", def.repr(ccx.tcx));
1068 ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
1069 def
1070 })
1071 }).collect()),
1072 };
1073
1074 fn compute_bounds(
1075 ccx: &CrateCtxt,
1076 param_ty: ty::param_ty,
1077 ast_bounds: &OwnedSlice<ast::TyParamBound>,
1078 sized: ast::Sized,
1079 ident: ast::Ident,
1080 span: Span) -> ty::ParamBounds
1081 {
1082 /*!
1083 * Translate the AST's notion of ty param bounds (which are an
1084 * enum consisting of a newtyped Ty or a region) to ty's
1085 * notion of ty param bounds, which can either be user-defined
1086 * traits, or the built-in trait (formerly known as kind): Send.
1087 */
1088
1089 let mut param_bounds = ty::ParamBounds {
1090 builtin_bounds: ty::EmptyBuiltinBounds(),
1091 trait_bounds: Vec::new()
1092 };
1093 for ast_bound in ast_bounds.iter() {
1094 match *ast_bound {
1095 TraitTyParamBound(ref b) => {
1096 let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
1097 let trait_ref = instantiate_trait_ref(ccx, b, ty);
1098 if !ty::try_add_builtin_trait(
1099 ccx.tcx, trait_ref.def_id,
1100 &mut param_bounds.builtin_bounds) {
1101 // Must be a user-defined trait
1102 param_bounds.trait_bounds.push(trait_ref);
1103 }
1104 }
1105
1106 StaticRegionTyParamBound => {
1107 param_bounds.builtin_bounds.add(ty::BoundStatic);
1108 }
1109
1110 OtherRegionTyParamBound(span) => {
1111 if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
1112 ccx.tcx.sess.span_err(
1113 span,
1114 format!("only the 'static lifetime is \
1115 accepted here."));
1116 }
1117 }
1118 }
1119 }
1120
1121 if sized == ast::StaticSize {
1122 match ccx.tcx.lang_items.require(SizedTraitLangItem) {
1123 Ok(def_id) => { ty::try_add_builtin_trait(ccx.tcx,
1124 def_id,
1125 &mut param_bounds.builtin_bounds); },
1126 // Fixme(13367) after `type` makes it into the snapshot, we can check this properly
1127 Err(_s) => {}, //ccx.tcx.sess.err(s),
1128 }
1129 }
1130
1131 check_bounds_compatible(ccx.tcx, ¶m_bounds, ident, span);
1132
1133 param_bounds
1134 }
1135
1136 fn check_bounds_compatible(tcx: &ty::ctxt,
1137 param_bounds: &ty::ParamBounds,
1138 ident: ast::Ident,
1139 span: Span) {
1140 // Currently the only bound which is incompatible with other bounds is
1141 // Sized/Unsized.
1142 if !param_bounds.builtin_bounds.contains_elem(ty::BoundSized) {
1143 ty::each_bound_trait_and_supertraits(tcx,
1144 param_bounds.trait_bounds.as_slice(),
1145 |trait_ref| {
1146 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
1147 if trait_def.bounds.contains_elem(ty::BoundSized) {
1148 tcx.sess.span_err(span,
1149 format!("incompatible bounds on type parameter {}, \
1150 bound {} does not allow unsized type",
1151 token::get_ident(ident),
1152 ppaux::trait_ref_to_str(tcx, &*trait_ref)));
1153 }
1154 true
1155 });
1156 }
1157 }
1158 }
1159
1160 pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
1161 decl: &ast::FnDecl,
1162 def_id: ast::DefId,
1163 ast_generics: &ast::Generics,
1164 abi: abi::Abi)
1165 -> ty::ty_param_bounds_and_ty {
1166
1167 for i in decl.inputs.iter() {
1168 match (*i).pat.node {
1169 ast::PatIdent(_, _, _) => (),
1170 ast::PatWild => (),
1171 _ => ccx.tcx.sess.span_err((*i).pat.span,
1172 "patterns aren't allowed in foreign function declarations")
1173 }
1174 }
1175
1176 let ty_generics_for_fn_or_method =
1177 ty_generics_for_fn_or_method(ccx, ast_generics, 0);
1178 let rb = BindingRscope::new(def_id.node);
1179 let input_tys = decl.inputs
1180 .iter()
1181 .map(|a| ty_of_arg(ccx, &rb, a, None))
1182 .collect();
1183
1184 let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
1185
1186 let t_fn = ty::mk_bare_fn(
1187 ccx.tcx,
1188 ty::BareFnTy {
1189 abi: abi,
1190 fn_style: ast::UnsafeFn,
1191 sig: ty::FnSig {binder_id: def_id.node,
1192 inputs: input_tys,
1193 output: output_ty,
1194 variadic: decl.variadic}
1195 });
1196 let tpt = ty_param_bounds_and_ty {
1197 generics: ty_generics_for_fn_or_method,
1198 ty: t_fn
1199 };
1200
1201 ccx.tcx.tcache.borrow_mut().insert(def_id, tpt.clone());
1202 return tpt;
1203 }
1204
1205 pub fn mk_item_substs(ccx: &CrateCtxt,
1206 ty_generics: &ty::Generics,
1207 self_ty: Option<ty::t>) -> ty::substs
1208 {
1209 let params: Vec<ty::t> =
1210 ty_generics.type_param_defs().iter().enumerate().map(
1211 |(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
1212
1213 let regions: OwnedSlice<ty::Region> =
1214 ty_generics.region_param_defs().iter().enumerate().map(
1215 |(i, l)| ty::ReEarlyBound(l.def_id.node, i, l.name)).collect();
1216
1217 substs {regions: ty::NonerasedRegions(regions),
1218 self_ty: self_ty,
1219 tps: params}
1220 }
librustc/middle/typeck/collect.rs:697:1-697:1 -fn- definition:
pub fn convert_struct(ccx: &CrateCtxt,
struct_def: &ast::StructDef,
tpt: ty::ty_param_bounds_and_ty,
references:- 2170: convert_struct(ccx, struct_def, tpt, variant.node.id);
--
676: convert_struct(ccx, struct_def, tpt, it.id);
677: },
librustc/middle/typeck/collect.rs:482:1-482:1 -fn- definition:
fn convert_methods(ccx: &CrateCtxt,
container: MethodContainer,
ms: &[@ast::Method],
references:- 2626: convert_methods(ccx,
627: ImplContainer(local_def(it.id)),
--
644: let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
645: convert_methods(ccx,
646: TraitContainer(local_def(it.id)),
librustc/middle/typeck/collect.rs:894:1-894:1 -fn- definition:
pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
-> ty::ty_param_bounds_and_ty {
let def_id = local_def(it.id);
references:- 6118: match self.tcx.map.find(id.node) {
119: Some(ast_map::NodeItem(item)) => ty_of_item(self, item),
120: Some(ast_map::NodeForeignItem(foreign_item)) => {
--
597: ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
598: let tpt = ty_of_item(ccx, it);
599: write_ty_to_tcx(tcx, it.id, tpt.ty);
--
679: ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
680: let tpt = ty_of_item(ccx, it);
681: write_ty_to_tcx(tcx, it.id, tpt.ty);
--
691: // it into the node type table.
692: let tpt = ty_of_item(ccx, it);
693: write_ty_to_tcx(tcx, it.id, tpt.ty);
librustc/middle/typeck/collect.rs:857:1-857:1 -fn- definition:
pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
let def_id = local_def(it.id);
let tcx = ccx.tcx;
references:- 2638: ast::ItemTrait(ref generics, _, _, ref trait_methods) => {
639: let trait_def = trait_def_of_item(ccx, it);
--
851: match ccx.tcx.map.get(trait_id.node) {
852: ast_map::NodeItem(item) => trait_def_of_item(ccx, item),
853: _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
librustc/middle/typeck/collect.rs:82:4-82:4 -fn- definition:
fn collect_intrinsic_type(ccx: &CrateCtxt,
lang_item: ast::DefId) {
let ty::ty_param_bounds_and_ty { ty: ty, .. } =
references:- 289: match ccx.tcx.lang_items.ty_desc() {
90: Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
91: }
92: match ccx.tcx.lang_items.opaque() {
93: Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
94: }
librustc/middle/typeck/collect.rs:1005:1-1005:1 -fn- definition:
fn ty_generics_for_type(ccx: &CrateCtxt,
generics: &ast::Generics)
-> ty::Generics {
references:- 8868: let self_ty = ty::mk_self(tcx, def_id);
869: let ty_generics = ty_generics_for_type(ccx, generics);
870: let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
--
948: // Create a new generic polytype.
949: let ty_generics = ty_generics_for_type(ccx, generics);
950: let substs = mk_item_substs(ccx, &ty_generics, None);
--
965: ast::ItemStruct(_, ref generics) => {
966: let ty_generics = ty_generics_for_type(ccx, generics);
967: let substs = mk_item_substs(ccx, &ty_generics, None);
librustc/middle/typeck/collect.rs:981:1-981:1 -fn- definition:
pub fn ty_of_foreign_item(ccx: &CrateCtxt,
it: &ast::ForeignItem,
abi: abi::Abi) -> ty::ty_param_bounds_and_ty
references:- 2121: let abi = self.tcx.map.get_foreign_abi(id.node);
122: ty_of_foreign_item(self, foreign_item, abi)
123: }
--
809: let tpt = ty_of_foreign_item(ccx, i, abi);
810: write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
librustc/middle/typeck/collect.rs:814:1-814:1 -fn- definition:
pub fn instantiate_trait_ref(ccx: &CrateCtxt,
ast_trait_ref: &ast::TraitRef,
self_ty: ty::t) -> Rc<ty::TraitRef> {
references:- 3424: // map. This is only needed for metadata; see the similar fixme in encoder.rs.
425: let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
426: if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
--
1096: let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
1097: let trait_ref = instantiate_trait_ref(ccx, b, ty);
1098: if !ty::try_add_builtin_trait(
librustc/middle/typeck/collect.rs:1011:1-1011:1 -fn- definition:
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
generics: &ast::Generics,
base_index: uint)
references:- 5498: let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
499: let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
500: num_rcvr_ty_params);
--
1176: let ty_generics_for_fn_or_method =
1177: ty_generics_for_fn_or_method(ccx, ast_generics, 0);
1178: let rb = BindingRscope::new(def_id.node);
librustc/middle/typeck/collect.rs:65:1-65:1 -struct- definition:
struct CollectItemTypesVisitor<'a> {
ccx: &'a CrateCtxt<'a>
}
references:- 270: impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
71: fn visit_item(&mut self, i: &ast::Item, _: ()) {
--
96: let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
97: visit::walk_crate(&mut visitor, krate, ());
librustc/middle/typeck/collect.rs:374:4-374:4 -fn- definition:
fn ty_method_of_trait_method(this: &CrateCtxt,
trait_id: ast::NodeId,
trait_generics: &ty::Generics,
references:- 2208: &ast::Provided(ref m) => {
209: ty_method_of_trait_method(
210: ccx, trait_id, &trait_ty_generics,
librustc/middle/typeck/collect.rs:845:1-845:1 -fn- definition:
fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
if trait_id.krate != ast::LOCAL_CRATE {
return ty::lookup_trait_def(ccx.tcx, trait_id)
references:- 2131: fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
132: get_trait_def(self, id)
133: }
--
341: // add in the "self" type parameter
342: let self_trait_def = get_trait_def(ccx, local_def(trait_id));
343: let self_trait_ref = self_trait_def.trait_ref.subst(tcx, &substs);
librustc/middle/typeck/collect.rs:1204:1-1204:1 -fn- definition:
pub fn mk_item_substs(ccx: &CrateCtxt,
ty_generics: &ty::Generics,
self_ty: Option<ty::t>) -> ty::substs
references:- 4966: let ty_generics = ty_generics_for_type(ccx, generics);
967: let substs = mk_item_substs(ccx, &ty_generics, None);
968: let t = ty::mk_struct(tcx, local_def(it.id), substs);
librustc/middle/typeck/collect.rs:1019:1-1019:1 -fn- definition:
fn ty_generics(ccx: &CrateCtxt,
lifetimes: &Vec<ast::Lifetime>,
ty_params: &OwnedSlice<ast::TyParam>,
references:- 21008: -> ty::Generics {
1009: ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
1010: }
--
1016: let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
1017: ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
1018: }
librustc/middle/typeck/collect.rs:565:1-565:1 -fn- definition:
pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
span: Span,
generics: &ast::Generics,
references:- 3678: ast::ItemTy(_, ref generics) => {
679: ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
680: let tpt = ty_of_item(ccx, it);