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 * Conversion from AST representation of types to the ty.rs
13 * representation. The main routine here is `ast_ty_to_ty()`: each use
14 * is parameterized by an instance of `AstConv` and a `RegionScope`.
15 *
16 * The parameterization of `ast_ty_to_ty()` is because it behaves
17 * somewhat differently during the collect and check phases,
18 * particularly with respect to looking up the types of top-level
19 * items. In the collect phase, the crate context is used as the
20 * `AstConv` instance; in this phase, the `get_item_ty()` function
21 * triggers a recursive call to `ty_of_item()` (note that
22 * `ast_ty_to_ty()` will detect recursive types and report an error).
23 * In the check phase, when the FnCtxt is used as the `AstConv`,
24 * `get_item_ty()` just looks up the item type in `tcx.tcache`.
25 *
26 * The `RegionScope` trait controls what happens when the user does
27 * not specify a region in some location where a region is required
28 * (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
29 * See the `rscope` module for more details.
30 *
31 * Unlike the `AstConv` trait, the region scope can change as we descend
32 * the type. This is to accommodate the fact that (a) fn types are binding
33 * scopes and (b) the default region may change. To understand case (a),
34 * consider something like:
35 *
36 * type foo = { x: &a.int, y: |&a.int| }
37 *
38 * The type of `x` is an error because there is no region `a` in scope.
39 * In the type of `y`, however, region `a` is considered a bound region
40 * as it does not already appear in scope.
41 *
42 * Case (b) says that if you have a type:
43 * type foo<'a> = ...;
44 * type bar = fn(&foo, &a.foo)
45 * The fully expanded version of type bar is:
46 * type bar = fn(&'foo &, &a.foo<'a>)
47 * Note that the self region for the `foo` defaulted to `&` in the first
48 * case but `&a` in the second. Basically, defaults that appear inside
49 * an rptr (`&r.T`) use the region `r` that appears in the rptr.
50 */
51
52
53 use middle::const_eval;
54 use middle::subst::Subst;
55 use middle::ty::{substs};
56 use middle::ty::{ty_param_substs_and_ty};
57 use middle::ty;
58 use middle::typeck::rscope;
59 use middle::typeck::rscope::{RegionScope};
60 use middle::typeck::lookup_def_tcx;
61 use util::ppaux::Repr;
62
63 use std::rc::Rc;
64 use syntax::abi;
65 use syntax::{ast, ast_util};
66 use syntax::codemap::Span;
67 use syntax::owned_slice::OwnedSlice;
68 use syntax::print::pprust::{lifetime_to_str, path_to_str};
69
70 pub trait AstConv {
71 fn tcx<'a>(&'a self) -> &'a ty::ctxt;
72 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
73 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef>;
74
75 // what type should we use when a type is omitted?
76 fn ty_infer(&self, span: Span) -> ty::t;
77 }
78
79 pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
80 -> ty::Region {
81 let r = match tcx.named_region_map.find(&lifetime.id) {
82 None => {
83 // should have been recorded by the `resolve_lifetime` pass
84 tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
85 }
86
87 Some(&ast::DefStaticRegion) => {
88 ty::ReStatic
89 }
90
91 Some(&ast::DefLateBoundRegion(binder_id, _, id)) => {
92 ty::ReLateBound(binder_id, ty::BrNamed(ast_util::local_def(id),
93 lifetime.name))
94 }
95
96 Some(&ast::DefEarlyBoundRegion(index, id)) => {
97 ty::ReEarlyBound(id, index, lifetime.name)
98 }
99
100 Some(&ast::DefFreeRegion(scope_id, id)) => {
101 ty::ReFree(ty::FreeRegion {
102 scope_id: scope_id,
103 bound_region: ty::BrNamed(ast_util::local_def(id),
104 lifetime.name)
105 })
106 }
107 };
108
109 debug!("ast_region_to_region(lifetime={} id={}) yields {}",
110 lifetime_to_str(lifetime),
111 lifetime.id, r.repr(tcx));
112
113 r
114 }
115
116 pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
117 this: &AC,
118 rscope: &RS,
119 default_span: Span,
120 opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
121 {
122 let r = match *opt_lifetime {
123 Some(ref lifetime) => {
124 ast_region_to_region(this.tcx(), lifetime)
125 }
126
127 None => {
128 match rscope.anon_regions(default_span, 1) {
129 Err(()) => {
130 debug!("optional region in illegal location");
131 this.tcx().sess.span_err(
132 default_span, "missing lifetime specifier");
133 ty::ReStatic
134 }
135
136 Ok(rs) => {
137 *rs.get(0)
138 }
139 }
140 }
141 };
142
143 debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {}",
144 opt_lifetime.as_ref().map(|e| lifetime_to_str(e)),
145 r.repr(this.tcx()));
146
147 r
148 }
149
150 fn ast_path_substs<AC:AstConv,RS:RegionScope>(
151 this: &AC,
152 rscope: &RS,
153 decl_generics: &ty::Generics,
154 self_ty: Option<ty::t>,
155 path: &ast::Path) -> ty::substs
156 {
157 /*!
158 * Given a path `path` that refers to an item `I` with the
159 * declared generics `decl_generics`, returns an appropriate
160 * set of substitutions for this particular reference to `I`.
161 */
162
163 let tcx = this.tcx();
164
165 // If the type is parameterized by the this region, then replace this
166 // region with the current anon region binding (in other words,
167 // whatever & would get replaced with).
168 let expected_num_region_params = decl_generics.region_param_defs().len();
169 let supplied_num_region_params = path.segments.last().unwrap().lifetimes.len();
170 let regions = if expected_num_region_params == supplied_num_region_params {
171 path.segments.last().unwrap().lifetimes.iter().map(
172 |l| ast_region_to_region(this.tcx(), l)).collect::<Vec<_>>()
173 } else {
174 let anon_regions =
175 rscope.anon_regions(path.span, expected_num_region_params);
176
177 if supplied_num_region_params != 0 || anon_regions.is_err() {
178 tcx.sess.span_err(
179 path.span,
180 format!("wrong number of lifetime parameters: \
181 expected {} but found {}",
182 expected_num_region_params,
183 supplied_num_region_params));
184 }
185
186 match anon_regions {
187 Ok(v) => v.move_iter().collect(),
188 Err(()) => Vec::from_fn(expected_num_region_params,
189 |_| ty::ReStatic) // hokey
190 }
191 };
192
193 // Convert the type parameters supplied by the user.
194 let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).len();
195 let formal_ty_param_count = decl_generics.type_param_defs().len();
196 let required_ty_param_count = decl_generics.type_param_defs().iter()
197 .take_while(|x| x.default.is_none())
198 .len();
199 if supplied_ty_param_count < required_ty_param_count {
200 let expected = if required_ty_param_count < formal_ty_param_count {
201 "expected at least"
202 } else {
203 "expected"
204 };
205 this.tcx().sess.span_fatal(path.span,
206 format!("wrong number of type arguments: {} {} but found {}",
207 expected, required_ty_param_count, supplied_ty_param_count));
208 } else if supplied_ty_param_count > formal_ty_param_count {
209 let expected = if required_ty_param_count < formal_ty_param_count {
210 "expected at most"
211 } else {
212 "expected"
213 };
214 this.tcx().sess.span_fatal(path.span,
215 format!("wrong number of type arguments: {} {} but found {}",
216 expected, formal_ty_param_count, supplied_ty_param_count));
217 }
218
219 if supplied_ty_param_count > required_ty_param_count
220 && !this.tcx().sess.features.default_type_params.get() {
221 this.tcx().sess.span_err(path.span, "default type parameters are \
222 experimental and possibly buggy");
223 this.tcx().sess.span_note(path.span, "add #![feature(default_type_params)] \
224 to the crate attributes to enable");
225 }
226
227 let tps = path.segments.iter().flat_map(|s| s.types.iter())
228 .map(|&a_t| ast_ty_to_ty(this, rscope, a_t))
229 .collect();
230
231 let mut substs = substs {
232 regions: ty::NonerasedRegions(OwnedSlice::from_vec(regions)),
233 self_ty: self_ty,
234 tps: tps
235 };
236
237 for param in decl_generics.type_param_defs()
238 .slice_from(supplied_ty_param_count).iter() {
239 let ty = param.default.unwrap().subst_spanned(tcx, &substs, Some(path.span));
240 substs.tps.push(ty);
241 }
242
243 substs
244 }
245
246 pub fn ast_path_to_substs_and_ty<AC:AstConv,
247 RS:RegionScope>(
248 this: &AC,
249 rscope: &RS,
250 did: ast::DefId,
251 path: &ast::Path)
252 -> ty_param_substs_and_ty {
253 let tcx = this.tcx();
254 let ty::ty_param_bounds_and_ty {
255 generics: generics,
256 ty: decl_ty
257 } = this.get_item_ty(did);
258
259 let substs = ast_path_substs(this, rscope, &generics, None, path);
260 let ty = ty::subst(tcx, &substs, decl_ty);
261 ty_param_substs_and_ty { substs: substs, ty: ty }
262 }
263
264 pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
265 this: &AC,
266 rscope: &RS,
267 trait_def_id: ast::DefId,
268 self_ty: Option<ty::t>,
269 path: &ast::Path) -> Rc<ty::TraitRef> {
270 let trait_def = this.get_trait_def(trait_def_id);
271 Rc::new(ty::TraitRef {
272 def_id: trait_def_id,
273 substs: ast_path_substs(this, rscope, &trait_def.generics, self_ty, path)
274 })
275 }
276
277 pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
278 this: &AC,
279 rscope: &RS,
280 did: ast::DefId,
281 path: &ast::Path)
282 -> ty_param_substs_and_ty
283 {
284 // Look up the polytype of the item and then substitute the provided types
285 // for any type/region parameters.
286 let ty::ty_param_substs_and_ty {
287 substs: substs,
288 ty: ty
289 } = ast_path_to_substs_and_ty(this, rscope, did, path);
290 ty_param_substs_and_ty { substs: substs, ty: ty }
291 }
292
293 pub static NO_REGIONS: uint = 1;
294 pub static NO_TPS: uint = 2;
295
296 fn check_path_args(tcx: &ty::ctxt,
297 path: &ast::Path,
298 flags: uint) {
299 if (flags & NO_TPS) != 0u {
300 if !path.segments.iter().all(|s| s.types.is_empty()) {
301 tcx.sess.span_err(
302 path.span,
303 "type parameters are not allowed on this type");
304 }
305 }
306
307 if (flags & NO_REGIONS) != 0u {
308 if !path.segments.last().unwrap().lifetimes.is_empty() {
309 tcx.sess.span_err(
310 path.span,
311 "region parameters are not allowed on this type");
312 }
313 }
314 }
315
316 pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
317 match ast_ty.node {
318 ast::TyPath(ref path, _, id) => {
319 let a_def = match tcx.def_map.borrow().find(&id) {
320 None => tcx.sess.span_bug(
321 ast_ty.span, format!("unbound path {}", path_to_str(path))),
322 Some(&d) => d
323 };
324 match a_def {
325 ast::DefPrimTy(nty) => {
326 match nty {
327 ast::TyBool => {
328 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
329 Some(ty::mk_bool())
330 }
331 ast::TyChar => {
332 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
333 Some(ty::mk_char())
334 }
335 ast::TyInt(it) => {
336 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
337 Some(ty::mk_mach_int(it))
338 }
339 ast::TyUint(uit) => {
340 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
341 Some(ty::mk_mach_uint(uit))
342 }
343 ast::TyFloat(ft) => {
344 if ft == ast::TyF128 && !tcx.sess.features.quad_precision_float.get() {
345 tcx.sess.span_err(path.span, "quadruple precision floats are \
346 missing complete runtime support");
347 tcx.sess.span_note(path.span, "add \
348 #[feature(quad_precision_float)] \
349 to the crate attributes to enable");
350 }
351 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
352 Some(ty::mk_mach_float(ft))
353 }
354 ast::TyStr => {
355 tcx.sess.span_err(ast_ty.span,
356 "bare `str` is not a type");
357 // return /something/ so they can at least get more errors
358 Some(ty::mk_uniq(tcx, ty::mk_str(tcx)))
359 }
360 }
361 }
362 _ => None
363 }
364 }
365 _ => None
366 }
367 }
368
369 /// Converts the given AST type to a built-in type. A "built-in type" is, at
370 /// present, either a core numeric type, a string, or `Box`.
371 pub fn ast_ty_to_builtin_ty<AC:AstConv,
372 RS:RegionScope>(
373 this: &AC,
374 rscope: &RS,
375 ast_ty: &ast::Ty)
376 -> Option<ty::t> {
377 match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
378 Some(typ) => return Some(typ),
379 None => {}
380 }
381
382 match ast_ty.node {
383 ast::TyPath(ref path, _, id) => {
384 let a_def = match this.tcx().def_map.borrow().find(&id) {
385 None => this.tcx().sess.span_bug(
386 ast_ty.span, format!("unbound path {}", path_to_str(path))),
387 Some(&d) => d
388 };
389
390 // FIXME(#12938): This is a hack until we have full support for
391 // DST.
392 match a_def {
393 ast::DefTy(did) | ast::DefStruct(did)
394 if Some(did) == this.tcx().lang_items.owned_box() => {
395 if path.segments
396 .iter()
397 .flat_map(|s| s.types.iter())
398 .len() > 1 {
399 this.tcx()
400 .sess
401 .span_err(path.span,
402 "`Box` has only one type parameter")
403 }
404
405 for inner_ast_type in path.segments
406 .iter()
407 .flat_map(|s| s.types.iter()) {
408 let mt = ast::MutTy {
409 ty: *inner_ast_type,
410 mutbl: ast::MutImmutable,
411 };
412 return Some(mk_pointer(this,
413 rscope,
414 &mt,
415 Uniq,
416 |typ| {
417 match ty::get(typ).sty {
418 ty::ty_str => {
419 this.tcx()
420 .sess
421 .span_err(path.span,
422 "`Box<str>` is not a type");
423 ty::mk_err()
424 }
425 ty::ty_vec(_, None) => {
426 this.tcx()
427 .sess
428 .span_err(path.span,
429 "`Box<[T]>` is not a type");
430 ty::mk_err()
431 }
432 _ => ty::mk_uniq(this.tcx(), typ),
433 }
434 }))
435 }
436 this.tcx().sess.span_bug(path.span,
437 "not enough type parameters \
438 supplied to `Box<T>`")
439 }
440 _ => None
441 }
442 }
443 _ => None
444 }
445 }
446
447 enum PointerTy {
448 Box,
449 RPtr(ty::Region),
450 Uniq
451 }
452
453 fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
454 rscope: &RS,
455 ty: &ast::Ty) -> ty::mt {
456 ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
457 }
458
459 // Handle `~`, `Box`, and `&` being able to mean strs and vecs.
460 // If a_seq_ty is a str or a vec, make it a str/vec.
461 // Also handle first-class trait types.
462 fn mk_pointer<AC:AstConv,
463 RS:RegionScope>(
464 this: &AC,
465 rscope: &RS,
466 a_seq_ty: &ast::MutTy,
467 ptr_ty: PointerTy,
468 constr: |ty::t| -> ty::t)
469 -> ty::t {
470 let tcx = this.tcx();
471 debug!("mk_pointer(ptr_ty={:?})", ptr_ty);
472
473 match a_seq_ty.ty.node {
474 ast::TyVec(ty) => {
475 let mut mt = ast_ty_to_mt(this, rscope, ty);
476 if a_seq_ty.mutbl == ast::MutMutable {
477 mt.mutbl = ast::MutMutable;
478 }
479 return constr(ty::mk_vec(tcx, mt, None));
480 }
481 ast::TyPath(ref path, ref bounds, id) => {
482 // Note that the "bounds must be empty if path is not a trait"
483 // restriction is enforced in the below case for ty_path, which
484 // will run after this as long as the path isn't a trait.
485 match tcx.def_map.borrow().find(&id) {
486 Some(&ast::DefPrimTy(ast::TyStr)) => {
487 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
488 match ptr_ty {
489 Uniq => {
490 return constr(ty::mk_str(tcx));
491 }
492 RPtr(r) => {
493 return ty::mk_str_slice(tcx, r, ast::MutImmutable);
494 }
495 _ => tcx.sess.span_err(path.span,
496 format!("managed strings are not supported")),
497 }
498 }
499 Some(&ast::DefTrait(trait_def_id)) => {
500 let result = ast_path_to_trait_ref(
501 this, rscope, trait_def_id, None, path);
502 let trait_store = match ptr_ty {
503 Uniq => ty::UniqTraitStore,
504 RPtr(r) => {
505 ty::RegionTraitStore(r, a_seq_ty.mutbl)
506 }
507 _ => {
508 tcx.sess.span_err(
509 path.span,
510 "~trait or &trait are the only supported \
511 forms of casting-to-trait");
512 return ty::mk_err();
513 }
514 };
515 let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
516 return ty::mk_trait(tcx,
517 result.def_id,
518 result.substs.clone(),
519 trait_store,
520 bounds);
521 }
522 _ => {}
523 }
524 }
525 _ => {}
526 }
527
528 constr(ast_ty_to_ty(this, rscope, a_seq_ty.ty))
529 }
530
531 // Parses the programmer's textual representation of a type into our
532 // internal notion of a type.
533 pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
534 this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
535
536 let tcx = this.tcx();
537
538 let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
539 match ast_ty_to_ty_cache.find(&ast_ty.id) {
540 Some(&ty::atttce_resolved(ty)) => return ty,
541 Some(&ty::atttce_unresolved) => {
542 tcx.sess.span_fatal(ast_ty.span,
543 "illegal recursive type; insert an enum \
544 or struct in the cycle, if this is \
545 desired");
546 }
547 None => { /* go on */ }
548 }
549 ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
550 drop(ast_ty_to_ty_cache);
551
552 let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
553 match ast_ty.node {
554 ast::TyNil => ty::mk_nil(),
555 ast::TyBot => ty::mk_bot(),
556 ast::TyBox(ty) => {
557 let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
558 mk_pointer(this, rscope, &mt, Box, |ty| ty::mk_box(tcx, ty))
559 }
560 ast::TyUniq(ty) => {
561 let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
562 mk_pointer(this, rscope, &mt, Uniq,
563 |ty| ty::mk_uniq(tcx, ty))
564 }
565 ast::TyVec(ty) => {
566 tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
567 // return /something/ so they can at least get more errors
568 let vec_ty = ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), None);
569 ty::mk_uniq(tcx, vec_ty)
570 }
571 ast::TyPtr(ref mt) => {
572 ty::mk_ptr(tcx, ty::mt {
573 ty: ast_ty_to_ty(this, rscope, mt.ty),
574 mutbl: mt.mutbl
575 })
576 }
577 ast::TyRptr(ref region, ref mt) => {
578 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
579 debug!("ty_rptr r={}", r.repr(this.tcx()));
580 mk_pointer(this, rscope, mt, RPtr(r),
581 |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
582 }
583 ast::TyTup(ref fields) => {
584 let flds = fields.iter()
585 .map(|&t| ast_ty_to_ty(this, rscope, t))
586 .collect();
587 ty::mk_tup(tcx, flds)
588 }
589 ast::TyBareFn(ref bf) => {
590 if bf.decl.variadic && bf.abi != abi::C {
591 tcx.sess.span_err(ast_ty.span,
592 "variadic function must have C calling convention");
593 }
594 ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style,
595 bf.abi, bf.decl))
596 }
597 ast::TyClosure(ref f, ref region) => {
598
599 // resolve the function bound region in the original region
600 // scope `rscope`, not the scope of the function parameters
601 let bound_region = opt_ast_region_to_region(this, rscope,
602 ast_ty.span, region);
603
604 let store = ty::RegionTraitStore(bound_region, ast::MutMutable);
605
606 // Use corresponding trait store to figure out default bounds
607 // if none were specified.
608 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, store);
609
610 let fn_decl = ty_of_closure(this,
611 ast_ty.id,
612 f.fn_style,
613 f.onceness,
614 bounds,
615 store,
616 f.decl,
617 None);
618 ty::mk_closure(tcx, fn_decl)
619 }
620 ast::TyProc(ref f) => {
621 // Use corresponding trait store to figure out default bounds
622 // if none were specified.
623 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, ty::UniqTraitStore);
624
625 let fn_decl = ty_of_closure(this,
626 ast_ty.id,
627 f.fn_style,
628 f.onceness,
629 bounds,
630 ty::UniqTraitStore,
631 f.decl,
632 None);
633 ty::mk_closure(tcx, fn_decl)
634 }
635 ast::TyPath(ref path, ref bounds, id) => {
636 let a_def = match tcx.def_map.borrow().find(&id) {
637 None => tcx.sess.span_bug(
638 ast_ty.span, format!("unbound path {}", path_to_str(path))),
639 Some(&d) => d
640 };
641 // Kind bounds on path types are only supported for traits.
642 match a_def {
643 // But don't emit the error if the user meant to do a trait anyway.
644 ast::DefTrait(..) => { },
645 _ if bounds.is_some() =>
646 tcx.sess.span_err(ast_ty.span,
647 "kind bounds can only be used on trait types"),
648 _ => { },
649 }
650 match a_def {
651 ast::DefTrait(_) => {
652 let path_str = path_to_str(path);
653 tcx.sess.span_err(
654 ast_ty.span,
655 format!("reference to trait `{name}` where a type is expected; \
656 try `~{name}` or `&{name}`", name=path_str));
657 ty::mk_err()
658 }
659 ast::DefTy(did) | ast::DefStruct(did) => {
660 ast_path_to_ty(this, rscope, did, path).ty
661 }
662 ast::DefTyParam(id, n) => {
663 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
664 ty::mk_param(tcx, n, id)
665 }
666 ast::DefSelfTy(id) => {
667 // n.b.: resolve guarantees that the this type only appears in a
668 // trait, which we rely upon in various places when creating
669 // substs
670 check_path_args(tcx, path, NO_TPS | NO_REGIONS);
671 let did = ast_util::local_def(id);
672 ty::mk_self(tcx, did)
673 }
674 ast::DefMod(id) => {
675 tcx.sess.span_fatal(ast_ty.span,
676 format!("found module name used as a type: {}",
677 tcx.map.node_to_str(id.node)));
678 }
679 ast::DefPrimTy(_) => {
680 fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
681 }
682 _ => {
683 tcx.sess.span_fatal(ast_ty.span,
684 format!("found value name used as a type: {:?}", a_def));
685 }
686 }
687 }
688 ast::TyFixedLengthVec(ty, e) => {
689 match const_eval::eval_const_expr_partial(tcx, e) {
690 Ok(ref r) => {
691 match *r {
692 const_eval::const_int(i) =>
693 ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
694 Some(i as uint)),
695 const_eval::const_uint(i) =>
696 ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
697 Some(i as uint)),
698 _ => {
699 tcx.sess.span_fatal(
700 ast_ty.span, "expected constant expr for vector length");
701 }
702 }
703 }
704 Err(ref r) => {
705 tcx.sess.span_fatal(
706 ast_ty.span,
707 format!("expected constant expr for vector length: {}", *r));
708 }
709 }
710 }
711 ast::TyTypeof(_e) => {
712 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
713 }
714 ast::TyInfer => {
715 // TyInfer also appears as the type of arguments or return
716 // values in a ExprFnBlock or ExprProc, or as the type of
717 // local variables. Both of these cases are handled specially
718 // and will not descend into this routine.
719 this.ty_infer(ast_ty.span)
720 }
721 }
722 });
723
724 tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
725 return typ;
726 }
727
728 pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::Arg,
729 expected_ty: Option<ty::t>) -> ty::t {
730 match a.ty.node {
731 ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
732 ast::TyInfer => this.ty_infer(a.ty.span),
733 _ => ast_ty_to_ty(this, rscope, a.ty),
734 }
735 }
736
737 struct SelfInfo {
738 untransformed_self_ty: ty::t,
739 explicit_self: ast::ExplicitSelf
740 }
741
742 pub fn ty_of_method<AC:AstConv>(
743 this: &AC,
744 id: ast::NodeId,
745 fn_style: ast::FnStyle,
746 untransformed_self_ty: ty::t,
747 explicit_self: ast::ExplicitSelf,
748 decl: &ast::FnDecl) -> ty::BareFnTy {
749 ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
750 untransformed_self_ty: untransformed_self_ty,
751 explicit_self: explicit_self
752 }), decl)
753 }
754
755 pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
756 fn_style: ast::FnStyle, abi: abi::Abi,
757 decl: &ast::FnDecl) -> ty::BareFnTy {
758 ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl)
759 }
760
761 fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
762 fn_style: ast::FnStyle, abi: abi::Abi,
763 opt_self_info: Option<SelfInfo>,
764 decl: &ast::FnDecl) -> ty::BareFnTy {
765 debug!("ty_of_method_or_bare_fn");
766
767 // new region names that appear inside of the fn decl are bound to
768 // that function type
769 let rb = rscope::BindingRscope::new(id);
770
771 let self_ty = opt_self_info.and_then(|self_info| {
772 match self_info.explicit_self.node {
773 ast::SelfStatic => None,
774 ast::SelfValue => {
775 Some(self_info.untransformed_self_ty)
776 }
777 ast::SelfRegion(ref lifetime, mutability) => {
778 let region =
779 opt_ast_region_to_region(this, &rb,
780 self_info.explicit_self.span,
781 lifetime);
782 Some(ty::mk_rptr(this.tcx(), region,
783 ty::mt {ty: self_info.untransformed_self_ty,
784 mutbl: mutability}))
785 }
786 ast::SelfUniq => {
787 Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
788 }
789 }
790 });
791
792 // HACK(eddyb) replace the fake self type in the AST with the actual type.
793 let input_tys = if self_ty.is_some() {
794 decl.inputs.slice_from(1)
795 } else {
796 decl.inputs.as_slice()
797 };
798 let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
799
800 let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
801
802 let output_ty = match decl.output.node {
803 ast::TyInfer => this.ty_infer(decl.output.span),
804 _ => ast_ty_to_ty(this, &rb, decl.output)
805 };
806
807 return ty::BareFnTy {
808 fn_style: fn_style,
809 abi: abi,
810 sig: ty::FnSig {
811 binder_id: id,
812 inputs: self_and_input_tys,
813 output: output_ty,
814 variadic: decl.variadic
815 }
816 };
817 }
818
819 pub fn ty_of_closure<AC:AstConv>(
820 this: &AC,
821 id: ast::NodeId,
822 fn_style: ast::FnStyle,
823 onceness: ast::Onceness,
824 bounds: ty::BuiltinBounds,
825 store: ty::TraitStore,
826 decl: &ast::FnDecl,
827 expected_sig: Option<ty::FnSig>)
828 -> ty::ClosureTy
829 {
830 debug!("ty_of_fn_decl");
831
832 // new region names that appear inside of the fn decl are bound to
833 // that function type
834 let rb = rscope::BindingRscope::new(id);
835
836 let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| {
837 let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
838 // no guarantee that the correct number of expected args
839 // were supplied
840 if i < e.inputs.len() {
841 Some(*e.inputs.get(i))
842 } else {
843 None
844 }
845 });
846 ty_of_arg(this, &rb, a, expected_arg_ty)
847 }).collect();
848
849 let expected_ret_ty = expected_sig.map(|e| e.output);
850 let output_ty = match decl.output.node {
851 ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
852 ast::TyInfer => this.ty_infer(decl.output.span),
853 _ => ast_ty_to_ty(this, &rb, decl.output)
854 };
855
856 ty::ClosureTy {
857 fn_style: fn_style,
858 onceness: onceness,
859 store: store,
860 bounds: bounds,
861 sig: ty::FnSig {binder_id: id,
862 inputs: input_tys,
863 output: output_ty,
864 variadic: decl.variadic}
865 }
866 }
867
868 fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
869 store: ty::TraitStore)
870 -> ty::BuiltinBounds {
871 //! Converts a list of bounds from the AST into a `BuiltinBounds`
872 //! struct. Reports an error if any of the bounds that appear
873 //! in the AST refer to general traits and not the built-in traits
874 //! like `Send`. Used to translate the bounds that
875 //! appear in closure and trait types, where only builtin bounds are
876 //! legal.
877 //! If no bounds were specified, we choose a "default" bound based on
878 //! the allocation type of the fn/trait, as per issue #7264. The user can
879 //! override this with an empty bounds list, e.g. "Box<fn:()>" or
880 //! "Box<Trait:>".
881
882 match (ast_bounds, store) {
883 (&Some(ref bound_vec), _) => {
884 let mut builtin_bounds = ty::EmptyBuiltinBounds();
885 for ast_bound in bound_vec.iter() {
886 match *ast_bound {
887 ast::TraitTyParamBound(ref b) => {
888 match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
889 ast::DefTrait(trait_did) => {
890 if ty::try_add_builtin_trait(tcx, trait_did,
891 &mut builtin_bounds) {
892 continue; // success
893 }
894 }
895 _ => { }
896 }
897 tcx.sess.span_fatal(
898 b.path.span,
899 format!("only the builtin traits can be used \
900 as closure or object bounds"));
901 }
902 ast::StaticRegionTyParamBound => {
903 builtin_bounds.add(ty::BoundStatic);
904 }
905 ast::OtherRegionTyParamBound(span) => {
906 if !tcx.sess.features.issue_5723_bootstrap.get() {
907 tcx.sess.span_err(
908 span,
909 format!("only the 'static lifetime is \
910 accepted here."));
911 }
912 }
913 }
914 }
915 builtin_bounds
916 },
917 // &'static Trait is sugar for &'static Trait:'static.
918 (&None, ty::RegionTraitStore(ty::ReStatic, _)) => {
919 let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
920 }
921 // No bounds are automatically applied for &'r Trait or ~Trait
922 (&None, ty::RegionTraitStore(..)) |
923 (&None, ty::UniqTraitStore) => ty::EmptyBuiltinBounds(),
924 }
925 }
librustc/middle/typeck/astconv.rs:736:1-736:1 -struct- definition:
struct SelfInfo {
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf
references:- 2748: decl: &ast::FnDecl) -> ty::BareFnTy {
749: ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
750: untransformed_self_ty: untransformed_self_ty,
--
762: fn_style: ast::FnStyle, abi: abi::Abi,
763: opt_self_info: Option<SelfInfo>,
764: decl: &ast::FnDecl) -> ty::BareFnTy {
librustc/middle/typeck/astconv.rs:263:1-263:1 -fn- definition:
pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
references:- 2librustc/middle/typeck/collect.rs:
829: let trait_ref =
830: astconv::ast_path_to_trait_ref(
831: ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
librustc/middle/typeck/astconv.rs:
499: Some(&ast::DefTrait(trait_def_id)) => {
500: let result = ast_path_to_trait_ref(
501: this, rscope, trait_def_id, None, path);
librustc/middle/typeck/astconv.rs:818:1-818:1 -fn- definition:
pub fn ty_of_closure<AC:AstConv>(
this: &AC,
id: ast::NodeId,
references:- 3625: let fn_decl = ty_of_closure(this,
626: ast_ty.id,
librustc/middle/typeck/check/mod.rs:
2316: // construct the function type
2317: let fn_ty = astconv::ty_of_closure(fcx,
2318: expr.id,
librustc/middle/typeck/astconv.rs:461:40-461:40 -fn- definition:
// Also handle first-class trait types.
fn mk_pointer<AC:AstConv,
RS:RegionScope>(
references:- 4561: let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
562: mk_pointer(this, rscope, &mt, Uniq,
563: |ty| ty::mk_uniq(tcx, ty))
--
579: debug!("ty_rptr r={}", r.repr(this.tcx()));
580: mk_pointer(this, rscope, mt, RPtr(r),
581: |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
librustc/middle/typeck/astconv.rs:78:1-78:1 -fn- definition:
pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
-> ty::Region {
let r = match tcx.named_region_map.find(&lifetime.id) {
references:- 3123: Some(ref lifetime) => {
124: ast_region_to_region(this.tcx(), lifetime)
125: }
--
171: path.segments.last().unwrap().lifetimes.iter().map(
172: |l| ast_region_to_region(this.tcx(), l)).collect::<Vec<_>>()
173: } else {
librustc/middle/typeck/check/mod.rs:
3832: OwnedSlice::from_vec(pth.segments.last().unwrap().lifetimes.iter().map(
3833: |l| ast_region_to_region(fcx.tcx(), l)).collect())
3834: } else {
librustc/middle/typeck/astconv.rs:727:1-727:1 -fn- definition:
pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::Arg,
expected_ty: Option<ty::t>) -> ty::t {
match a.ty.node {
references:- 3797: };
798: let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
librustc/middle/typeck/collect.rs:
1180: .iter()
1181: .map(|a| ty_of_arg(ccx, &rb, a, None))
1182: .collect();
librustc/middle/typeck/astconv.rs:
845: });
846: ty_of_arg(this, &rb, a, expected_arg_ty)
847: }).collect();
librustc/middle/typeck/astconv.rs:149:1-149:1 -fn- definition:
fn ast_path_substs<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
references:- 2259: let substs = ast_path_substs(this, rscope, &generics, None, path);
260: let ty = ty::subst(tcx, &substs, decl_ty);
--
272: def_id: trait_def_id,
273: substs: ast_path_substs(this, rscope, &trait_def.generics, self_ty, path)
274: })
librustc/middle/typeck/astconv.rs:295:1-295:1 -fn- definition:
fn check_path_args(tcx: &ty::ctxt,
path: &ast::Path,
flags: uint) {
references:- 8662: ast::DefTyParam(id, n) => {
663: check_path_args(tcx, path, NO_TPS | NO_REGIONS);
664: ty::mk_param(tcx, n, id)
--
669: // substs
670: check_path_args(tcx, path, NO_TPS | NO_REGIONS);
671: let did = ast_util::local_def(id);
librustc/middle/typeck/astconv.rs:315:1-315:1 -fn- definition:
pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
match ast_ty.node {
ast::TyPath(ref path, _, id) => {
references:- 2376: -> Option<ty::t> {
377: match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
378: Some(typ) => return Some(typ),
librustc/middle/const_eval.rs:
421: let ety = ty::expr_ty_opt(tcx.ty_ctxt(), e)
422: .or_else(|| astconv::ast_ty_to_prim_ty(tcx.ty_ctxt(), target_ty))
423: .unwrap_or_else(|| tcx.ty_ctxt().sess.span_fatal(
librustc/middle/typeck/astconv.rs:754:1-754:1 -fn- definition:
pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
fn_style: ast::FnStyle, abi: abi::Abi,
decl: &ast::FnDecl) -> ty::BareFnTy {
references:- 2593: }
594: ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style,
595: bf.abi, bf.decl))
librustc/middle/typeck/collect.rs:
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,
librustc/middle/typeck/astconv.rs:532:30-532:30 -fn- definition:
// internal notion of a type.
pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
references:- 14528: constr(ast_ty_to_ty(this, rscope, a_seq_ty.ty))
529: }
--
803: ast::TyInfer => this.ty_infer(decl.output.span),
804: _ => ast_ty_to_ty(this, &rb, decl.output)
805: };
librustc/middle/typeck/collect.rs:
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: }
--
1184: let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
librustc/middle/lint.rs:
702: ast::ExprCast(expr, ty) => {
703: let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), ty);
704: if ty::get(ty::expr_ty(cx.tcx, expr)).sty == ty::get(t_t).sty {
librustc/middle/typeck/check/mod.rs:
1163: pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1164: ast_ty_to_ty(self, self.infcx(), ast_t)
1165: }
librustc/middle/typeck/astconv.rs:
852: ast::TyInfer => this.ty_infer(decl.output.span),
853: _ => ast_ty_to_ty(this, &rb, decl.output)
854: };
librustc/middle/typeck/astconv.rs:452:1-452:1 -fn- definition:
fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
rscope: &RS,
ty: &ast::Ty) -> ty::mt {
references:- 4692: const_eval::const_int(i) =>
693: ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
694: Some(i as uint)),
695: const_eval::const_uint(i) =>
696: ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
697: Some(i as uint)),
librustc/middle/typeck/astconv.rs:867:1-867:1 -fn- definition:
fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
store: ty::TraitStore)
-> ty::BuiltinBounds {
references:- 3607: // if none were specified.
608: let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, store);
--
622: // if none were specified.
623: let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, ty::UniqTraitStore);
librustc/middle/typeck/astconv.rs:69:1-69:1 -trait- definition:
pub trait AstConv {
fn tcx<'a>(&'a self) -> &'a ty::ctxt;
fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
references:- 17819: pub fn ty_of_closure<AC:AstConv>(
820: this: &AC,
librustc/middle/typeck/collect.rs:
110: impl<'a> AstConv for CrateCtxt<'a> {
111: fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
librustc/middle/lint.rs:
682: }
683: impl<'a> AstConv for Context<'a>{
684: fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
librustc/middle/typeck/check/mod.rs:
1049: impl<'a> AstConv for FnCtxt<'a> {
1050: fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
librustc/middle/typeck/astconv.rs:
453: fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
454: rscope: &RS,
librustc/middle/typeck/astconv.rs:760:1-760:1 -fn- definition:
fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
fn_style: ast::FnStyle, abi: abi::Abi,
opt_self_info: Option<SelfInfo>,
references:- 2748: decl: &ast::FnDecl) -> ty::BareFnTy {
749: ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
750: untransformed_self_ty: untransformed_self_ty,
--
757: decl: &ast::FnDecl) -> ty::BareFnTy {
758: ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl)
759: }
librustc/middle/typeck/astconv.rs:741:1-741:1 -fn- definition:
pub fn ty_of_method<AC:AstConv>(
this: &AC,
id: ast::NodeId,
references:- 2librustc/middle/typeck/collect.rs:
539: {
540: let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
541: untransformed_rcvr_ty,
librustc/middle/typeck/astconv.rs:115:1-115:1 -fn- definition:
pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
references:- 4600: // scope `rscope`, not the scope of the function parameters
601: let bound_region = opt_ast_region_to_region(this, rscope,
602: ast_ty.span, region);
--
778: let region =
779: opt_ast_region_to_region(this, &rb,
780: self_info.explicit_self.span,
librustc/middle/typeck/check/mod.rs:
2992: ast::ExprFnBlock(decl, body) => {
2993: let region = astconv::opt_ast_region_to_region(fcx,
2994: fcx.infcx(),
librustc/middle/typeck/astconv.rs:
577: ast::TyRptr(ref region, ref mt) => {
578: let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
579: debug!("ty_rptr r={}", r.repr(this.tcx()));