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