]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/astconv.rs
rollup merge of #20263: crhino/lifetime-elision-help
[rust.git] / src / librustc_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 //! Conversion from AST representation of types to the ty.rs
12 //! representation.  The main routine here is `ast_ty_to_ty()`: each use
13 //! is parameterized by an instance of `AstConv` and a `RegionScope`.
14 //!
15 //! The parameterization of `ast_ty_to_ty()` is because it behaves
16 //! somewhat differently during the collect and check phases,
17 //! particularly with respect to looking up the types of top-level
18 //! items.  In the collect phase, the crate context is used as the
19 //! `AstConv` instance; in this phase, the `get_item_ty()` function
20 //! triggers a recursive call to `ty_of_item()`  (note that
21 //! `ast_ty_to_ty()` will detect recursive types and report an error).
22 //! In the check phase, when the FnCtxt is used as the `AstConv`,
23 //! `get_item_ty()` just looks up the item type in `tcx.tcache`.
24 //!
25 //! The `RegionScope` trait controls what happens when the user does
26 //! not specify a region in some location where a region is required
27 //! (e.g., if the user writes `&Foo` as a type rather than `&'a Foo`).
28 //! See the `rscope` module for more details.
29 //!
30 //! Unlike the `AstConv` trait, the region scope can change as we descend
31 //! the type.  This is to accommodate the fact that (a) fn types are binding
32 //! scopes and (b) the default region may change.  To understand case (a),
33 //! consider something like:
34 //!
35 //!   type foo = { x: &a.int, y: |&a.int| }
36 //!
37 //! The type of `x` is an error because there is no region `a` in scope.
38 //! In the type of `y`, however, region `a` is considered a bound region
39 //! as it does not already appear in scope.
40 //!
41 //! Case (b) says that if you have a type:
42 //!   type foo<'a> = ...;
43 //!   type bar = fn(&foo, &a.foo)
44 //! The fully expanded version of type bar is:
45 //!   type bar = fn(&'foo &, &a.foo<'a>)
46 //! Note that the self region for the `foo` defaulted to `&` in the first
47 //! case but `&a` in the second.  Basically, defaults that appear inside
48 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
49
50 use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
51 use middle::const_eval;
52 use middle::def;
53 use middle::resolve_lifetime as rl;
54 use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
55 use middle::subst::{VecPerParamSpace};
56 use middle::ty::{mod, RegionEscape, Ty};
57 use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
58              ShiftedRscope, BindingRscope};
59 use TypeAndSubsts;
60 use util::common::ErrorReported;
61 use util::nodemap::DefIdMap;
62 use util::ppaux::{mod, Repr, UserString};
63
64 use std::rc::Rc;
65 use std::iter::AdditiveIterator;
66 use syntax::{abi, ast, ast_util};
67 use syntax::codemap::Span;
68 use syntax::parse::token;
69 use syntax::print::pprust;
70
71 pub trait AstConv<'tcx> {
72     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
73     fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx>;
74     fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
75
76     /// Return an (optional) substitution to convert bound type parameters that
77     /// are in scope into free ones. This function should only return Some
78     /// within a fn body.
79     /// See ParameterEnvironment::free_substs for more information.
80     fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
81         None
82     }
83
84     /// What type should we use when a type is omitted?
85     fn ty_infer(&self, span: Span) -> Ty<'tcx>;
86
87     /// Returns true if associated types from the given trait and type are
88     /// allowed to be used here and false otherwise.
89     fn associated_types_of_trait_are_valid(&self,
90                                            ty: Ty<'tcx>,
91                                            trait_id: ast::DefId)
92                                            -> bool;
93
94     /// Returns the concrete type bound to the given associated type (indicated
95     /// by associated_type_id) in the current context. For example,
96     /// in `trait Foo { type A; }` looking up `A` will give a type variable;
97     /// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`.
98     fn associated_type_binding(&self,
99                                span: Span,
100                                self_ty: Option<Ty<'tcx>>,
101                                // DefId for the declaration of the trait
102                                // in which the associated type is declared.
103                                trait_id: ast::DefId,
104                                associated_type_id: ast::DefId)
105                                -> Option<Ty<'tcx>>;
106 }
107
108 pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
109                             -> ty::Region {
110     let r = match tcx.named_region_map.get(&lifetime.id) {
111         None => {
112             // should have been recorded by the `resolve_lifetime` pass
113             tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
114         }
115
116         Some(&rl::DefStaticRegion) => {
117             ty::ReStatic
118         }
119
120         Some(&rl::DefLateBoundRegion(debruijn, id)) => {
121             ty::ReLateBound(debruijn, ty::BrNamed(ast_util::local_def(id), lifetime.name))
122         }
123
124         Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
125             ty::ReEarlyBound(id, space, index, lifetime.name)
126         }
127
128         Some(&rl::DefFreeRegion(scope, id)) => {
129             ty::ReFree(ty::FreeRegion {
130                     scope: scope,
131                     bound_region: ty::BrNamed(ast_util::local_def(id),
132                                               lifetime.name)
133                 })
134         }
135     };
136
137     debug!("ast_region_to_region(lifetime={} id={}) yields {}",
138            lifetime.repr(tcx),
139            lifetime.id,
140            r.repr(tcx));
141
142     r
143 }
144
145 pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
146     this: &AC,
147     rscope: &RS,
148     default_span: Span,
149     opt_lifetime: &Option<ast::Lifetime>) -> ty::Region
150 {
151     let r = match *opt_lifetime {
152         Some(ref lifetime) => {
153             ast_region_to_region(this.tcx(), lifetime)
154         }
155
156         None => {
157             match rscope.anon_regions(default_span, 1) {
158                 Err(v) => {
159                     debug!("optional region in illegal location");
160                     span_err!(this.tcx().sess, default_span, E0106,
161                         "missing lifetime specifier");
162                     match v {
163                         Some(v) => {
164                             let mut m = String::new();
165                             let len = v.len();
166                             for (i, (name, n)) in v.into_iter().enumerate() {
167                                 let help_name = if name.is_empty() {
168                                     format!("argument {}", i + 1)
169                                 } else {
170                                     format!("`{}`", name)
171                                 };
172
173                                 m.push_str(if n == 1 {
174                                     help_name
175                                 } else {
176                                     format!("one of {}'s {} elided lifetimes", help_name, n)
177                                 }[]);
178
179                                 if len == 2 && i == 0 {
180                                     m.push_str(" or ");
181                                 } else if i == len - 2 {
182                                     m.push_str(", or ");
183                                 } else if i != len - 1 {
184                                     m.push_str(", ");
185                                 }
186                             }
187                             if len == 1 {
188                                 span_help!(this.tcx().sess, default_span,
189                                     "this function's return type contains a borrowed value, but \
190                                      the signature does not say which {} it is borrowed from",
191                                     m);
192                             } else if len == 0 {
193                                 span_help!(this.tcx().sess, default_span,
194                                     "this function's return type contains a borrowed value, but \
195                                      there is no value for it to be borrowed from");
196                                 span_help!(this.tcx().sess, default_span,
197                                     "consider giving it a 'static lifetime");
198                             } else {
199                                 span_help!(this.tcx().sess, default_span,
200                                     "this function's return type contains a borrowed value, but \
201                                      the signature does not say whether it is borrowed from {}",
202                                     m);
203                             }
204                         }
205                         None => {},
206                     }
207                     ty::ReStatic
208                 }
209
210                 Ok(rs) => rs[0],
211             }
212         }
213     };
214
215     debug!("opt_ast_region_to_region(opt_lifetime={}) yields {}",
216             opt_lifetime.repr(this.tcx()),
217             r.repr(this.tcx()));
218
219     r
220 }
221
222 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
223 /// returns an appropriate set of substitutions for this particular reference to `I`.
224 fn ast_path_substs_for_ty<'tcx,AC,RS>(
225     this: &AC,
226     rscope: &RS,
227     decl_def_id: ast::DefId,
228     decl_generics: &ty::Generics<'tcx>,
229     path: &ast::Path)
230     -> Substs<'tcx>
231     where AC: AstConv<'tcx>, RS: RegionScope
232 {
233     let tcx = this.tcx();
234
235     // ast_path_substs() is only called to convert paths that are
236     // known to refer to traits, types, or structs. In these cases,
237     // all type parameters defined for the item being referenced will
238     // be in the TypeSpace or SelfSpace.
239     //
240     // Note: in the case of traits, the self parameter is also
241     // defined, but we don't currently create a `type_param_def` for
242     // `Self` because it is implicit.
243     assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
244     assert!(decl_generics.types.all(|d| d.space != FnSpace));
245
246     let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
247         ast::AngleBracketedParameters(ref data) => {
248             convert_angle_bracketed_parameters(this, rscope, data)
249         }
250         ast::ParenthesizedParameters(ref data) => {
251             tcx.sess.span_err(
252                 path.span,
253                 "parenthesized parameters may only be used with a trait");
254             (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
255         }
256     };
257
258     create_substs_for_ast_path(this,
259                                rscope,
260                                path.span,
261                                decl_def_id,
262                                decl_generics,
263                                None,
264                                types,
265                                regions,
266                                assoc_bindings)
267 }
268
269 fn create_substs_for_ast_path<'tcx,AC,RS>(
270     this: &AC,
271     rscope: &RS,
272     span: Span,
273     decl_def_id: ast::DefId,
274     decl_generics: &ty::Generics<'tcx>,
275     self_ty: Option<Ty<'tcx>>,
276     types: Vec<Ty<'tcx>>,
277     regions: Vec<ty::Region>,
278     assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>)
279     -> Substs<'tcx>
280     where AC: AstConv<'tcx>, RS: RegionScope
281 {
282     let tcx = this.tcx();
283
284     // If the type is parameterized by the this region, then replace this
285     // region with the current anon region binding (in other words,
286     // whatever & would get replaced with).
287     let expected_num_region_params = decl_generics.regions.len(TypeSpace);
288     let supplied_num_region_params = regions.len();
289     let regions = if expected_num_region_params == supplied_num_region_params {
290         regions
291     } else {
292         let anon_regions =
293             rscope.anon_regions(span, expected_num_region_params);
294
295         if supplied_num_region_params != 0 || anon_regions.is_err() {
296             span_err!(tcx.sess, span, E0107,
297                       "wrong number of lifetime parameters: expected {}, found {}",
298                       expected_num_region_params, supplied_num_region_params);
299         }
300
301         match anon_regions {
302             Ok(v) => v.into_iter().collect(),
303             Err(_) => Vec::from_fn(expected_num_region_params,
304                                    |_| ty::ReStatic) // hokey
305         }
306     };
307
308     // Convert the type parameters supplied by the user.
309     let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
310     let supplied_ty_param_count = types.len();
311     let formal_ty_param_count =
312         ty_param_defs.iter()
313         .take_while(|x| !ty::is_associated_type(tcx, x.def_id))
314         .count();
315     let required_ty_param_count =
316         ty_param_defs.iter()
317         .take_while(|x| {
318             x.default.is_none() &&
319                 !ty::is_associated_type(tcx, x.def_id)
320         })
321         .count();
322     if supplied_ty_param_count < required_ty_param_count {
323         let expected = if required_ty_param_count < formal_ty_param_count {
324             "expected at least"
325         } else {
326             "expected"
327         };
328         this.tcx().sess.span_fatal(span,
329                                    format!("wrong number of type arguments: {} {}, found {}",
330                                            expected,
331                                            required_ty_param_count,
332                                            supplied_ty_param_count)[]);
333     } else if supplied_ty_param_count > formal_ty_param_count {
334         let expected = if required_ty_param_count < formal_ty_param_count {
335             "expected at most"
336         } else {
337             "expected"
338         };
339         this.tcx().sess.span_fatal(span,
340                                    format!("wrong number of type arguments: {} {}, found {}",
341                                            expected,
342                                            formal_ty_param_count,
343                                            supplied_ty_param_count)[]);
344     }
345
346     if supplied_ty_param_count > required_ty_param_count
347         && !this.tcx().sess.features.borrow().default_type_params {
348         span_err!(this.tcx().sess, span, E0108,
349             "default type parameters are experimental and possibly buggy");
350         span_help!(this.tcx().sess, span,
351             "add #![feature(default_type_params)] to the crate attributes to enable");
352     }
353
354     let mut substs = Substs::new_type(types, regions);
355
356     match self_ty {
357         None => {
358             // If no self-type is provided, it's still possible that
359             // one was declared, because this could be an object type.
360         }
361         Some(ty) => {
362             // If a self-type is provided, one should have been
363             // "declared" (in other words, this should be a
364             // trait-ref).
365             assert!(decl_generics.types.get_self().is_some());
366             substs.types.push(SelfSpace, ty);
367         }
368     }
369
370     for param in ty_param_defs[supplied_ty_param_count..].iter() {
371         match param.default {
372             Some(default) => {
373                 // This is a default type parameter.
374                 let default = default.subst_spanned(tcx,
375                                                     &substs,
376                                                     Some(span));
377                 substs.types.push(TypeSpace, default);
378             }
379             None => {
380                 tcx.sess.span_bug(span, "extra parameter without default");
381             }
382         }
383     }
384
385     for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() {
386         let mut found = false;
387         for &(ident, ty) in assoc_bindings.iter() {
388             if formal_assoc.name.ident() == ident {
389                 substs.types.push(AssocSpace, ty);
390                 found = true;
391                 break;
392             }
393         }
394         if !found {
395             match this.associated_type_binding(span,
396                                                self_ty,
397                                                decl_def_id,
398                                                formal_assoc.def_id) {
399                 Some(ty) => {
400                     substs.types.push(AssocSpace, ty);
401                 }
402                 None => {
403                     substs.types.push(AssocSpace, ty::mk_err());
404                     span_err!(this.tcx().sess, span, E0171,
405                               "missing type for associated type `{}`",
406                               token::get_ident(formal_assoc.name.ident()));
407                 }
408             }
409         }
410     }
411
412     for &(ident, _) in assoc_bindings.iter() {
413         let mut formal_idents = decl_generics.types.get_slice(AssocSpace)
414                                 .iter().map(|t| t.name.ident());
415         if !formal_idents.any(|i| i == ident) {
416             span_err!(this.tcx().sess, span, E0177,
417                       "associated type `{}` does not exist",
418                       token::get_ident(ident));
419         }
420     }
421
422     return substs;
423 }
424
425 fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
426                                                     rscope: &RS,
427                                                     data: &ast::AngleBracketedParameterData)
428                                                     -> (Vec<ty::Region>,
429                                                         Vec<Ty<'tcx>>,
430                                                         Vec<(ast::Ident, Ty<'tcx>)>)
431     where AC: AstConv<'tcx>, RS: RegionScope
432 {
433     let regions: Vec<_> =
434         data.lifetimes.iter()
435         .map(|l| ast_region_to_region(this.tcx(), l))
436         .collect();
437
438     let types: Vec<_> =
439         data.types.iter()
440         .map(|t| ast_ty_to_ty(this, rscope, &**t))
441         .collect();
442
443     let assoc_bindings: Vec<_> =
444         data.bindings.iter()
445         .map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty)))
446         .collect();
447
448     (regions, types, assoc_bindings)
449 }
450
451 /// Returns the appropriate lifetime to use for any output lifetimes
452 /// (if one exists) and a vector of the (pattern, number of lifetimes)
453 /// corresponding to each input type/pattern.
454 fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
455                               -> (Option<ty::Region>, Vec<(String, uint)>)
456 {
457     let mut lifetimes_for_params: Vec<(String, uint)> = Vec::new();
458     let mut possible_implied_output_region = None;
459
460     for (input_type, input_pat) in input_tys.iter().zip(input_pats.into_iter()) {
461         let mut accumulator = Vec::new();
462         ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type);
463
464         if accumulator.len() == 1 {
465             // there's a chance that the unique lifetime of this
466             // iteration will be the appropriate lifetime for output
467             // parameters, so lets store it.
468             possible_implied_output_region = Some(accumulator[0])
469         }
470
471         lifetimes_for_params.push((input_pat, accumulator.len()));
472     }
473
474     let implied_output_region = if lifetimes_for_params.iter().map(|&(_, n)| n).sum() == 1 {
475         assert!(possible_implied_output_region.is_some());
476         possible_implied_output_region
477     } else {
478         None
479     };
480     (implied_output_region, lifetimes_for_params)
481 }
482
483 fn convert_ty_with_lifetime_elision<'tcx,AC>(this: &AC,
484                                              implied_output_region: Option<ty::Region>,
485                                              param_lifetimes: Vec<(String, uint)>,
486                                              ty: &ast::Ty)
487                                              -> Ty<'tcx>
488     where AC: AstConv<'tcx>
489 {
490     match implied_output_region {
491         Some(implied_output_region) => {
492             let rb = SpecificRscope::new(implied_output_region);
493             ast_ty_to_ty(this, &rb, ty)
494         }
495         None => {
496             // All regions must be explicitly specified in the output
497             // if the lifetime elision rules do not apply. This saves
498             // the user from potentially-confusing errors.
499             let rb = UnelidableRscope::new(param_lifetimes);
500             ast_ty_to_ty(this, &rb, ty)
501         }
502     }
503 }
504
505 fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
506                                              data: &ast::ParenthesizedParameterData)
507                                              -> Vec<Ty<'tcx>>
508     where AC: AstConv<'tcx>
509 {
510     let binding_rscope = BindingRscope::new();
511     let inputs = data.inputs.iter()
512                             .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
513                             .collect::<Vec<Ty<'tcx>>>();
514
515     let input_params = Vec::from_elem(inputs.len(), String::new());
516     let (implied_output_region,
517          params_lifetimes) = find_implied_output_region(&*inputs, input_params);
518
519     let input_ty = ty::mk_tup(this.tcx(), inputs);
520
521     let output = match data.output {
522         Some(ref output_ty) => convert_ty_with_lifetime_elision(this,
523                                                                 implied_output_region,
524                                                                 params_lifetimes,
525                                                                 &**output_ty),
526         None => ty::mk_nil(this.tcx()),
527     };
528
529     vec![input_ty, output]
530 }
531
532 pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
533     this: &AC,
534     rscope: &RS,
535     ast_trait_ref: &ast::PolyTraitRef,
536     self_ty: Option<Ty<'tcx>>,
537     allow_eq: AllowEqConstraints)
538     -> Rc<ty::PolyTraitRef<'tcx>>
539     where AC: AstConv<'tcx>, RS: RegionScope
540 {
541     let trait_ref =
542         instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
543     let trait_ref = (*trait_ref).clone();
544     Rc::new(ty::Binder(trait_ref)) // Ugh.
545 }
546
547 /// Instantiates the path for the given trait reference, assuming that it's
548 /// bound to a valid trait type. Returns the def_id for the defining trait.
549 /// Fails if the type is a type other than a trait type.
550 pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
551                                          rscope: &RS,
552                                          ast_trait_ref: &ast::TraitRef,
553                                          self_ty: Option<Ty<'tcx>>,
554                                          allow_eq: AllowEqConstraints)
555                                          -> Rc<ty::TraitRef<'tcx>>
556                                          where AC: AstConv<'tcx>,
557                                                RS: RegionScope
558 {
559     match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
560         def::DefTrait(trait_def_id) => {
561             let trait_ref = Rc::new(ast_path_to_trait_ref(this,
562                                                           rscope,
563                                                           trait_def_id,
564                                                           self_ty,
565                                                           &ast_trait_ref.path,
566                                                           allow_eq));
567             this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
568                                                       trait_ref.clone());
569             trait_ref
570         }
571         _ => {
572             this.tcx().sess.span_fatal(
573                 ast_trait_ref.path.span,
574                 format!("`{}` is not a trait", ast_trait_ref.path.user_string(this.tcx()))[]);
575         }
576     }
577 }
578
579 #[deriving(PartialEq,Show)]
580 pub enum AllowEqConstraints {
581     Allow,
582     DontAllow
583 }
584
585 fn ast_path_to_trait_ref<'tcx,AC,RS>(
586     this: &AC,
587     rscope: &RS,
588     trait_def_id: ast::DefId,
589     self_ty: Option<Ty<'tcx>>,
590     path: &ast::Path,
591     allow_eq: AllowEqConstraints)
592     -> ty::TraitRef<'tcx>
593     where AC: AstConv<'tcx>, RS: RegionScope
594 {
595     debug!("ast_path_to_trait_ref {}", path);
596     let trait_def = this.get_trait_def(trait_def_id);
597
598     // the trait reference introduces a binding level here, so
599     // we need to shift the `rscope`. It'd be nice if we could
600     // do away with this rscope stuff and work this knowledge
601     // into resolve_lifetimes, as we do with non-omitted
602     // lifetimes. Oh well, not there yet.
603     let shifted_rscope = ShiftedRscope::new(rscope);
604
605     let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
606         ast::AngleBracketedParameters(ref data) => {
607             convert_angle_bracketed_parameters(this, &shifted_rscope, data)
608         }
609         ast::ParenthesizedParameters(ref data) => {
610             // For now, require that parenthetical notation be used
611             // only with `Fn()` etc.
612             if !this.tcx().sess.features.borrow().unboxed_closures &&
613                 this.tcx().lang_items.fn_trait_kind(trait_def_id).is_none()
614             {
615                 this.tcx().sess.span_err(path.span,
616                                          "parenthetical notation is only stable when \
617                                          used with the `Fn` family of traits");
618                 span_help!(this.tcx().sess, path.span,
619                            "add `#![feature(unboxed_closures)]` to \
620                             the crate attributes to enable");
621             }
622
623             (Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
624         }
625     };
626
627     if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 {
628         span_err!(this.tcx().sess, path.span, E0173,
629                   "equality constraints are not allowed in this position");
630     }
631
632     let substs = create_substs_for_ast_path(this,
633                                             &shifted_rscope,
634                                             path.span,
635                                             trait_def_id,
636                                             &trait_def.generics,
637                                             self_ty,
638                                             types,
639                                             regions,
640                                             assoc_bindings);
641
642     ty::TraitRef::new(trait_def_id, this.tcx().mk_substs(substs))
643 }
644
645 pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
646     this: &AC,
647     rscope: &RS,
648     did: ast::DefId,
649     path: &ast::Path)
650     -> TypeAndSubsts<'tcx>
651 {
652     let tcx = this.tcx();
653     let ty::Polytype {
654         generics,
655         ty: decl_ty
656     } = this.get_item_ty(did);
657
658     let substs = ast_path_substs_for_ty(this,
659                                         rscope,
660                                         did,
661                                         &generics,
662                                         path);
663     let ty = decl_ty.subst(tcx, &substs);
664     TypeAndSubsts { substs: substs, ty: ty }
665 }
666
667 /// Returns the type that this AST path refers to. If the path has no type
668 /// parameters and the corresponding type has type parameters, fresh type
669 /// and/or region variables are substituted.
670 ///
671 /// This is used when checking the constructor in struct literals.
672 pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
673     this: &AC,
674     rscope: &RS,
675     did: ast::DefId,
676     path: &ast::Path)
677     -> TypeAndSubsts<'tcx>
678     where AC : AstConv<'tcx>, RS : RegionScope
679 {
680     let tcx = this.tcx();
681     let ty::Polytype {
682         generics,
683         ty: decl_ty
684     } = this.get_item_ty(did);
685
686     let wants_params =
687         generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
688
689     let needs_defaults =
690         wants_params &&
691         path.segments.iter().all(|s| s.parameters.is_empty());
692
693     let substs = if needs_defaults {
694         let type_params = Vec::from_fn(generics.types.len(TypeSpace),
695                                        |_| this.ty_infer(path.span));
696         let region_params =
697             rscope.anon_regions(path.span, generics.regions.len(TypeSpace))
698                   .unwrap();
699         Substs::new(VecPerParamSpace::params_from_type(type_params),
700                     VecPerParamSpace::params_from_type(region_params))
701     } else {
702         ast_path_substs_for_ty(this, rscope, did, &generics, path)
703     };
704
705     let ty = decl_ty.subst(tcx, &substs);
706     TypeAndSubsts {
707         substs: substs,
708         ty: ty,
709     }
710 }
711
712 /// Converts the given AST type to a built-in type. A "built-in type" is, at
713 /// present, either a core numeric type, a string, or `Box`.
714 pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
715         this: &AC,
716         rscope: &RS,
717         ast_ty: &ast::Ty)
718         -> Option<Ty<'tcx>> {
719     match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
720         Some(typ) => return Some(typ),
721         None => {}
722     }
723
724     match ast_ty.node {
725         ast::TyPath(ref path, id) => {
726             let a_def = match this.tcx().def_map.borrow().get(&id) {
727                 None => {
728                     this.tcx()
729                         .sess
730                         .span_bug(ast_ty.span,
731                                   format!("unbound path {}",
732                                           path.repr(this.tcx()))[])
733                 }
734                 Some(&d) => d
735             };
736
737             // FIXME(#12938): This is a hack until we have full support for
738             // DST.
739             match a_def {
740                 def::DefTy(did, _) |
741                 def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
742                     let ty = ast_path_to_ty(this, rscope, did, path).ty;
743                     match ty.sty {
744                         ty::ty_struct(struct_def_id, ref substs) => {
745                             assert_eq!(struct_def_id, did);
746                             assert_eq!(substs.types.len(TypeSpace), 1);
747                             let referent_ty = *substs.types.get(TypeSpace, 0);
748                             Some(ty::mk_uniq(this.tcx(), referent_ty))
749                         }
750                         _ => {
751                             this.tcx().sess.span_bug(
752                                 path.span,
753                                 format!("converting `Box` to `{}`",
754                                         ty.repr(this.tcx()))[]);
755                         }
756                     }
757                 }
758                 _ => None
759             }
760         }
761         _ => None
762     }
763 }
764
765 fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
766                                    rscope: &RS,
767                                    ty: &ast::Ty,
768                                    bounds: &[ast::TyParamBound])
769                                    -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
770     where AC : AstConv<'tcx>, RS : RegionScope
771 {
772     /*!
773      * In a type like `Foo + Send`, we want to wait to collect the
774      * full set of bounds before we make the object type, because we
775      * need them to infer a region bound.  (For example, if we tried
776      * made a type from just `Foo`, then it wouldn't be enough to
777      * infer a 'static bound, and hence the user would get an error.)
778      * So this function is used when we're dealing with a sum type to
779      * convert the LHS. It only accepts a type that refers to a trait
780      * name, and reports an error otherwise.
781      */
782
783     match ty.node {
784         ast::TyPath(ref path, id) => {
785             match this.tcx().def_map.borrow().get(&id) {
786                 Some(&def::DefTrait(trait_def_id)) => {
787                     return Ok(ty::Binder(ast_path_to_trait_ref(this,
788                                                                rscope,
789                                                                trait_def_id,
790                                                                None,
791                                                                path,
792                                                                AllowEqConstraints::Allow)));
793                 }
794                 _ => {
795                     span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
796                     Err(ErrorReported)
797                 }
798             }
799         }
800         _ => {
801             span_err!(this.tcx().sess, ty.span, E0178,
802                       "expected a path on the left-hand side of `+`, not `{}`",
803                       pprust::ty_to_string(ty));
804             match ty.node {
805                 ast::TyRptr(None, ref mut_ty) => {
806                     span_note!(this.tcx().sess, ty.span,
807                                "perhaps you meant `&{}({} +{})`? (per RFC 438)",
808                                ppaux::mutability_to_string(mut_ty.mutbl),
809                                pprust::ty_to_string(&*mut_ty.ty),
810                                pprust::bounds_to_string(bounds));
811                 }
812                ast::TyRptr(Some(ref lt), ref mut_ty) => {
813                     span_note!(this.tcx().sess, ty.span,
814                                "perhaps you meant `&{} {}({} +{})`? (per RFC 438)",
815                                pprust::lifetime_to_string(lt),
816                                ppaux::mutability_to_string(mut_ty.mutbl),
817                                pprust::ty_to_string(&*mut_ty.ty),
818                                pprust::bounds_to_string(bounds));
819                 }
820
821                 _ => {
822                     span_note!(this.tcx().sess, ty.span,
823                                "perhaps you forgot parentheses? (per RFC 438)");
824                 }
825             }
826             Err(ErrorReported)
827         }
828     }
829 }
830
831 fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
832                                         rscope: &RS,
833                                         span: Span,
834                                         trait_ref: ty::PolyTraitRef<'tcx>,
835                                         bounds: &[ast::TyParamBound])
836                                         -> Ty<'tcx>
837     where AC : AstConv<'tcx>, RS : RegionScope
838 {
839     let existential_bounds = conv_existential_bounds(this,
840                                                      rscope,
841                                                      span,
842                                                      Some(&trait_ref),
843                                                      bounds);
844
845     let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
846     debug!("trait_ref_to_object_type: result={}",
847            result.repr(this.tcx()));
848
849     result
850 }
851
852 fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
853                            rscope: &RS,
854                            ast_ty: &ast::Ty, // the TyQPath
855                            qpath: &ast::QPath)
856                            -> Ty<'tcx>
857     where AC: AstConv<'tcx>, RS: RegionScope
858 {
859     debug!("qpath_to_ty(ast_ty={})",
860            ast_ty.repr(this.tcx()));
861
862     let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
863
864     debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
865
866     let trait_ref = instantiate_trait_ref(this,
867                                           rscope,
868                                           &*qpath.trait_ref,
869                                           Some(self_type),
870                                           AllowEqConstraints::DontAllow);
871
872     debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
873
874     if let Some(ty) = find_assoc_ty(this, &*trait_ref, qpath.item_name) {
875         return ty;
876     }
877
878     this.tcx().sess.span_bug(ast_ty.span,
879                              "this associated type didn't get added \
880                               as a parameter for some reason")
881 }
882
883 fn find_assoc_ty<'tcx, AC>(this: &AC,
884                            trait_ref: &ty::TraitRef<'tcx>,
885                            type_name: ast::Ident)
886                            -> Option<Ty<'tcx>>
887 where AC: AstConv<'tcx> {
888     let trait_def = this.get_trait_def(trait_ref.def_id);
889
890     for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
891         if ty_param_def.name == type_name.name {
892             return Some(trait_ref.substs.type_for_def(ty_param_def));
893         }
894     }
895
896     None
897 }
898
899 // Parses the programmer's textual representation of a type into our
900 // internal notion of a type.
901 pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
902         this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>
903 {
904     debug!("ast_ty_to_ty(ast_ty={})",
905            ast_ty.repr(this.tcx()));
906
907     let tcx = this.tcx();
908
909     let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut();
910     match ast_ty_to_ty_cache.get(&ast_ty.id) {
911         Some(&ty::atttce_resolved(ty)) => return ty,
912         Some(&ty::atttce_unresolved) => {
913             tcx.sess.span_fatal(ast_ty.span,
914                                 "illegal recursive type; insert an enum \
915                                  or struct in the cycle, if this is \
916                                  desired");
917         }
918         None => { /* go on */ }
919     }
920     ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
921     drop(ast_ty_to_ty_cache);
922
923     let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
924         match ast_ty.node {
925             ast::TyVec(ref ty) => {
926                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
927             }
928             ast::TyObjectSum(ref ty, ref bounds) => {
929                 match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) {
930                     Ok(trait_ref) => {
931                         trait_ref_to_object_type(this, rscope, ast_ty.span,
932                                                  trait_ref, bounds[])
933                     }
934                     Err(ErrorReported) => {
935                         ty::mk_err()
936                     }
937                 }
938             }
939             ast::TyPtr(ref mt) => {
940                 ty::mk_ptr(tcx, ty::mt {
941                     ty: ast_ty_to_ty(this, rscope, &*mt.ty),
942                     mutbl: mt.mutbl
943                 })
944             }
945             ast::TyRptr(ref region, ref mt) => {
946                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
947                 debug!("ty_rptr r={}", r.repr(this.tcx()));
948                 let t = ast_ty_to_ty(this, rscope, &*mt.ty);
949                 ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
950             }
951             ast::TyTup(ref fields) => {
952                 let flds = fields.iter()
953                                  .map(|t| ast_ty_to_ty(this, rscope, &**t))
954                                  .collect();
955                 ty::mk_tup(tcx, flds)
956             }
957             ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
958             ast::TyBareFn(ref bf) => {
959                 if bf.decl.variadic && bf.abi != abi::C {
960                     tcx.sess.span_err(ast_ty.span,
961                                       "variadic function must have C calling convention");
962                 }
963                 let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
964                 ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
965             }
966             ast::TyClosure(ref f) => {
967                 // Use corresponding trait store to figure out default bounds
968                 // if none were specified.
969                 let bounds = conv_existential_bounds(this,
970                                                      rscope,
971                                                      ast_ty.span,
972                                                      None,
973                                                      f.bounds.as_slice());
974                 let fn_decl = ty_of_closure(this,
975                                             f.unsafety,
976                                             f.onceness,
977                                             bounds,
978                                             ty::RegionTraitStore(
979                                                 bounds.region_bound,
980                                                 ast::MutMutable),
981                                             &*f.decl,
982                                             abi::Rust,
983                                             None);
984                 ty::mk_closure(tcx, fn_decl)
985             }
986             ast::TyPolyTraitRef(ref bounds) => {
987                 conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds[])
988             }
989             ast::TyPath(ref path, id) => {
990                 let a_def = match tcx.def_map.borrow().get(&id) {
991                     None => {
992                         tcx.sess
993                            .span_bug(ast_ty.span,
994                                      format!("unbound path {}",
995                                              path.repr(tcx))[])
996                     }
997                     Some(&d) => d
998                 };
999                 match a_def {
1000                     def::DefTrait(trait_def_id) => {
1001                         // N.B. this case overlaps somewhat with
1002                         // TyObjectSum, see that fn for details
1003                         let result = ty::Binder(ast_path_to_trait_ref(this,
1004                                                                       rscope,
1005                                                                       trait_def_id,
1006                                                                       None,
1007                                                                       path,
1008                                                                       AllowEqConstraints::Allow));
1009                         trait_ref_to_object_type(this, rscope, path.span, result, &[])
1010                     }
1011                     def::DefTy(did, _) | def::DefStruct(did) => {
1012                         ast_path_to_ty(this, rscope, did, path).ty
1013                     }
1014                     def::DefTyParam(space, id, n) => {
1015                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
1016                         ty::mk_param(tcx, space, n, id)
1017                     }
1018                     def::DefSelfTy(id) => {
1019                         // n.b.: resolve guarantees that the this type only appears in a
1020                         // trait, which we rely upon in various places when creating
1021                         // substs
1022                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
1023                         let did = ast_util::local_def(id);
1024                         ty::mk_self_type(tcx, did)
1025                     }
1026                     def::DefMod(id) => {
1027                         tcx.sess.span_fatal(ast_ty.span,
1028                             format!("found module name used as a type: {}",
1029                                     tcx.map.node_to_string(id.node))[]);
1030                     }
1031                     def::DefPrimTy(_) => {
1032                         panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
1033                     }
1034                     def::DefAssociatedTy(trait_type_id) => {
1035                         let path_str = tcx.map.path_to_string(
1036                             tcx.map.get_parent(trait_type_id.node));
1037                         tcx.sess.span_err(ast_ty.span,
1038                                           format!("ambiguous associated \
1039                                                    type; specify the type \
1040                                                    using the syntax `<Type \
1041                                                    as {}>::{}`",
1042                                                   path_str,
1043                                                   token::get_ident(
1044                                                       path.segments
1045                                                           .last()
1046                                                           .unwrap()
1047                                                           .identifier)
1048                                                   .get())[]);
1049                         ty::mk_err()
1050                     }
1051                     def::DefAssociatedPath(typ, assoc_ident) => {
1052                         // FIXME(#19541): in both branches we should consider
1053                         // associated types in super-traits.
1054                         let (assoc_tys, tp_name): (Vec<_>, _) = match typ {
1055                             def::TyParamProvenance::FromParam(did) |
1056                             def::TyParamProvenance::FromSelf(did) => {
1057                                 let ty_param_defs = tcx.ty_param_defs.borrow();
1058                                 let tp_def = &(*ty_param_defs)[did.node];
1059                                 let assoc_tys = tp_def.bounds.trait_bounds.iter()
1060                                     .filter_map(|b| find_assoc_ty(this, &b.0, assoc_ident))
1061                                     .collect();
1062                                 (assoc_tys, token::get_name(tp_def.name).to_string())
1063                             }
1064                         };
1065
1066                         if assoc_tys.len() == 0 {
1067                             tcx.sess.span_err(ast_ty.span,
1068                                               format!("associated type `{}` not \
1069                                                        found for type parameter `{}`",
1070                                                       token::get_ident(assoc_ident),
1071                                                       tp_name).as_slice());
1072                             return ty::mk_err()
1073                         }
1074
1075                         if assoc_tys.len() > 1 {
1076                             tcx.sess.span_err(ast_ty.span,
1077                                               format!("ambiguous associated type \
1078                                                        `{}` in bounds of `{}`",
1079                                                       token::get_ident(assoc_ident),
1080                                                       tp_name).as_slice());
1081                         }
1082
1083                         let mut result_ty = assoc_tys[0];
1084                         if let Some(substs) = this.get_free_substs() {
1085                             result_ty = result_ty.subst(tcx, substs);
1086                         }
1087
1088                         result_ty
1089                     }
1090                     _ => {
1091                         tcx.sess.span_fatal(ast_ty.span,
1092                                             format!("found value name used \
1093                                                      as a type: {}",
1094                                                     a_def)[]);
1095                     }
1096                 }
1097             }
1098             ast::TyQPath(ref qpath) => {
1099                 qpath_to_ty(this, rscope, ast_ty, &**qpath)
1100             }
1101             ast::TyFixedLengthVec(ref ty, ref e) => {
1102                 match const_eval::eval_const_expr_partial(tcx, &**e) {
1103                     Ok(ref r) => {
1104                         match *r {
1105                             const_eval::const_int(i) =>
1106                                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
1107                                            Some(i as uint)),
1108                             const_eval::const_uint(i) =>
1109                                 ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
1110                                            Some(i as uint)),
1111                             _ => {
1112                                 tcx.sess.span_fatal(
1113                                     ast_ty.span, "expected constant expr for array length");
1114                             }
1115                         }
1116                     }
1117                     Err(ref r) => {
1118                         tcx.sess.span_fatal(
1119                             ast_ty.span,
1120                             format!("expected constant expr for array \
1121                                      length: {}",
1122                                     *r)[]);
1123                     }
1124                 }
1125             }
1126             ast::TyTypeof(ref _e) => {
1127                 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
1128             }
1129             ast::TyInfer => {
1130                 // TyInfer also appears as the type of arguments or return
1131                 // values in a ExprClosure, or as
1132                 // the type of local variables. Both of these cases are
1133                 // handled specially and will not descend into this routine.
1134                 this.ty_infer(ast_ty.span)
1135             }
1136         }
1137     });
1138
1139     tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
1140     return typ;
1141 }
1142
1143 pub fn ty_of_arg<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(this: &AC, rscope: &RS,
1144                                                            a: &ast::Arg,
1145                                                            expected_ty: Option<Ty<'tcx>>)
1146                                                            -> Ty<'tcx> {
1147     match a.ty.node {
1148         ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
1149         ast::TyInfer => this.ty_infer(a.ty.span),
1150         _ => ast_ty_to_ty(this, rscope, &*a.ty),
1151     }
1152 }
1153
1154 struct SelfInfo<'a, 'tcx> {
1155     untransformed_self_ty: Ty<'tcx>,
1156     explicit_self: &'a ast::ExplicitSelf,
1157 }
1158
1159 pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
1160                     this: &AC,
1161                     unsafety: ast::Unsafety,
1162                     untransformed_self_ty: Ty<'tcx>,
1163                     explicit_self: &ast::ExplicitSelf,
1164                     decl: &ast::FnDecl,
1165                     abi: abi::Abi)
1166                     -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
1167     let self_info = Some(SelfInfo {
1168         untransformed_self_ty: untransformed_self_ty,
1169         explicit_self: explicit_self,
1170     });
1171     let (bare_fn_ty, optional_explicit_self_category) =
1172         ty_of_method_or_bare_fn(this,
1173                                 unsafety,
1174                                 abi,
1175                                 self_info,
1176                                 decl);
1177     (bare_fn_ty, optional_explicit_self_category.unwrap())
1178 }
1179
1180 pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, unsafety: ast::Unsafety, abi: abi::Abi,
1181                                               decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> {
1182     let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
1183     bare_fn_ty
1184 }
1185
1186 fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
1187                            this: &AC,
1188                            unsafety: ast::Unsafety,
1189                            abi: abi::Abi,
1190                            opt_self_info: Option<SelfInfo<'a, 'tcx>>,
1191                            decl: &ast::FnDecl)
1192                            -> (ty::BareFnTy<'tcx>,
1193                                Option<ty::ExplicitSelfCategory>)
1194 {
1195     debug!("ty_of_method_or_bare_fn");
1196
1197     // New region names that appear inside of the arguments of the function
1198     // declaration are bound to that function type.
1199     let rb = rscope::BindingRscope::new();
1200
1201     // `implied_output_region` is the region that will be assumed for any
1202     // region parameters in the return type. In accordance with the rules for
1203     // lifetime elision, we can determine it in two ways. First (determined
1204     // here), if self is by-reference, then the implied output region is the
1205     // region of the self parameter.
1206     let mut explicit_self_category_result = None;
1207     let (self_ty, mut implied_output_region) = match opt_self_info {
1208         None => (None, None),
1209         Some(self_info) => {
1210             // This type comes from an impl or trait; no late-bound
1211             // regions should be present.
1212             assert!(!self_info.untransformed_self_ty.has_escaping_regions());
1213
1214             // Figure out and record the explicit self category.
1215             let explicit_self_category =
1216                 determine_explicit_self_category(this, &rb, &self_info);
1217             explicit_self_category_result = Some(explicit_self_category);
1218             match explicit_self_category {
1219                 ty::StaticExplicitSelfCategory => {
1220                     (None, None)
1221                 }
1222                 ty::ByValueExplicitSelfCategory => {
1223                     (Some(self_info.untransformed_self_ty), None)
1224                 }
1225                 ty::ByReferenceExplicitSelfCategory(region, mutability) => {
1226                     (Some(ty::mk_rptr(this.tcx(),
1227                                       this.tcx().mk_region(region),
1228                                       ty::mt {
1229                                         ty: self_info.untransformed_self_ty,
1230                                         mutbl: mutability
1231                                       })),
1232                      Some(region))
1233                 }
1234                 ty::ByBoxExplicitSelfCategory => {
1235                     (Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)), None)
1236                 }
1237             }
1238         }
1239     };
1240
1241     // HACK(eddyb) replace the fake self type in the AST with the actual type.
1242     let input_params = if self_ty.is_some() {
1243         decl.inputs.slice_from(1)
1244     } else {
1245         decl.inputs[]
1246     };
1247     let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None));
1248     let input_pats: Vec<String> = input_params.iter()
1249                                               .map(|a| pprust::pat_to_string(&*a.pat))
1250                                               .collect();
1251     let self_and_input_tys: Vec<Ty> =
1252         self_ty.into_iter().chain(input_tys).collect();
1253
1254
1255     // Second, if there was exactly one lifetime (either a substitution or a
1256     // reference) in the arguments, then any anonymous regions in the output
1257     // have that lifetime.
1258     let lifetimes_for_params = if implied_output_region.is_none() {
1259         let input_tys = if self_ty.is_some() {
1260             // Skip the first argument if `self` is present.
1261             self_and_input_tys.slice_from(1)
1262         } else {
1263             self_and_input_tys.slice_from(0)
1264         };
1265
1266         let (ior, lfp) = find_implied_output_region(input_tys, input_pats);
1267         implied_output_region = ior;
1268         lfp
1269     } else {
1270         vec![]
1271     };
1272
1273     let output_ty = match decl.output {
1274         ast::Return(ref output) if output.node == ast::TyInfer =>
1275             ty::FnConverging(this.ty_infer(output.span)),
1276         ast::Return(ref output) =>
1277             ty::FnConverging(convert_ty_with_lifetime_elision(this,
1278                                                               implied_output_region,
1279                                                               lifetimes_for_params,
1280                                                               &**output)),
1281         ast::NoReturn(_) => ty::FnDiverging
1282     };
1283
1284     (ty::BareFnTy {
1285         unsafety: unsafety,
1286         abi: abi,
1287         sig: ty::Binder(ty::FnSig {
1288             inputs: self_and_input_tys,
1289             output: output_ty,
1290             variadic: decl.variadic
1291         }),
1292     }, explicit_self_category_result)
1293 }
1294
1295 fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>,
1296                                     RS:RegionScope>(
1297                                     this: &AC,
1298                                     rscope: &RS,
1299                                     self_info: &SelfInfo<'a, 'tcx>)
1300                                     -> ty::ExplicitSelfCategory
1301 {
1302     return match self_info.explicit_self.node {
1303         ast::SelfStatic => ty::StaticExplicitSelfCategory,
1304         ast::SelfValue(_) => ty::ByValueExplicitSelfCategory,
1305         ast::SelfRegion(ref lifetime, mutability, _) => {
1306             let region =
1307                 opt_ast_region_to_region(this,
1308                                          rscope,
1309                                          self_info.explicit_self.span,
1310                                          lifetime);
1311             ty::ByReferenceExplicitSelfCategory(region, mutability)
1312         }
1313         ast::SelfExplicit(ref ast_type, _) => {
1314             let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
1315
1316             // We wish to (for now) categorize an explicit self
1317             // declaration like `self: SomeType` into either `self`,
1318             // `&self`, `&mut self`, or `Box<self>`. We do this here
1319             // by some simple pattern matching. A more precise check
1320             // is done later in `check_method_self_type()`.
1321             //
1322             // Examples:
1323             //
1324             // ```
1325             // impl Foo for &T {
1326             //     // Legal declarations:
1327             //     fn method1(self: &&T); // ByReferenceExplicitSelfCategory
1328             //     fn method2(self: &T); // ByValueExplicitSelfCategory
1329             //     fn method3(self: Box<&T>); // ByBoxExplicitSelfCategory
1330             //
1331             //     // Invalid cases will be caught later by `check_method_self_type`:
1332             //     fn method_err1(self: &mut T); // ByReferenceExplicitSelfCategory
1333             // }
1334             // ```
1335             //
1336             // To do the check we just count the number of "modifiers"
1337             // on each type and compare them. If they are the same or
1338             // the impl has more, we call it "by value". Otherwise, we
1339             // look at the outermost modifier on the method decl and
1340             // call it by-ref, by-box as appropriate. For method1, for
1341             // example, the impl type has one modifier, but the method
1342             // type has two, so we end up with
1343             // ByReferenceExplicitSelfCategory.
1344
1345             let impl_modifiers = count_modifiers(self_info.untransformed_self_ty);
1346             let method_modifiers = count_modifiers(explicit_type);
1347
1348             debug!("determine_explicit_self_category(self_info.untransformed_self_ty={} \
1349                    explicit_type={} \
1350                    modifiers=({},{})",
1351                    self_info.untransformed_self_ty.repr(this.tcx()),
1352                    explicit_type.repr(this.tcx()),
1353                    impl_modifiers,
1354                    method_modifiers);
1355
1356             if impl_modifiers >= method_modifiers {
1357                 ty::ByValueExplicitSelfCategory
1358             } else {
1359                 match explicit_type.sty {
1360                     ty::ty_rptr(r, mt) => ty::ByReferenceExplicitSelfCategory(*r, mt.mutbl),
1361                     ty::ty_uniq(_) => ty::ByBoxExplicitSelfCategory,
1362                     _ => ty::ByValueExplicitSelfCategory,
1363                 }
1364             }
1365         }
1366     };
1367
1368     fn count_modifiers(ty: Ty) -> uint {
1369         match ty.sty {
1370             ty::ty_rptr(_, mt) => count_modifiers(mt.ty) + 1,
1371             ty::ty_uniq(t) => count_modifiers(t) + 1,
1372             _ => 0,
1373         }
1374     }
1375 }
1376
1377 pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
1378     this: &AC,
1379     unsafety: ast::Unsafety,
1380     onceness: ast::Onceness,
1381     bounds: ty::ExistentialBounds,
1382     store: ty::TraitStore,
1383     decl: &ast::FnDecl,
1384     abi: abi::Abi,
1385     expected_sig: Option<ty::FnSig<'tcx>>)
1386     -> ty::ClosureTy<'tcx>
1387 {
1388     debug!("ty_of_closure(expected_sig={})",
1389            expected_sig.repr(this.tcx()));
1390
1391     // new region names that appear inside of the fn decl are bound to
1392     // that function type
1393     let rb = rscope::BindingRscope::new();
1394
1395     let input_tys: Vec<_> = decl.inputs.iter().enumerate().map(|(i, a)| {
1396         let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
1397             // no guarantee that the correct number of expected args
1398             // were supplied
1399             if i < e.inputs.len() {
1400                 Some(e.inputs[i])
1401             } else {
1402                 None
1403             }
1404         });
1405         ty_of_arg(this, &rb, a, expected_arg_ty)
1406     }).collect();
1407
1408     let expected_ret_ty = expected_sig.map(|e| e.output);
1409
1410     let output_ty = match decl.output {
1411         ast::Return(ref output) if output.node == ast::TyInfer && expected_ret_ty.is_some() =>
1412             expected_ret_ty.unwrap(),
1413         ast::Return(ref output) if output.node == ast::TyInfer =>
1414             ty::FnConverging(this.ty_infer(output.span)),
1415         ast::Return(ref output) =>
1416             ty::FnConverging(ast_ty_to_ty(this, &rb, &**output)),
1417         ast::NoReturn(_) => ty::FnDiverging
1418     };
1419
1420     debug!("ty_of_closure: input_tys={}", input_tys.repr(this.tcx()));
1421     debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx()));
1422
1423     ty::ClosureTy {
1424         unsafety: unsafety,
1425         onceness: onceness,
1426         store: store,
1427         bounds: bounds,
1428         abi: abi,
1429         sig: ty::Binder(ty::FnSig {inputs: input_tys,
1430                                    output: output_ty,
1431                                    variadic: decl.variadic}),
1432     }
1433 }
1434
1435 /// Given an existential type like `Foo+'a+Bar`, this routine converts the `'a` and `Bar` intos an
1436 /// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
1437 /// for closures. Eventually this should all be normalized, I think, so that there is no "main
1438 /// trait ref" and instead we just have a flat list of bounds as the existential type.
1439 pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
1440     this: &AC,
1441     rscope: &RS,
1442     span: Span,
1443     principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures
1444     ast_bounds: &[ast::TyParamBound])
1445     -> ty::ExistentialBounds
1446 {
1447     let partitioned_bounds =
1448         partition_bounds(this.tcx(), span, ast_bounds);
1449
1450     conv_existential_bounds_from_partitioned_bounds(
1451         this, rscope, span, principal_trait_ref, partitioned_bounds)
1452 }
1453
1454 fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
1455     this: &AC,
1456     rscope: &RS,
1457     span: Span,
1458     ast_bounds: &[ast::TyParamBound])
1459     -> Ty<'tcx>
1460     where AC: AstConv<'tcx>, RS:RegionScope
1461 {
1462     let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
1463
1464     let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
1465         Some(trait_bound) => {
1466             Some(instantiate_poly_trait_ref(this,
1467                                             rscope,
1468                                             trait_bound,
1469                                             None,
1470                                             AllowEqConstraints::Allow))
1471         }
1472         None => {
1473             this.tcx().sess.span_err(
1474                 span,
1475                 "at least one non-builtin trait is required for an object type");
1476             None
1477         }
1478     };
1479
1480     let bounds =
1481         conv_existential_bounds_from_partitioned_bounds(this,
1482                                                         rscope,
1483                                                         span,
1484                                                         main_trait_bound.as_ref().map(|tr| &**tr),
1485                                                         partitioned_bounds);
1486
1487     match main_trait_bound {
1488         None => ty::mk_err(),
1489         Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
1490     }
1491 }
1492
1493 pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
1494     this: &AC,
1495     rscope: &RS,
1496     span: Span,
1497     principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures
1498     partitioned_bounds: PartitionedBounds)
1499     -> ty::ExistentialBounds
1500     where AC: AstConv<'tcx>, RS:RegionScope
1501 {
1502     let PartitionedBounds { builtin_bounds,
1503                             trait_bounds,
1504                             region_bounds } =
1505         partitioned_bounds;
1506
1507     if !trait_bounds.is_empty() {
1508         let b = &trait_bounds[0];
1509         this.tcx().sess.span_err(
1510             b.trait_ref.path.span,
1511             format!("only the builtin traits can be used \
1512                      as closure or object bounds")[]);
1513     }
1514
1515     let region_bound = compute_region_bound(this,
1516                                             rscope,
1517                                             span,
1518                                             region_bounds.as_slice(),
1519                                             principal_trait_ref,
1520                                             builtin_bounds);
1521
1522     ty::ExistentialBounds {
1523         region_bound: region_bound,
1524         builtin_bounds: builtin_bounds,
1525     }
1526 }
1527
1528 /// Given the bounds on a type parameter / existential type, determines what single region bound
1529 /// (if any) we can use to summarize this type. The basic idea is that we will use the bound the
1530 /// user provided, if they provided one, and otherwise search the supertypes of trait bounds for
1531 /// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
1532 fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
1533                                   span: Span,
1534                                   explicit_region_bounds: &[&ast::Lifetime],
1535                                   principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>,
1536                                   builtin_bounds: ty::BuiltinBounds)
1537                                   -> Option<ty::Region>
1538 {
1539     debug!("compute_opt_region_bound(explicit_region_bounds={}, \
1540            principal_trait_ref={}, builtin_bounds={})",
1541            explicit_region_bounds,
1542            principal_trait_ref.repr(tcx),
1543            builtin_bounds.repr(tcx));
1544
1545     if explicit_region_bounds.len() > 1 {
1546         tcx.sess.span_err(
1547             explicit_region_bounds[1].span,
1548             format!("only a single explicit lifetime bound is permitted").as_slice());
1549     }
1550
1551     if explicit_region_bounds.len() != 0 {
1552         // Explicitly specified region bound. Use that.
1553         let r = explicit_region_bounds[0];
1554         return Some(ast_region_to_region(tcx, r));
1555     }
1556
1557     // No explicit region bound specified. Therefore, examine trait
1558     // bounds and see if we can derive region bounds from those.
1559     let derived_region_bounds =
1560         ty::object_region_bounds(tcx, principal_trait_ref, builtin_bounds);
1561
1562     // If there are no derived region bounds, then report back that we
1563     // can find no region bound.
1564     if derived_region_bounds.len() == 0 {
1565         return None;
1566     }
1567
1568     // If any of the derived region bounds are 'static, that is always
1569     // the best choice.
1570     if derived_region_bounds.iter().any(|r| ty::ReStatic == *r) {
1571         return Some(ty::ReStatic);
1572     }
1573
1574     // Determine whether there is exactly one unique region in the set
1575     // of derived region bounds. If so, use that. Otherwise, report an
1576     // error.
1577     let r = derived_region_bounds[0];
1578     if derived_region_bounds.slice_from(1).iter().any(|r1| r != *r1) {
1579         tcx.sess.span_err(
1580             span,
1581             format!("ambiguous lifetime bound, \
1582                      explicit lifetime bound required")[]);
1583     }
1584     return Some(r);
1585 }
1586
1587 /// A version of `compute_opt_region_bound` for use where some region bound is required
1588 /// (existential types, basically). Reports an error if no region bound can be derived and we are
1589 /// in an `rscope` that does not provide a default.
1590 fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
1591     this: &AC,
1592     rscope: &RS,
1593     span: Span,
1594     region_bounds: &[&ast::Lifetime],
1595     principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for closures
1596     builtin_bounds: ty::BuiltinBounds)
1597     -> ty::Region
1598 {
1599     match compute_opt_region_bound(this.tcx(), span, region_bounds,
1600                                    principal_trait_ref, builtin_bounds) {
1601         Some(r) => r,
1602         None => {
1603             match rscope.default_region_bound(span) {
1604                 Some(r) => { r }
1605                 None => {
1606                     this.tcx().sess.span_err(
1607                         span,
1608                         format!("explicit lifetime bound required")[]);
1609                     ty::ReStatic
1610                 }
1611             }
1612         }
1613     }
1614 }
1615
1616 pub struct PartitionedBounds<'a> {
1617     pub builtin_bounds: ty::BuiltinBounds,
1618     pub trait_bounds: Vec<&'a ast::PolyTraitRef>,
1619     pub region_bounds: Vec<&'a ast::Lifetime>,
1620 }
1621
1622 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
1623 /// general trait bounds, and region bounds.
1624 pub fn partition_bounds<'a>(tcx: &ty::ctxt,
1625                             _span: Span,
1626                             ast_bounds: &'a [ast::TyParamBound])
1627                             -> PartitionedBounds<'a>
1628 {
1629     let mut builtin_bounds = ty::empty_builtin_bounds();
1630     let mut region_bounds = Vec::new();
1631     let mut trait_bounds = Vec::new();
1632     let mut trait_def_ids = DefIdMap::new();
1633     for ast_bound in ast_bounds.iter() {
1634         match *ast_bound {
1635             ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
1636                 match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
1637                     def::DefTrait(trait_did) => {
1638                         match trait_def_ids.get(&trait_did) {
1639                             // Already seen this trait. We forbid
1640                             // duplicates in the list (for some
1641                             // reason).
1642                             Some(span) => {
1643                                 span_err!(
1644                                     tcx.sess, b.trait_ref.path.span, E0127,
1645                                     "trait `{}` already appears in the \
1646                                      list of bounds",
1647                                     b.trait_ref.path.user_string(tcx));
1648                                 tcx.sess.span_note(
1649                                     *span,
1650                                     "previous appearance is here");
1651
1652                                 continue;
1653                             }
1654
1655                             None => { }
1656                         }
1657
1658                         trait_def_ids.insert(trait_did, b.trait_ref.path.span);
1659
1660                         if ty::try_add_builtin_trait(tcx,
1661                                                      trait_did,
1662                                                      &mut builtin_bounds) {
1663                             continue; // success
1664                         }
1665                     }
1666                     _ => {
1667                         // Not a trait? that's an error, but it'll get
1668                         // reported later.
1669                     }
1670                 }
1671                 trait_bounds.push(b);
1672             }
1673             ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {}
1674             ast::RegionTyParamBound(ref l) => {
1675                 region_bounds.push(l);
1676             }
1677         }
1678     }
1679
1680     PartitionedBounds {
1681         builtin_bounds: builtin_bounds,
1682         trait_bounds: trait_bounds,
1683         region_bounds: region_bounds,
1684     }
1685 }