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