]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/astconv.rs
auto merge of #13967 : richo/rust/features/ICE-fails, r=alexcrichton
[rust.git] / src / librustc / middle / typeck / astconv.rs
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 }