]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/astconv.rs
auto merge of #13424 : eddyb/rust/ty-mut-in-store, r=nikomatsakis
[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;
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.iter().map(
171             |l| ast_region_to_region(this.tcx(), l)).collect::<Vec<_>>()
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::VstoreUniq))
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     enum PointerTy {
376         Box,
377         VStore(ty::Vstore)
378     }
379     impl PointerTy {
380         fn expect_vstore(&self, tcx: &ty::ctxt, span: Span, ty: &str) -> ty::Vstore {
381             match *self {
382                 Box => {
383                     tcx.sess.span_err(span, format!("managed {} are not supported", ty));
384                     // everything can be ~, so this is a worth substitute
385                     ty::VstoreUniq
386                 }
387                 VStore(vst) => vst
388             }
389         }
390     }
391
392     // Handle ~, and & being able to mean strs and vecs.
393     // If a_seq_ty is a str or a vec, make it a str/vec.
394     // Also handle first-class trait types.
395     fn mk_pointer<AC:AstConv,
396                   RS:RegionScope>(
397                   this: &AC,
398                   rscope: &RS,
399                   a_seq_ty: &ast::Ty,
400                   ptr_ty: PointerTy,
401                   constr: |ty::t| -> ty::t)
402                   -> ty::t {
403         let tcx = this.tcx();
404         debug!("mk_pointer(ptr_ty={:?})", ptr_ty);
405
406         match a_seq_ty.node {
407             ast::TyVec(ty) => {
408                 let vst = ptr_ty.expect_vstore(tcx, a_seq_ty.span, "vectors");
409                 debug!("&[]: vst={:?}", vst);
410                 return ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty), vst);
411             }
412             ast::TyPath(ref path, ref bounds, id) => {
413                 // Note that the "bounds must be empty if path is not a trait"
414                 // restriction is enforced in the below case for ty_path, which
415                 // will run after this as long as the path isn't a trait.
416                 match tcx.def_map.borrow().find(&id) {
417                     Some(&ast::DefPrimTy(ast::TyStr)) => {
418                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
419                         let vst = ptr_ty.expect_vstore(tcx, path.span, "strings");
420                         match vst {
421                             ty::VstoreUniq => {
422                                 return ty::mk_str(tcx, ty::VstoreUniq);
423                             }
424                             ty::VstoreSlice(r, ast::MutImmutable) => {
425                                 return ty::mk_str(tcx, ty::VstoreSlice(r, ()));
426                             }
427                             _ => {}
428                         }
429                     }
430                     Some(&ast::DefTrait(trait_def_id)) => {
431                         let result = ast_path_to_trait_ref(
432                             this, rscope, trait_def_id, None, path);
433                         let trait_store = match ptr_ty {
434                             VStore(ty::VstoreUniq) => ty::UniqTraitStore,
435                             VStore(ty::VstoreSlice(r, m)) => {
436                                 ty::RegionTraitStore(r, m)
437                             }
438                             _ => {
439                                 tcx.sess.span_err(
440                                     path.span,
441                                     "~trait or &trait are the only supported \
442                                      forms of casting-to-trait");
443                                 return ty::mk_err();
444                             }
445                         };
446                         let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
447                         return ty::mk_trait(tcx,
448                                             result.def_id,
449                                             result.substs.clone(),
450                                             trait_store,
451                                             bounds);
452                     }
453                     _ => {}
454                 }
455             }
456             _ => {}
457         }
458
459         constr(ast_ty_to_ty(this, rscope, a_seq_ty))
460     }
461
462     let tcx = this.tcx();
463
464     let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
465     match ast_ty_to_ty_cache.find(&ast_ty.id) {
466         Some(&ty::atttce_resolved(ty)) => return ty,
467         Some(&ty::atttce_unresolved) => {
468             tcx.sess.span_fatal(ast_ty.span,
469                                 "illegal recursive type; insert an enum \
470                                  or struct in the cycle, if this is \
471                                  desired");
472         }
473         None => { /* go on */ }
474     }
475     ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
476     drop(ast_ty_to_ty_cache);
477
478     let typ = ast_ty_to_prim_ty(tcx, ast_ty).unwrap_or_else(|| match ast_ty.node {
479             ast::TyNil => ty::mk_nil(),
480             ast::TyBot => ty::mk_bot(),
481             ast::TyBox(ty) => {
482                 mk_pointer(this, rscope, ty, Box, |ty| ty::mk_box(tcx, ty))
483             }
484             ast::TyUniq(ty) => {
485                 mk_pointer(this, rscope, ty, VStore(ty::VstoreUniq),
486                            |ty| ty::mk_uniq(tcx, ty))
487             }
488             ast::TyVec(ty) => {
489                 tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
490                 // return /something/ so they can at least get more errors
491                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty), ty::VstoreUniq)
492             }
493             ast::TyPtr(ref mt) => {
494                 ty::mk_ptr(tcx, ty::mt {
495                     ty: ast_ty_to_ty(this, rscope, mt.ty),
496                     mutbl: mt.mutbl
497                 })
498             }
499             ast::TyRptr(ref region, ref mt) => {
500                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
501                 debug!("ty_rptr r={}", r.repr(this.tcx()));
502                 mk_pointer(this, rscope, &*mt.ty, VStore(ty::VstoreSlice(r, mt.mutbl)),
503                            |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
504             }
505             ast::TyTup(ref fields) => {
506                 let flds = fields.iter()
507                                  .map(|&t| ast_ty_to_ty(this, rscope, t))
508                                  .collect();
509                 ty::mk_tup(tcx, flds)
510             }
511             ast::TyBareFn(ref bf) => {
512                 if bf.decl.variadic && bf.abi != abi::C {
513                     tcx.sess.span_err(ast_ty.span,
514                                       "variadic function must have C calling convention");
515                 }
516                 ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style,
517                                                   bf.abi, bf.decl))
518             }
519             ast::TyClosure(ref f) => {
520                 if f.sigil == ast::ManagedSigil {
521                     tcx.sess.span_err(ast_ty.span,
522                                       "managed closures are not supported");
523                 }
524
525                 let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
526                         // Use corresponding trait store to figure out default bounds
527                         // if none were specified.
528                         ast::BorrowedSigil => {
529                             // dummy region
530                             ty::RegionTraitStore(ty::ReEmpty, ast::MutMutable)
531                         }
532                         ast::OwnedSigil    => ty::UniqTraitStore,
533                         ast::ManagedSigil  => return ty::mk_err()
534                     });
535                 let fn_decl = ty_of_closure(this,
536                                             rscope,
537                                             ast_ty.id,
538                                             f.sigil,
539                                             f.fn_style,
540                                             f.onceness,
541                                             bounds,
542                                             &f.region,
543                                             f.decl,
544                                             None,
545                                             ast_ty.span);
546                 ty::mk_closure(tcx, fn_decl)
547             }
548             ast::TyPath(ref path, ref bounds, id) => {
549                 let a_def = match tcx.def_map.borrow().find(&id) {
550                     None => tcx.sess.span_fatal(
551                         ast_ty.span, format!("unbound path {}", path_to_str(path))),
552                     Some(&d) => d
553                 };
554                 // Kind bounds on path types are only supported for traits.
555                 match a_def {
556                     // But don't emit the error if the user meant to do a trait anyway.
557                     ast::DefTrait(..) => { },
558                     _ if bounds.is_some() =>
559                         tcx.sess.span_err(ast_ty.span,
560                                           "kind bounds can only be used on trait types"),
561                     _ => { },
562                 }
563                 match a_def {
564                     ast::DefTrait(_) => {
565                         let path_str = path_to_str(path);
566                         tcx.sess.span_err(
567                             ast_ty.span,
568                             format!("reference to trait `{name}` where a type is expected; \
569                                     try `~{name}` or `&{name}`", name=path_str));
570                         ty::mk_err()
571                     }
572                     ast::DefTy(did) | ast::DefStruct(did) => {
573                         ast_path_to_ty(this, rscope, did, path).ty
574                     }
575                     ast::DefTyParam(id, n) => {
576                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
577                         ty::mk_param(tcx, n, id)
578                     }
579                     ast::DefSelfTy(id) => {
580                         // n.b.: resolve guarantees that the this type only appears in a
581                         // trait, which we rely upon in various places when creating
582                         // substs
583                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
584                         let did = ast_util::local_def(id);
585                         ty::mk_self(tcx, did)
586                     }
587                     ast::DefMod(id) => {
588                         tcx.sess.span_fatal(ast_ty.span,
589                             format!("found module name used as a type: {}",
590                                     tcx.map.node_to_str(id.node)));
591                     }
592                     ast::DefPrimTy(_) => {
593                         fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
594                     }
595                     _ => {
596                         tcx.sess.span_fatal(ast_ty.span,
597                             format!("found value name used as a type: {:?}", a_def));
598                     }
599                 }
600             }
601             ast::TyFixedLengthVec(ty, e) => {
602                 match const_eval::eval_const_expr_partial(tcx, e) {
603                     Ok(ref r) => {
604                         match *r {
605                             const_eval::const_int(i) =>
606                                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty),
607                                            ty::VstoreFixed(i as uint)),
608                             const_eval::const_uint(i) =>
609                                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty),
610                                            ty::VstoreFixed(i as uint)),
611                             _ => {
612                                 tcx.sess.span_fatal(
613                                     ast_ty.span, "expected constant expr for vector length");
614                             }
615                         }
616                     }
617                     Err(ref r) => {
618                         tcx.sess.span_fatal(
619                             ast_ty.span,
620                             format!("expected constant expr for vector length: {}", *r));
621                     }
622                 }
623             }
624             ast::TyTypeof(_e) => {
625                 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
626             }
627             ast::TyInfer => {
628                 // TyInfer also appears as the type of arguments or return
629                 // values in a ExprFnBlock or ExprProc, or as the type of
630                 // local variables. Both of these cases are handled specially
631                 // and will not descend into this routine.
632                 this.ty_infer(ast_ty.span)
633             }
634         });
635
636     tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
637     return typ;
638 }
639
640 pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::Arg,
641                                                expected_ty: Option<ty::t>) -> ty::t {
642     match a.ty.node {
643         ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
644         ast::TyInfer => this.ty_infer(a.ty.span),
645         _ => ast_ty_to_ty(this, rscope, a.ty),
646     }
647 }
648
649 struct SelfInfo {
650     untransformed_self_ty: ty::t,
651     explicit_self: ast::ExplicitSelf
652 }
653
654 pub fn ty_of_method<AC:AstConv>(
655     this: &AC,
656     id: ast::NodeId,
657     fn_style: ast::FnStyle,
658     untransformed_self_ty: ty::t,
659     explicit_self: ast::ExplicitSelf,
660     decl: &ast::FnDecl) -> ty::BareFnTy {
661     ty_of_method_or_bare_fn(this, id, fn_style, abi::Rust, Some(SelfInfo {
662         untransformed_self_ty: untransformed_self_ty,
663         explicit_self: explicit_self
664     }), decl)
665 }
666
667 pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
668                                  fn_style: ast::FnStyle, abi: abi::Abi,
669                                  decl: &ast::FnDecl) -> ty::BareFnTy {
670     ty_of_method_or_bare_fn(this, id, fn_style, abi, None, decl)
671 }
672
673 fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
674                                        fn_style: ast::FnStyle, abi: abi::Abi,
675                                        opt_self_info: Option<SelfInfo>,
676                                        decl: &ast::FnDecl) -> ty::BareFnTy {
677     debug!("ty_of_method_or_bare_fn");
678
679     // new region names that appear inside of the fn decl are bound to
680     // that function type
681     let rb = rscope::BindingRscope::new(id);
682
683     let self_ty = opt_self_info.and_then(|self_info| {
684         match self_info.explicit_self.node {
685             ast::SelfStatic => None,
686             ast::SelfValue => {
687                 Some(self_info.untransformed_self_ty)
688             }
689             ast::SelfRegion(ref lifetime, mutability) => {
690                 let region =
691                     opt_ast_region_to_region(this, &rb,
692                                              self_info.explicit_self.span,
693                                              lifetime);
694                 Some(ty::mk_rptr(this.tcx(), region,
695                                  ty::mt {ty: self_info.untransformed_self_ty,
696                                          mutbl: mutability}))
697             }
698             ast::SelfUniq => {
699                 Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
700             }
701         }
702     });
703
704     // HACK(eddyb) replace the fake self type in the AST with the actual type.
705     let input_tys = if self_ty.is_some() {
706         decl.inputs.slice_from(1)
707     } else {
708         decl.inputs.as_slice()
709     };
710     let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
711
712     let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
713
714     let output_ty = match decl.output.node {
715         ast::TyInfer => this.ty_infer(decl.output.span),
716         _ => ast_ty_to_ty(this, &rb, decl.output)
717     };
718
719     return ty::BareFnTy {
720         fn_style: fn_style,
721         abi: abi,
722         sig: ty::FnSig {
723             binder_id: id,
724             inputs: self_and_input_tys,
725             output: output_ty,
726             variadic: decl.variadic
727         }
728     };
729 }
730
731 pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
732     this: &AC,
733     rscope: &RS,
734     id: ast::NodeId,
735     sigil: ast::Sigil,
736     fn_style: ast::FnStyle,
737     onceness: ast::Onceness,
738     bounds: ty::BuiltinBounds,
739     opt_lifetime: &Option<ast::Lifetime>,
740     decl: &ast::FnDecl,
741     expected_sig: Option<ty::FnSig>,
742     span: Span)
743     -> ty::ClosureTy
744 {
745     debug!("ty_of_fn_decl");
746
747     // resolve the function bound region in the original region
748     // scope `rscope`, not the scope of the function parameters
749     let bound_region = match opt_lifetime {
750         &Some(ref lifetime) => {
751             ast_region_to_region(this.tcx(), lifetime)
752         }
753         &None => {
754             match sigil {
755                 ast::OwnedSigil | ast::ManagedSigil => {
756                     // @fn(), ~fn() default to static as the bound
757                     // on their upvars:
758                     ty::ReStatic
759                 }
760                 ast::BorrowedSigil => {
761                     // || defaults as normal for an omitted lifetime:
762                     opt_ast_region_to_region(this, rscope, span, opt_lifetime)
763                 }
764             }
765         }
766     };
767
768     // new region names that appear inside of the fn decl are bound to
769     // that function type
770     let rb = rscope::BindingRscope::new(id);
771
772     let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| {
773         let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
774             // no guarantee that the correct number of expected args
775             // were supplied
776             if i < e.inputs.len() {
777                 Some(*e.inputs.get(i))
778             } else {
779                 None
780             }
781         });
782         ty_of_arg(this, &rb, a, expected_arg_ty)
783     }).collect();
784
785     let expected_ret_ty = expected_sig.map(|e| e.output);
786     let output_ty = match decl.output.node {
787         ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
788         ast::TyInfer => this.ty_infer(decl.output.span),
789         _ => ast_ty_to_ty(this, &rb, decl.output)
790     };
791
792     ty::ClosureTy {
793         fn_style: fn_style,
794         sigil: sigil,
795         onceness: onceness,
796         region: bound_region,
797         bounds: bounds,
798         sig: ty::FnSig {binder_id: id,
799                         inputs: input_tys,
800                         output: output_ty,
801                         variadic: decl.variadic}
802     }
803 }
804
805 fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
806                        store: ty::TraitStore)
807                        -> ty::BuiltinBounds {
808     //! Converts a list of bounds from the AST into a `BuiltinBounds`
809     //! struct. Reports an error if any of the bounds that appear
810     //! in the AST refer to general traits and not the built-in traits
811     //! like `Send`. Used to translate the bounds that
812     //! appear in closure and trait types, where only builtin bounds are
813     //! legal.
814     //! If no bounds were specified, we choose a "default" bound based on
815     //! the allocation type of the fn/trait, as per issue #7264. The user can
816     //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
817
818     match (ast_bounds, store) {
819         (&Some(ref bound_vec), _) => {
820             let mut builtin_bounds = ty::EmptyBuiltinBounds();
821             for ast_bound in bound_vec.iter() {
822                 match *ast_bound {
823                     ast::TraitTyParamBound(ref b) => {
824                         match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
825                             ast::DefTrait(trait_did) => {
826                                 if ty::try_add_builtin_trait(tcx, trait_did,
827                                                              &mut builtin_bounds) {
828                                     continue; // success
829                                 }
830                             }
831                             _ => { }
832                         }
833                         tcx.sess.span_fatal(
834                             b.path.span,
835                             format!("only the builtin traits can be used \
836                                   as closure or object bounds"));
837                     }
838                     ast::RegionTyParamBound => {
839                         builtin_bounds.add(ty::BoundStatic);
840                     }
841                 }
842             }
843             builtin_bounds
844         },
845         // &'static Trait is sugar for &'static Trait:'static.
846         (&None, ty::RegionTraitStore(ty::ReStatic, _)) => {
847             let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundStatic); set
848         }
849         // No bounds are automatically applied for &'r Trait or ~Trait
850         (&None, ty::RegionTraitStore(..)) |
851         (&None, ty::UniqTraitStore) => ty::EmptyBuiltinBounds(),
852     }
853 }