]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/mod.rs
Auto merge of #22541 - Manishearth:rollup, r=Gankro
[rust.git] / src / librustc_typeck / check / mod.rs
1 // Copyright 2012-2015 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
13 # check.rs
14
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function).  Inference is used to supply types wherever they are
18 unknown.
19
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
22
23 - gather: creates type variables to represent the type of each local
24   variable and pattern binding.
25
26 - main: the main pass does the lion's share of the work: it
27   determines the types of all expressions, resolves
28   methods, checks for most invalid conditions, and so forth.  In
29   some cases, where a type is unknown, it may create a type or region
30   variable and use that as the type of an expression.
31
32   In the process of checking, various constraints will be placed on
33   these type variables through the subtyping relationships requested
34   through the `demand` module.  The `infer` module is in charge
35   of resolving those constraints.
36
37 - regionck: after main is complete, the regionck pass goes over all
38   types looking for regions and making sure that they did not escape
39   into places they are not in scope.  This may also influence the
40   final assignments of the various region variables if there is some
41   flexibility.
42
43 - vtable: find and records the impls to use for each trait bound that
44   appears on a type parameter.
45
46 - writeback: writes the final types within a function body, replacing
47   type variables with their final inferred types.  These final types
48   are written into the `tcx.node_types` table, which should *never* contain
49   any reference to a type variable.
50
51 ## Intermediate types
52
53 While type checking a function, the intermediate types for the
54 expressions, blocks, and so forth contained within the function are
55 stored in `fcx.node_types` and `fcx.item_substs`.  These types
56 may contain unresolved type variables.  After type checking is
57 complete, the functions in the writeback module are used to take the
58 types from this table, resolve them, and then write them into their
59 permanent home in the type context `ccx.tcx`.
60
61 This means that during inferencing you should use `fcx.write_ty()`
62 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63 nodes within the function.
64
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
67
68 n.b.: A type variable is not the same thing as a type parameter.  A
69 type variable is rather an "instance" of a type parameter: that is,
70 given a generic function `fn foo<T>(t: T)`: while checking the
71 function `foo`, the type `ty_param(0)` refers to the type `T`, which
72 is treated in abstract.  When `foo()` is called, however, `T` will be
73 substituted for a fresh type variable `N`.  This variable will
74 eventually be resolved to some concrete type (which might itself be
75 type parameter).
76
77 */
78
79 pub use self::LvaluePreference::*;
80 pub use self::Expectation::*;
81 pub use self::compare_method::compare_impl_method;
82 use self::IsBinopAssignment::*;
83 use self::TupleArgumentsFlag::*;
84
85 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
86 use check::_match::pat_ctxt;
87 use fmt_macros::{Parser, Piece, Position};
88 use middle::{const_eval, def};
89 use middle::infer;
90 use middle::mem_categorization as mc;
91 use middle::mem_categorization::McResult;
92 use middle::pat_util::{self, pat_id_map};
93 use middle::region::{self, CodeExtent};
94 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
95 use middle::traits;
96 use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
97 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
98 use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
99 use middle::ty::liberate_late_bound_regions;
100 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
101 use middle::ty_fold::{TypeFolder, TypeFoldable};
102 use rscope::RegionScope;
103 use session::Session;
104 use {CrateCtxt, lookup_def_ccx, require_same_types};
105 use TypeAndSubsts;
106 use lint;
107 use util::common::{block_query, indenter, loop_query};
108 use util::ppaux::{self, Repr};
109 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
110 use util::lev_distance::lev_distance;
111
112 use std::cell::{Cell, Ref, RefCell};
113 use std::collections::hash_map::Entry::{Occupied, Vacant};
114 use std::mem::replace;
115 use std::rc::Rc;
116 use std::iter::repeat;
117 use std::slice;
118 use syntax::{self, abi, attr};
119 use syntax::attr::AttrMetaMethods;
120 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
121 use syntax::ast_util::{self, local_def, PostExpansionMethod};
122 use syntax::codemap::{self, Span};
123 use syntax::owned_slice::OwnedSlice;
124 use syntax::parse::token;
125 use syntax::print::pprust;
126 use syntax::ptr::P;
127 use syntax::visit::{self, Visitor};
128
129 mod assoc;
130 pub mod dropck;
131 pub mod _match;
132 pub mod vtable;
133 pub mod writeback;
134 pub mod implicator;
135 pub mod regionck;
136 pub mod coercion;
137 pub mod demand;
138 pub mod method;
139 mod upvar;
140 pub mod wf;
141 mod closure;
142 mod callee;
143 mod compare_method;
144
145 /// closures defined within the function.  For example:
146 ///
147 ///     fn foo() {
148 ///         bar(move|| { ... })
149 ///     }
150 ///
151 /// Here, the function `foo()` and the closure passed to
152 /// `bar()` will each have their own `FnCtxt`, but they will
153 /// share the inherited fields.
154 pub struct Inherited<'a, 'tcx: 'a> {
155     infcx: infer::InferCtxt<'a, 'tcx>,
156     locals: RefCell<NodeMap<Ty<'tcx>>>,
157     param_env: ty::ParameterEnvironment<'a, 'tcx>,
158
159     // Temporary tables:
160     node_types: RefCell<NodeMap<Ty<'tcx>>>,
161     item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
162     adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
163     method_map: MethodMap<'tcx>,
164     upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
165     closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
166     closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
167     object_cast_map: ObjectCastMap<'tcx>,
168
169     // A mapping from each fn's id to its signature, with all bound
170     // regions replaced with free ones. Unlike the other tables, this
171     // one is never copied into the tcx: it is only used by regionck.
172     fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
173
174     // Tracks trait obligations incurred during this function body.
175     fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
176
177     // When we process a call like `c()` where `c` is a closure type,
178     // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
179     // `FnOnce` closure. In that case, we defer full resolution of the
180     // call until upvar inference can kick in and make the
181     // decision. We keep these deferred resolutions grouped by the
182     // def-id of the closure, so that once we decide, we can easily go
183     // back and process them.
184     deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
185 }
186
187 trait DeferredCallResolution<'tcx> {
188     fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
189 }
190
191 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
192
193 /// When type-checking an expression, we propagate downward
194 /// whatever type hint we are able in the form of an `Expectation`.
195 #[derive(Copy)]
196 enum Expectation<'tcx> {
197     /// We know nothing about what type this expression should have.
198     NoExpectation,
199
200     /// This expression should have the type given (or some subtype)
201     ExpectHasType(Ty<'tcx>),
202
203     /// This expression will be cast to the `Ty`
204     ExpectCastableToType(Ty<'tcx>),
205
206     /// This rvalue expression will be wrapped in `&` or `Box` and coerced
207     /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
208     ExpectRvalueLikeUnsized(Ty<'tcx>),
209 }
210
211 impl<'tcx> Expectation<'tcx> {
212     // Disregard "castable to" expectations because they
213     // can lead us astray. Consider for example `if cond
214     // {22} else {c} as u8` -- if we propagate the
215     // "castable to u8" constraint to 22, it will pick the
216     // type 22u8, which is overly constrained (c might not
217     // be a u8). In effect, the problem is that the
218     // "castable to" expectation is not the tightest thing
219     // we can say, so we want to drop it in this case.
220     // The tightest thing we can say is "must unify with
221     // else branch". Note that in the case of a "has type"
222     // constraint, this limitation does not hold.
223
224     // If the expected type is just a type variable, then don't use
225     // an expected type. Otherwise, we might write parts of the type
226     // when checking the 'then' block which are incompatible with the
227     // 'else' branch.
228     fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
229         match *self {
230             ExpectHasType(ety) => {
231                 let ety = fcx.infcx().shallow_resolve(ety);
232                 if !ty::type_is_ty_var(ety) {
233                     ExpectHasType(ety)
234                 } else {
235                     NoExpectation
236                 }
237             }
238             ExpectRvalueLikeUnsized(ety) => {
239                 ExpectRvalueLikeUnsized(ety)
240             }
241             _ => NoExpectation
242         }
243     }
244 }
245
246 #[derive(Copy, Clone)]
247 pub struct UnsafetyState {
248     pub def: ast::NodeId,
249     pub unsafety: ast::Unsafety,
250     from_fn: bool
251 }
252
253 impl UnsafetyState {
254     pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
255         UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
256     }
257
258     pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
259         match self.unsafety {
260             // If this unsafe, then if the outer function was already marked as
261             // unsafe we shouldn't attribute the unsafe'ness to the block. This
262             // way the block can be warned about instead of ignoring this
263             // extraneous block (functions are never warned about).
264             ast::Unsafety::Unsafe if self.from_fn => *self,
265
266             unsafety => {
267                 let (unsafety, def) = match blk.rules {
268                     ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
269                     ast::DefaultBlock => (unsafety, self.def),
270                 };
271                 UnsafetyState{ def: def,
272                              unsafety: unsafety,
273                              from_fn: false }
274             }
275         }
276     }
277 }
278
279 /// Whether `check_binop` is part of an assignment or not.
280 /// Used to know whether we allow user overloads and to print
281 /// better messages on error.
282 #[derive(PartialEq)]
283 enum IsBinopAssignment{
284     SimpleBinop,
285     BinopAssignment,
286 }
287
288 #[derive(Clone)]
289 pub struct FnCtxt<'a, 'tcx: 'a> {
290     body_id: ast::NodeId,
291
292     // This flag is set to true if, during the writeback phase, we encounter
293     // a type error in this function.
294     writeback_errors: Cell<bool>,
295
296     // Number of errors that had been reported when we started
297     // checking this function. On exit, if we find that *more* errors
298     // have been reported, we will skip regionck and other work that
299     // expects the types within the function to be consistent.
300     err_count_on_creation: uint,
301
302     ret_ty: ty::FnOutput<'tcx>,
303
304     ps: RefCell<UnsafetyState>,
305
306     inh: &'a Inherited<'a, 'tcx>,
307
308     ccx: &'a CrateCtxt<'a, 'tcx>,
309 }
310
311 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
312     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
313         let ty = self.node_ty(id);
314         self.resolve_type_vars_or_error(&ty)
315     }
316     fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
317         let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
318         self.resolve_type_vars_or_error(&ty)
319     }
320     fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
321         let ty = self.infcx().resolve_type_vars_if_possible(&ty);
322         !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
323     }
324     fn node_method_ty(&self, method_call: ty::MethodCall)
325                       -> Option<Ty<'tcx>> {
326         self.inh.method_map.borrow()
327                            .get(&method_call)
328                            .map(|method| method.ty)
329                            .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
330     }
331     fn node_method_origin(&self, method_call: ty::MethodCall)
332                           -> Option<ty::MethodOrigin<'tcx>>
333     {
334         self.inh.method_map.borrow()
335                            .get(&method_call)
336                            .map(|method| method.origin.clone())
337     }
338     fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
339         &self.inh.adjustments
340     }
341     fn is_method_call(&self, id: ast::NodeId) -> bool {
342         self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
343     }
344     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
345         self.param_env().temporary_scope(rvalue_id)
346     }
347     fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
348         self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
349     }
350 }
351
352 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
353     fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
354         &self.inh.param_env
355     }
356
357     fn closure_kind(&self,
358                     def_id: ast::DefId)
359                     -> Option<ty::ClosureKind>
360     {
361         self.inh.closure_kinds.borrow().get(&def_id).cloned()
362     }
363
364     fn closure_type(&self,
365                     def_id: ast::DefId,
366                     substs: &subst::Substs<'tcx>)
367                     -> ty::ClosureTy<'tcx>
368     {
369         self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs)
370     }
371
372     fn closure_upvars(&self,
373                       def_id: ast::DefId,
374                       substs: &Substs<'tcx>)
375                       -> Option<Vec<ty::ClosureUpvar<'tcx>>>
376     {
377         ty::closure_upvars(self, def_id, substs)
378     }
379 }
380
381 impl<'a, 'tcx> Inherited<'a, 'tcx> {
382     fn new(tcx: &'a ty::ctxt<'tcx>,
383            param_env: ty::ParameterEnvironment<'a, 'tcx>)
384            -> Inherited<'a, 'tcx> {
385         Inherited {
386             infcx: infer::new_infer_ctxt(tcx),
387             locals: RefCell::new(NodeMap()),
388             param_env: param_env,
389             node_types: RefCell::new(NodeMap()),
390             item_substs: RefCell::new(NodeMap()),
391             adjustments: RefCell::new(NodeMap()),
392             method_map: RefCell::new(FnvHashMap()),
393             object_cast_map: RefCell::new(NodeMap()),
394             upvar_capture_map: RefCell::new(FnvHashMap()),
395             closure_tys: RefCell::new(DefIdMap()),
396             closure_kinds: RefCell::new(DefIdMap()),
397             fn_sig_map: RefCell::new(NodeMap()),
398             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
399             deferred_call_resolutions: RefCell::new(DefIdMap()),
400         }
401     }
402
403     fn normalize_associated_types_in<T>(&self,
404                                         typer: &ty::ClosureTyper<'tcx>,
405                                         span: Span,
406                                         body_id: ast::NodeId,
407                                         value: &T)
408                                         -> T
409         where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
410     {
411         let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
412         assoc::normalize_associated_types_in(&self.infcx,
413                                              typer,
414                                              &mut *fulfillment_cx, span,
415                                              body_id,
416                                              value)
417     }
418
419 }
420
421 // Used by check_const and check_enum_variants
422 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
423                                inh: &'a Inherited<'a, 'tcx>,
424                                rty: ty::FnOutput<'tcx>,
425                                body_id: ast::NodeId)
426                                -> FnCtxt<'a, 'tcx> {
427     FnCtxt {
428         body_id: body_id,
429         writeback_errors: Cell::new(false),
430         err_count_on_creation: ccx.tcx.sess.err_count(),
431         ret_ty: rty,
432         ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
433         inh: inh,
434         ccx: ccx
435     }
436 }
437
438 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
439                                     -> Inherited<'a, 'tcx> {
440     // It's kind of a kludge to manufacture a fake function context
441     // and statement context, but we might as well do write the code only once
442     let param_env = ty::empty_parameter_environment(ccx.tcx);
443     Inherited::new(ccx.tcx, param_env)
444 }
445
446 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
447
448 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
449     fn visit_item(&mut self, i: &'tcx ast::Item) {
450         check_item(self.ccx, i);
451         visit::walk_item(self, i);
452     }
453
454     fn visit_ty(&mut self, t: &'tcx ast::Ty) {
455         match t.node {
456             ast::TyFixedLengthVec(_, ref expr) => {
457                 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
458             }
459             _ => {}
460         }
461
462         visit::walk_ty(self, t);
463     }
464 }
465
466 pub fn check_item_types(ccx: &CrateCtxt) {
467     let krate = ccx.tcx.map.krate();
468     let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
469     visit::walk_crate(&mut visit, krate);
470
471     // If types are not well-formed, it leads to all manner of errors
472     // downstream, so stop reporting errors at this point.
473     ccx.tcx.sess.abort_if_errors();
474
475     let mut visit = CheckItemTypesVisitor { ccx: ccx };
476     visit::walk_crate(&mut visit, krate);
477
478     ccx.tcx.sess.abort_if_errors();
479 }
480
481 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
482                            decl: &'tcx ast::FnDecl,
483                            body: &'tcx ast::Block,
484                            fn_id: ast::NodeId,
485                            fn_span: Span,
486                            raw_fty: Ty<'tcx>,
487                            param_env: ty::ParameterEnvironment<'a, 'tcx>)
488 {
489     match raw_fty.sty {
490         ty::ty_bare_fn(_, ref fn_ty) => {
491             let inh = Inherited::new(ccx.tcx, param_env);
492
493             // Compute the fty from point of view of inside fn.
494             let fn_sig =
495                 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
496             let fn_sig =
497                 liberate_late_bound_regions(ccx.tcx,
498                                             region::DestructionScopeData::new(body.id),
499                                             &fn_sig);
500             let fn_sig =
501                 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
502
503             let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
504                                decl, fn_id, body, &inh);
505
506             vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
507             upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
508             vtable::select_all_fcx_obligations_or_error(&fcx);
509             regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
510             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
511         }
512         _ => ccx.tcx.sess.impossible_case(body.span,
513                                  "check_bare_fn: function type expected")
514     }
515 }
516
517 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
518     fcx: &'a FnCtxt<'a, 'tcx>
519 }
520
521 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
522     fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
523         match ty_opt {
524             None => {
525                 // infer the variable's type
526                 let var_ty = self.fcx.infcx().next_ty_var();
527                 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
528                 var_ty
529             }
530             Some(typ) => {
531                 // take type that the user specified
532                 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
533                 typ
534             }
535         }
536     }
537 }
538
539 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
540     // Add explicitly-declared locals.
541     fn visit_local(&mut self, local: &'tcx ast::Local) {
542         let o_ty = match local.ty {
543             Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
544             None => None
545         };
546         self.assign(local.span, local.id, o_ty);
547         debug!("Local variable {} is assigned type {}",
548                self.fcx.pat_to_string(&*local.pat),
549                self.fcx.infcx().ty_to_string(
550                    self.fcx.inh.locals.borrow()[local.id].clone()));
551         visit::walk_local(self, local);
552     }
553
554     // Add pattern bindings.
555     fn visit_pat(&mut self, p: &'tcx ast::Pat) {
556         if let ast::PatIdent(_, ref path1, _) = p.node {
557             if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
558                 let var_ty = self.assign(p.span, p.id, None);
559
560                 self.fcx.require_type_is_sized(var_ty, p.span,
561                                                traits::VariableType(p.id));
562
563                 debug!("Pattern binding {} is assigned to {} with type {}",
564                        token::get_ident(path1.node),
565                        self.fcx.infcx().ty_to_string(
566                            self.fcx.inh.locals.borrow()[p.id].clone()),
567                        var_ty.repr(self.fcx.tcx()));
568             }
569         }
570         visit::walk_pat(self, p);
571     }
572
573     fn visit_block(&mut self, b: &'tcx ast::Block) {
574         // non-obvious: the `blk` variable maps to region lb, so
575         // we have to keep this up-to-date.  This
576         // is... unfortunate.  It'd be nice to not need this.
577         visit::walk_block(self, b);
578     }
579
580     // Since an expr occurs as part of the type fixed size arrays we
581     // need to record the type for that node
582     fn visit_ty(&mut self, t: &'tcx ast::Ty) {
583         match t.node {
584             ast::TyFixedLengthVec(ref ty, ref count_expr) => {
585                 self.visit_ty(&**ty);
586                 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
587             }
588             _ => visit::walk_ty(self, t)
589         }
590     }
591
592     // Don't descend into fns and items
593     fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
594                 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
595     fn visit_item(&mut self, _: &ast::Item) { }
596
597 }
598
599 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
600 /// body and returns the function context used for that purpose, since in the case of a fn item
601 /// there is still a bit more to do.
602 ///
603 /// * ...
604 /// * inherited: other fields inherited from the enclosing fn (if any)
605 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
606                       unsafety: ast::Unsafety,
607                       unsafety_id: ast::NodeId,
608                       fn_sig: &ty::FnSig<'tcx>,
609                       decl: &'tcx ast::FnDecl,
610                       fn_id: ast::NodeId,
611                       body: &'tcx ast::Block,
612                       inherited: &'a Inherited<'a, 'tcx>)
613                       -> FnCtxt<'a, 'tcx>
614 {
615     let tcx = ccx.tcx;
616     let err_count_on_creation = tcx.sess.err_count();
617
618     let arg_tys = &fn_sig.inputs[];
619     let ret_ty = fn_sig.output;
620
621     debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
622            arg_tys.repr(tcx),
623            ret_ty.repr(tcx),
624            fn_id);
625
626     // Create the function context.  This is either derived from scratch or,
627     // in the case of function expressions, based on the outer context.
628     let fcx = FnCtxt {
629         body_id: body.id,
630         writeback_errors: Cell::new(false),
631         err_count_on_creation: err_count_on_creation,
632         ret_ty: ret_ty,
633         ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
634         inh: inherited,
635         ccx: ccx
636     };
637
638     // Remember return type so that regionck can access it later.
639     let mut fn_sig_tys: Vec<Ty> =
640         arg_tys.iter()
641         .cloned()
642         .collect();
643
644     if let ty::FnConverging(ret_ty) = ret_ty {
645         fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
646         fn_sig_tys.push(ret_ty);
647     }
648
649     debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
650            fn_id,
651            fn_sig_tys.repr(tcx));
652
653     inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
654
655     {
656         let mut visit = GatherLocalsVisitor { fcx: &fcx, };
657
658         // Add formal parameters.
659         for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
660             // Create type variables for each argument.
661             pat_util::pat_bindings(
662                 &tcx.def_map,
663                 &*input.pat,
664                 |_bm, pat_id, sp, _path| {
665                     let var_ty = visit.assign(sp, pat_id, None);
666                     fcx.require_type_is_sized(var_ty, sp,
667                                               traits::VariableType(pat_id));
668                 });
669
670             // Check the pattern.
671             let pcx = pat_ctxt {
672                 fcx: &fcx,
673                 map: pat_id_map(&tcx.def_map, &*input.pat),
674             };
675             _match::check_pat(&pcx, &*input.pat, *arg_ty);
676         }
677
678         visit.visit_block(body);
679     }
680
681     check_block_with_expected(&fcx, body, match ret_ty {
682         ty::FnConverging(result_type) => ExpectHasType(result_type),
683         ty::FnDiverging => NoExpectation
684     });
685
686     for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
687         fcx.write_ty(input.id, *arg);
688     }
689
690     fcx
691 }
692
693 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
694     let tcx = ccx.tcx;
695
696     check_representable(tcx, span, id, "struct");
697     check_instantiable(tcx, span, id);
698
699     if ty::lookup_simd(tcx, local_def(id)) {
700         check_simd(tcx, span, id);
701     }
702 }
703
704 pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
705     debug!("check_item(it.id={}, it.ident={})",
706            it.id,
707            ty::item_path_str(ccx.tcx, local_def(it.id)));
708     let _indenter = indenter();
709
710     match it.node {
711       ast::ItemStatic(_, _, ref e) |
712       ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
713       ast::ItemEnum(ref enum_definition, _) => {
714         check_enum_variants(ccx,
715                             it.span,
716                             &enum_definition.variants[],
717                             it.id);
718       }
719       ast::ItemFn(ref decl, _, _, _, ref body) => {
720         let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
721         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
722         check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
723       }
724       ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
725         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
726
727         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
728
729           match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
730               Some(impl_trait_ref) => {
731                 check_impl_items_against_trait(ccx,
732                                                it.span,
733                                                &*impl_trait_ref,
734                                                impl_items);
735               }
736               None => { }
737           }
738
739         for impl_item in impl_items {
740             match *impl_item {
741                 ast::MethodImplItem(ref m) => {
742                     check_method_body(ccx, &impl_pty.generics, &**m);
743                 }
744                 ast::TypeImplItem(_) => {
745                     // Nothing to do here.
746                 }
747             }
748         }
749
750       }
751       ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
752         check_trait_on_unimplemented(ccx, generics, it);
753         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
754         for trait_method in trait_methods {
755             match *trait_method {
756                 RequiredMethod(..) => {
757                     // Nothing to do, since required methods don't have
758                     // bodies to check.
759                 }
760                 ProvidedMethod(ref m) => {
761                     check_method_body(ccx, &trait_def.generics, &**m);
762                 }
763                 TypeTraitItem(_) => {
764                     // Nothing to do.
765                 }
766             }
767         }
768       }
769       ast::ItemStruct(..) => {
770         check_struct(ccx, it.id, it.span);
771       }
772       ast::ItemTy(ref t, ref generics) => {
773         let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
774         check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
775       }
776       ast::ItemForeignMod(ref m) => {
777         if m.abi == abi::RustIntrinsic {
778             for item in &m.items {
779                 check_intrinsic_type(ccx, &**item);
780             }
781         } else {
782             for item in &m.items {
783                 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
784                 if !pty.generics.types.is_empty() {
785                     span_err!(ccx.tcx.sess, item.span, E0044,
786                         "foreign items may not have type parameters");
787                 }
788
789                 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
790                     if fn_decl.variadic && m.abi != abi::C {
791                         span_err!(ccx.tcx.sess, item.span, E0045,
792                                   "variadic function must have C calling convention");
793                     }
794                 }
795             }
796         }
797       }
798       _ => {/* nothing to do */ }
799     }
800 }
801
802 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
803                                generics: &ast::Generics,
804                                item: &ast::Item) {
805     if let Some(ref attr) = item.attrs.iter().find(|a| {
806         a.check_name("rustc_on_unimplemented")
807     }) {
808         if let Some(ref istring) = attr.value_str() {
809             let parser = Parser::new(&istring);
810             let types = &*generics.ty_params;
811             for token in parser {
812                 match token {
813                     Piece::String(_) => (), // Normal string, no need to check it
814                     Piece::NextArgument(a) => match a.position {
815                         // `{Self}` is allowed
816                         Position::ArgumentNamed(s) if s == "Self" => (),
817                         // So is `{A}` if A is a type parameter
818                         Position::ArgumentNamed(s) => match types.iter().find(|t| {
819                             t.ident.as_str() == s
820                         }) {
821                             Some(_) => (),
822                             None => {
823                                 span_err!(ccx.tcx.sess, attr.span, E0230,
824                                                  "there is no type parameter \
825                                                           {} on trait {}",
826                                                            s, item.ident.as_str());
827                             }
828                         },
829                         // `{:1}` and `{}` are not to be used
830                         Position::ArgumentIs(_) | Position::ArgumentNext => {
831                             span_err!(ccx.tcx.sess, attr.span, E0231,
832                                                   "only named substitution \
833                                                    parameters are allowed");
834                         }
835                     }
836                 }
837             }
838         } else {
839             span_err!(ccx.tcx.sess, attr.span, E0232,
840                                   "this attribute must have a value, \
841                                    eg `#[rustc_on_unimplemented = \"foo\"]`")
842         }
843     }
844 }
845
846 /// Type checks a method body.
847 ///
848 /// # Parameters
849 ///
850 /// * `item_generics`: generics defined on the impl/trait that contains
851 ///   the method
852 /// * `self_bound`: bound for the `Self` type parameter, if any
853 /// * `method`: the method definition
854 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
855                                item_generics: &ty::Generics<'tcx>,
856                                method: &'tcx ast::Method) {
857     debug!("check_method_body(item_generics={}, method.id={})",
858             item_generics.repr(ccx.tcx),
859             method.id);
860     let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
861
862     let fty = ty::node_id_to_type(ccx.tcx, method.id);
863     debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
864
865     check_bare_fn(ccx,
866                   &*method.pe_fn_decl(),
867                   &*method.pe_body(),
868                   method.id,
869                   method.span,
870                   fty,
871                   param_env);
872 }
873
874 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
875                                             impl_span: Span,
876                                             impl_trait_ref: &ty::TraitRef<'tcx>,
877                                             impl_items: &[ast::ImplItem]) {
878     // Locate trait methods
879     let tcx = ccx.tcx;
880     let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
881
882     // Check existing impl methods to see if they are both present in trait
883     // and compatible with trait signature
884     for impl_item in impl_items {
885         match *impl_item {
886             ast::MethodImplItem(ref impl_method) => {
887                 let impl_method_def_id = local_def(impl_method.id);
888                 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
889                                                           impl_method_def_id);
890
891                 // If this is an impl of a trait method, find the
892                 // corresponding method definition in the trait.
893                 let opt_trait_method_ty =
894                     trait_items.iter()
895                                .find(|ti| ti.name() == impl_item_ty.name());
896                 match opt_trait_method_ty {
897                     Some(trait_method_ty) => {
898                         match (trait_method_ty, &impl_item_ty) {
899                             (&ty::MethodTraitItem(ref trait_method_ty),
900                              &ty::MethodTraitItem(ref impl_method_ty)) => {
901                                 compare_impl_method(ccx.tcx,
902                                                     &**impl_method_ty,
903                                                     impl_method.span,
904                                                     impl_method.pe_body().id,
905                                                     &**trait_method_ty,
906                                                     &*impl_trait_ref);
907                             }
908                             _ => {
909                                 // This is span_bug as it should have already been
910                                 // caught in resolve.
911                                 tcx.sess.span_bug(
912                                     impl_method.span,
913                                     &format!("item `{}` is of a different kind from its trait `{}`",
914                                              token::get_name(impl_item_ty.name()),
915                                              impl_trait_ref.repr(tcx)));
916                             }
917                         }
918                     }
919                     None => {
920                         // This is span_bug as it should have already been
921                         // caught in resolve.
922                         tcx.sess.span_bug(
923                             impl_method.span,
924                             &format!("method `{}` is not a member of trait `{}`",
925                                      token::get_name(impl_item_ty.name()),
926                                      impl_trait_ref.repr(tcx)));
927                     }
928                 }
929             }
930             ast::TypeImplItem(ref typedef) => {
931                 let typedef_def_id = local_def(typedef.id);
932                 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
933                                                         typedef_def_id);
934
935                 // If this is an impl of an associated type, find the
936                 // corresponding type definition in the trait.
937                 let opt_associated_type =
938                     trait_items.iter()
939                                .find(|ti| ti.name() == typedef_ty.name());
940                 match opt_associated_type {
941                     Some(associated_type) => {
942                         match (associated_type, &typedef_ty) {
943                             (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
944                             _ => {
945                                 // This is `span_bug` as it should have
946                                 // already been caught in resolve.
947                                 tcx.sess.span_bug(
948                                     typedef.span,
949                                     &format!("item `{}` is of a different kind from its trait `{}`",
950                                              token::get_name(typedef_ty.name()),
951                                              impl_trait_ref.repr(tcx)));
952                             }
953                         }
954                     }
955                     None => {
956                         // This is `span_bug` as it should have already been
957                         // caught in resolve.
958                         tcx.sess.span_bug(
959                             typedef.span,
960                             &format!(
961                                 "associated type `{}` is not a member of \
962                                  trait `{}`",
963                                 token::get_name(typedef_ty.name()),
964                                 impl_trait_ref.repr(tcx)));
965                     }
966                 }
967             }
968         }
969     }
970
971     // Check for missing items from trait
972     let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
973     let mut missing_methods = Vec::new();
974     for trait_item in &*trait_items {
975         match *trait_item {
976             ty::MethodTraitItem(ref trait_method) => {
977                 let is_implemented =
978                     impl_items.iter().any(|ii| {
979                         match *ii {
980                             ast::MethodImplItem(ref m) => {
981                                 m.pe_ident().name == trait_method.name
982                             }
983                             ast::TypeImplItem(_) => false,
984                         }
985                     });
986                 let is_provided =
987                     provided_methods.iter().any(|m| m.name == trait_method.name);
988                 if !is_implemented && !is_provided {
989                     missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
990                 }
991             }
992             ty::TypeTraitItem(ref associated_type) => {
993                 let is_implemented = impl_items.iter().any(|ii| {
994                     match *ii {
995                         ast::TypeImplItem(ref typedef) => {
996                             typedef.ident.name == associated_type.name
997                         }
998                         ast::MethodImplItem(_) => false,
999                     }
1000                 });
1001                 if !is_implemented {
1002                     missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1003                 }
1004             }
1005         }
1006     }
1007
1008     if !missing_methods.is_empty() {
1009         span_err!(tcx.sess, impl_span, E0046,
1010             "not all trait items implemented, missing: {}",
1011             missing_methods.connect(", "));
1012     }
1013 }
1014
1015 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1016                                          span: Span,
1017                                          t_span: Span,
1018                                          e_span: Span,
1019                                          t_1: Ty<'tcx>,
1020                                          t_e: Ty<'tcx>,
1021                                          id: ast::NodeId) {
1022     let tstr = fcx.infcx().ty_to_string(t_1);
1023     fcx.type_error_message(span, |actual| {
1024         format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1025     }, t_e, None);
1026     match t_e.sty {
1027         ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1028             let mtstr = match mt {
1029                 ast::MutMutable => "mut ",
1030                 ast::MutImmutable => ""
1031             };
1032             if ty::type_is_trait(t_1) {
1033                 span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
1034             } else {
1035                 span_help!(fcx.tcx().sess, span,
1036                            "consider using an implicit coercion to `&{}{}` instead",
1037                            mtstr, tstr);
1038             }
1039         }
1040         ty::ty_uniq(..) => {
1041             span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
1042         }
1043         _ => {
1044             span_help!(fcx.tcx().sess, e_span,
1045                        "consider using a box or reference as appropriate");
1046         }
1047     }
1048     fcx.write_error(id);
1049 }
1050
1051
1052 fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1053                               span: Span,
1054                               t_1: Ty<'tcx>,
1055                               t_e: Ty<'tcx>,
1056                               e: &ast::Expr) {
1057     fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1058                                           span: Span,
1059                                           t_1: Ty<'tcx>,
1060                                           t_e: Ty<'tcx>) {
1061         fcx.type_error_message(span, |actual| {
1062             format!("illegal cast; cast through an \
1063                     integer first: `{}` as `{}`",
1064                     actual,
1065                     fcx.infcx().ty_to_string(t_1))
1066         }, t_e, None);
1067     }
1068
1069     let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1070     let t_e_is_scalar = ty::type_is_scalar(t_e);
1071     let t_e_is_integral = ty::type_is_integral(t_e);
1072     let t_e_is_float = ty::type_is_floating_point(t_e);
1073     let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
1074
1075     let t_1_is_scalar = ty::type_is_scalar(t_1);
1076     let t_1_is_char = ty::type_is_char(t_1);
1077     let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1078     let t_1_is_float = ty::type_is_floating_point(t_1);
1079
1080     // casts to scalars other than `char` and `bare fn` are trivial
1081     let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1082
1083     if t_e_is_bare_fn_item && t_1_is_bare_fn {
1084         demand::coerce(fcx, e.span, t_1, &*e);
1085     } else if t_1_is_char {
1086         let t_e = fcx.infcx().shallow_resolve(t_e);
1087         if t_e.sty != ty::ty_uint(ast::TyU8) {
1088             fcx.type_error_message(span, |actual| {
1089                 format!("only `u8` can be cast as \
1090                          `char`, not `{}`", actual)
1091             }, t_e, None);
1092         }
1093     } else if t_1.sty == ty::ty_bool {
1094         span_err!(fcx.tcx().sess, span, E0054,
1095             "cannot cast as `bool`, compare with zero instead");
1096     } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
1097         t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
1098         // Casts to float must go through an integer or boolean
1099         cast_through_integer_err(fcx, span, t_1, t_e)
1100     } else if t_e_is_c_enum && t_1_is_trivial {
1101         if ty::type_is_unsafe_ptr(t_1) {
1102             // ... and likewise with C enum -> *T
1103             cast_through_integer_err(fcx, span, t_1, t_e)
1104         }
1105         // casts from C-like enums are allowed
1106     } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1107         fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1108                                       t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1109             match t1.sty {
1110                 ty::ty_vec(_, Some(_)) => {}
1111                 _ => return false
1112             }
1113             if ty::type_needs_infer(t2) {
1114                 // This prevents this special case from going off when casting
1115                 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1116                 // #14893.)
1117                 return false
1118             }
1119
1120             let el = ty::sequence_element_type(fcx.tcx(), t1);
1121             infer::mk_eqty(fcx.infcx(),
1122                            false,
1123                            infer::Misc(sp),
1124                            el,
1125                            t2).is_ok()
1126         }
1127
1128         // Due to the limitations of LLVM global constants,
1129         // region pointers end up pointing at copies of
1130         // vector elements instead of the original values.
1131         // To allow unsafe pointers to work correctly, we
1132         // need to special-case obtaining an unsafe pointer
1133         // from a region pointer to a vector.
1134
1135         /* this cast is only allowed from &[T, ..n] to *T or
1136         &T to *T. */
1137         match (&t_e.sty, &t_1.sty) {
1138             (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1139              &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1140             if types_compatible(fcx, e.span, mt1, mt2) => {
1141                 /* this case is allowed */
1142             }
1143             _ => {
1144                 demand::coerce(fcx, e.span, t_1, &*e);
1145             }
1146         }
1147     } else if !(t_e_is_scalar && t_1_is_trivial) {
1148         /*
1149         If more type combinations should be supported than are
1150         supported here, then file an enhancement issue and
1151         record the issue number in this comment.
1152         */
1153         fcx.type_error_message(span, |actual| {
1154             format!("non-scalar cast: `{}` as `{}`",
1155                     actual,
1156                     fcx.infcx().ty_to_string(t_1))
1157         }, t_e, None);
1158     }
1159 }
1160
1161 fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
1162                        cast_expr: &ast::Expr,
1163                        e: &'tcx ast::Expr,
1164                        t: &ast::Ty) {
1165     let id = cast_expr.id;
1166     let span = cast_expr.span;
1167
1168     // Find the type of `e`. Supply hints based on the type we are casting to,
1169     // if appropriate.
1170     let t_1 = fcx.to_ty(t);
1171     let t_1 = structurally_resolved_type(fcx, span, t_1);
1172
1173     check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1174
1175     let t_e = fcx.expr_ty(e);
1176
1177     debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1178     debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1179
1180     if ty::type_is_error(t_e) {
1181         fcx.write_error(id);
1182         return
1183     }
1184
1185     if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1186         report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
1187         return
1188     }
1189
1190     if ty::type_is_trait(t_1) {
1191         // This will be looked up later on.
1192         vtable::check_object_cast(fcx, cast_expr, e, t_1);
1193         fcx.write_ty(id, t_1);
1194         return
1195     }
1196
1197     let t_1 = structurally_resolved_type(fcx, span, t_1);
1198     let t_e = structurally_resolved_type(fcx, span, t_e);
1199
1200     check_cast_inner(fcx, span, t_1, t_e, e);
1201     fcx.write_ty(id, t_1);
1202 }
1203
1204 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1205     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1206
1207     fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1208         ty::lookup_item_type(self.tcx(), id)
1209     }
1210
1211     fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1212         ty::lookup_trait_def(self.tcx(), id)
1213     }
1214
1215     fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1216         Some(&self.inh.param_env.free_substs)
1217     }
1218
1219     fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1220         self.infcx().next_ty_var()
1221     }
1222
1223     fn projected_ty_from_poly_trait_ref(&self,
1224                                         span: Span,
1225                                         poly_trait_ref: ty::PolyTraitRef<'tcx>,
1226                                         item_name: ast::Name)
1227                                         -> Ty<'tcx>
1228     {
1229         let (trait_ref, _) =
1230             self.infcx().replace_late_bound_regions_with_fresh_var(
1231                 span,
1232                 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1233                 &poly_trait_ref);
1234
1235         self.normalize_associated_type(span, trait_ref, item_name)
1236     }
1237
1238     fn projected_ty(&self,
1239                     span: Span,
1240                     trait_ref: Rc<ty::TraitRef<'tcx>>,
1241                     item_name: ast::Name)
1242                     -> Ty<'tcx>
1243     {
1244         self.normalize_associated_type(span, trait_ref, item_name)
1245     }
1246 }
1247
1248 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1249     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1250
1251     pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1252         &self.inh.infcx
1253     }
1254
1255     pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1256         &self.inh.param_env
1257     }
1258
1259     pub fn sess(&self) -> &Session {
1260         &self.tcx().sess
1261     }
1262
1263     pub fn err_count_since_creation(&self) -> uint {
1264         self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1265     }
1266
1267     /// Resolves type variables in `ty` if possible. Unlike the infcx
1268     /// version, this version will also select obligations if it seems
1269     /// useful, in an effort to get more type information.
1270     fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1271         // No ty::infer()? Nothing needs doing.
1272         if !ty::type_has_ty_infer(ty) {
1273             return ty;
1274         }
1275
1276         // If `ty` is a type variable, see whether we already know what it is.
1277         ty = self.infcx().resolve_type_vars_if_possible(&ty);
1278         if !ty::type_has_ty_infer(ty) {
1279             return ty;
1280         }
1281
1282         // If not, try resolving any new fcx obligations that have cropped up.
1283         vtable::select_new_fcx_obligations(self);
1284         ty = self.infcx().resolve_type_vars_if_possible(&ty);
1285         if !ty::type_has_ty_infer(ty) {
1286             return ty;
1287         }
1288
1289         // If not, try resolving *all* pending obligations as much as
1290         // possible. This can help substantially when there are
1291         // indirect dependencies that don't seem worth tracking
1292         // precisely.
1293         vtable::select_fcx_obligations_where_possible(self);
1294         self.infcx().resolve_type_vars_if_possible(&ty)
1295     }
1296
1297     /// Resolves all type variables in `t` and then, if any were left
1298     /// unresolved, substitutes an error type. This is used after the
1299     /// main checking when doing a second pass before writeback. The
1300     /// justification is that writeback will produce an error for
1301     /// these unconstrained type variables.
1302     fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1303         let t = self.infcx().resolve_type_vars_if_possible(t);
1304         if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1305     }
1306
1307     fn record_deferred_call_resolution(&self,
1308                                        closure_def_id: ast::DefId,
1309                                        r: DeferredCallResolutionHandler<'tcx>) {
1310         let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1311         let mut vec = match deferred_call_resolutions.entry(closure_def_id) {
1312             Occupied(entry) => entry.into_mut(),
1313             Vacant(entry) => entry.insert(Vec::new()),
1314         };
1315         vec.push(r);
1316     }
1317
1318     fn remove_deferred_call_resolutions(&self,
1319                                         closure_def_id: ast::DefId)
1320                                         -> Vec<DeferredCallResolutionHandler<'tcx>>
1321     {
1322         let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1323         deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1324     }
1325
1326     pub fn tag(&self) -> String {
1327         format!("{:?}", self as *const FnCtxt)
1328     }
1329
1330     pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1331         match self.inh.locals.borrow().get(&nid) {
1332             Some(&t) => t,
1333             None => {
1334                 self.tcx().sess.span_bug(
1335                     span,
1336                     &format!("no type for local variable {}",
1337                             nid)[]);
1338             }
1339         }
1340     }
1341
1342     /// Apply "fallbacks" to some types
1343     /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1344     pub fn default_type_parameters(&self) {
1345         use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1346         for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1347             let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1348             if self.infcx().type_var_diverges(resolved) {
1349                 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1350             } else {
1351                 match self.infcx().type_is_unconstrained_numeric(resolved) {
1352                     UnconstrainedInt => {
1353                         demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1354                     },
1355                     UnconstrainedFloat => {
1356                         demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1357                     }
1358                     Neither => { }
1359                 }
1360             }
1361         }
1362     }
1363
1364     #[inline]
1365     pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1366         debug!("write_ty({}, {}) in fcx {}",
1367                node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1368         self.inh.node_types.borrow_mut().insert(node_id, ty);
1369     }
1370
1371     pub fn write_object_cast(&self,
1372                              key: ast::NodeId,
1373                              trait_ref: ty::PolyTraitRef<'tcx>) {
1374         debug!("write_object_cast key={} trait_ref={}",
1375                key, trait_ref.repr(self.tcx()));
1376         self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1377     }
1378
1379     pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1380         if !substs.substs.is_noop() {
1381             debug!("write_substs({}, {}) in fcx {}",
1382                    node_id,
1383                    substs.repr(self.tcx()),
1384                    self.tag());
1385
1386             self.inh.item_substs.borrow_mut().insert(node_id, substs);
1387         }
1388     }
1389
1390     pub fn write_autoderef_adjustment(&self,
1391                                       node_id: ast::NodeId,
1392                                       span: Span,
1393                                       derefs: uint) {
1394         if derefs == 0 { return; }
1395         self.write_adjustment(
1396             node_id,
1397             span,
1398             ty::AdjustDerefRef(ty::AutoDerefRef {
1399                 autoderefs: derefs,
1400                 autoref: None })
1401         );
1402     }
1403
1404     pub fn write_adjustment(&self,
1405                             node_id: ast::NodeId,
1406                             span: Span,
1407                             adj: ty::AutoAdjustment<'tcx>) {
1408         debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1409
1410         if adj.is_identity() {
1411             return;
1412         }
1413
1414         // Careful: adjustments can imply trait obligations if we are
1415         // casting from a concrete type to an object type. I think
1416         // it'd probably be nicer to move the logic that creates the
1417         // obligation into the code that creates the adjustment, but
1418         // that's a bit awkward, so instead we go digging and pull the
1419         // obligation out here.
1420         self.register_adjustment_obligations(span, &adj);
1421         self.inh.adjustments.borrow_mut().insert(node_id, adj);
1422     }
1423
1424     /// Basically whenever we are converting from a type scheme into
1425     /// the fn body space, we always want to normalize associated
1426     /// types as well. This function combines the two.
1427     fn instantiate_type_scheme<T>(&self,
1428                                   span: Span,
1429                                   substs: &Substs<'tcx>,
1430                                   value: &T)
1431                                   -> T
1432         where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1433     {
1434         let value = value.subst(self.tcx(), substs);
1435         let result = self.normalize_associated_types_in(span, &value);
1436         debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1437                value.repr(self.tcx()),
1438                substs.repr(self.tcx()),
1439                result.repr(self.tcx()));
1440         result
1441     }
1442
1443     /// As `instantiate_type_scheme`, but for the bounds found in a
1444     /// generic type scheme.
1445     fn instantiate_bounds(&self,
1446                           span: Span,
1447                           substs: &Substs<'tcx>,
1448                           bounds: &ty::GenericPredicates<'tcx>)
1449                           -> ty::InstantiatedPredicates<'tcx>
1450     {
1451         ty::InstantiatedPredicates {
1452             predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1453         }
1454     }
1455
1456
1457     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1458         where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1459     {
1460         self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1461     }
1462
1463     fn normalize_associated_type(&self,
1464                                  span: Span,
1465                                  trait_ref: Rc<ty::TraitRef<'tcx>>,
1466                                  item_name: ast::Name)
1467                                  -> Ty<'tcx>
1468     {
1469         let cause = traits::ObligationCause::new(span,
1470                                                  self.body_id,
1471                                                  traits::ObligationCauseCode::MiscObligation);
1472         self.inh.fulfillment_cx
1473             .borrow_mut()
1474             .normalize_projection_type(self.infcx(),
1475                                        self,
1476                                        ty::ProjectionTy {
1477                                            trait_ref: trait_ref,
1478                                            item_name: item_name,
1479                                        },
1480                                        cause)
1481     }
1482
1483     fn register_adjustment_obligations(&self,
1484                                        span: Span,
1485                                        adj: &ty::AutoAdjustment<'tcx>) {
1486         match *adj {
1487             ty::AdjustReifyFnPointer(..) => {
1488             }
1489             ty::AdjustDerefRef(ref d_r) => {
1490                 match d_r.autoref {
1491                     Some(ref a_r) => {
1492                         self.register_autoref_obligations(span, a_r);
1493                     }
1494                     None => {}
1495                 }
1496             }
1497         }
1498     }
1499
1500     fn register_autoref_obligations(&self,
1501                                     span: Span,
1502                                     autoref: &ty::AutoRef<'tcx>) {
1503         match *autoref {
1504             ty::AutoUnsize(ref unsize) => {
1505                 self.register_unsize_obligations(span, unsize);
1506             }
1507             ty::AutoPtr(_, _, None) |
1508             ty::AutoUnsafe(_, None) => {
1509             }
1510             ty::AutoPtr(_, _, Some(ref a_r)) |
1511             ty::AutoUnsafe(_, Some(ref a_r)) => {
1512                 self.register_autoref_obligations(span, &**a_r)
1513             }
1514             ty::AutoUnsizeUniq(ref unsize) => {
1515                 self.register_unsize_obligations(span, unsize);
1516             }
1517         }
1518     }
1519
1520     fn register_unsize_obligations(&self,
1521                                    span: Span,
1522                                    unsize: &ty::UnsizeKind<'tcx>) {
1523         debug!("register_unsize_obligations: unsize={:?}", unsize);
1524
1525         match *unsize {
1526             ty::UnsizeLength(..) => {}
1527             ty::UnsizeStruct(ref u, _) => {
1528                 self.register_unsize_obligations(span, &**u)
1529             }
1530             ty::UnsizeVtable(ref ty_trait, self_ty) => {
1531                 vtable::check_object_safety(self.tcx(), ty_trait, span);
1532
1533                 // If the type is `Foo+'a`, ensures that the type
1534                 // being cast to `Foo+'a` implements `Foo`:
1535                 vtable::register_object_cast_obligations(self,
1536                                                          span,
1537                                                          ty_trait,
1538                                                          self_ty);
1539
1540                 // If the type is `Foo+'a`, ensures that the type
1541                 // being cast to `Foo+'a` outlives `'a`:
1542                 let cause = traits::ObligationCause { span: span,
1543                                                       body_id: self.body_id,
1544                                                       code: traits::ObjectCastObligation(self_ty) };
1545                 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1546             }
1547         }
1548     }
1549
1550     /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1551     /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1552     /// Registers any trait obligations specified on `def_id` at the same time.
1553     ///
1554     /// Note that function is only intended to be used with types (notably, not fns). This is
1555     /// because it doesn't do any instantiation of late-bound regions.
1556     pub fn instantiate_type(&self,
1557                             span: Span,
1558                             def_id: ast::DefId)
1559                             -> TypeAndSubsts<'tcx>
1560     {
1561         let type_scheme =
1562             ty::lookup_item_type(self.tcx(), def_id);
1563         let type_predicates =
1564             ty::lookup_predicates(self.tcx(), def_id);
1565         let substs =
1566             self.infcx().fresh_substs_for_generics(
1567                 span,
1568                 &type_scheme.generics);
1569         let bounds =
1570             self.instantiate_bounds(span, &substs, &type_predicates);
1571         self.add_obligations_for_parameters(
1572             traits::ObligationCause::new(
1573                 span,
1574                 self.body_id,
1575                 traits::ItemObligation(def_id)),
1576             &bounds);
1577         let monotype =
1578             self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1579
1580         TypeAndSubsts {
1581             ty: monotype,
1582             substs: substs
1583         }
1584     }
1585
1586     /// Returns the type that this AST path refers to. If the path has no type
1587     /// parameters and the corresponding type has type parameters, fresh type
1588     /// and/or region variables are substituted.
1589     ///
1590     /// This is used when checking the constructor in struct literals.
1591     fn instantiate_struct_literal_ty(&self,
1592                                      did: ast::DefId,
1593                                      path: &ast::Path)
1594                                      -> TypeAndSubsts<'tcx>
1595     {
1596         let tcx = self.tcx();
1597
1598         let ty::TypeScheme { generics, ty: decl_ty } =
1599             ty::lookup_item_type(tcx, did);
1600
1601         let wants_params =
1602             generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1603
1604         let needs_defaults =
1605             wants_params &&
1606             path.segments.iter().all(|s| s.parameters.is_empty());
1607
1608         let substs = if needs_defaults {
1609             let tps =
1610                 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1611             let rps =
1612                 self.infcx().region_vars_for_defs(path.span,
1613                                                   generics.regions.get_slice(TypeSpace));
1614             Substs::new_type(tps, rps)
1615         } else {
1616             astconv::ast_path_substs_for_ty(self, self, &generics, path)
1617         };
1618
1619         let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1620
1621         TypeAndSubsts { substs: substs, ty: ty }
1622     }
1623
1624     pub fn write_nil(&self, node_id: ast::NodeId) {
1625         self.write_ty(node_id, ty::mk_nil(self.tcx()));
1626     }
1627     pub fn write_error(&self, node_id: ast::NodeId) {
1628         self.write_ty(node_id, self.tcx().types.err);
1629     }
1630
1631     pub fn require_type_meets(&self,
1632                               ty: Ty<'tcx>,
1633                               span: Span,
1634                               code: traits::ObligationCauseCode<'tcx>,
1635                               bound: ty::BuiltinBound)
1636     {
1637         self.register_builtin_bound(
1638             ty,
1639             bound,
1640             traits::ObligationCause::new(span, self.body_id, code));
1641     }
1642
1643     pub fn require_type_is_sized(&self,
1644                                  ty: Ty<'tcx>,
1645                                  span: Span,
1646                                  code: traits::ObligationCauseCode<'tcx>)
1647     {
1648         self.require_type_meets(ty, span, code, ty::BoundSized);
1649     }
1650
1651     pub fn require_expr_have_sized_type(&self,
1652                                         expr: &ast::Expr,
1653                                         code: traits::ObligationCauseCode<'tcx>)
1654     {
1655         self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1656     }
1657
1658     pub fn type_is_known_to_be_sized(&self,
1659                                      ty: Ty<'tcx>,
1660                                      span: Span)
1661                                      -> bool
1662     {
1663         traits::type_known_to_meet_builtin_bound(self.infcx(),
1664                                                  self.param_env(),
1665                                                  ty,
1666                                                  ty::BoundSized,
1667                                                  span)
1668     }
1669
1670     pub fn register_builtin_bound(&self,
1671                                   ty: Ty<'tcx>,
1672                                   builtin_bound: ty::BuiltinBound,
1673                                   cause: traits::ObligationCause<'tcx>)
1674     {
1675         self.inh.fulfillment_cx.borrow_mut()
1676             .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1677     }
1678
1679     pub fn register_predicate(&self,
1680                               obligation: traits::PredicateObligation<'tcx>)
1681     {
1682         debug!("register_predicate({})",
1683                obligation.repr(self.tcx()));
1684         self.inh.fulfillment_cx
1685             .borrow_mut()
1686             .register_predicate_obligation(self.infcx(), obligation);
1687     }
1688
1689     pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1690         let t = ast_ty_to_ty(self, self, ast_t);
1691
1692         let mut bounds_checker = wf::BoundsChecker::new(self,
1693                                                         ast_t.span,
1694                                                         self.body_id,
1695                                                         None);
1696         bounds_checker.check_ty(t);
1697
1698         t
1699     }
1700
1701     pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1702         pat.repr(self.tcx())
1703     }
1704
1705     pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1706         match self.inh.node_types.borrow().get(&ex.id) {
1707             Some(&t) => t,
1708             None => {
1709                 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1710                                             self.tag())[]);
1711             }
1712         }
1713     }
1714
1715     /// Apply `adjustment` to the type of `expr`
1716     pub fn adjust_expr_ty(&self,
1717                           expr: &ast::Expr,
1718                           adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1719                           -> Ty<'tcx>
1720     {
1721         let raw_ty = self.expr_ty(expr);
1722         let raw_ty = self.infcx().shallow_resolve(raw_ty);
1723         let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1724         ty::adjust_ty(self.tcx(),
1725                       expr.span,
1726                       expr.id,
1727                       raw_ty,
1728                       adjustment,
1729                       |method_call| self.inh.method_map.borrow()
1730                                                        .get(&method_call)
1731                                                        .map(|method| resolve_ty(method.ty)))
1732     }
1733
1734     pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1735         match self.inh.node_types.borrow().get(&id) {
1736             Some(&t) => t,
1737             None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1738             None => {
1739                 self.tcx().sess.bug(
1740                     &format!("no type for node {}: {} in fcx {}",
1741                             id, self.tcx().map.node_to_string(id),
1742                             self.tag())[]);
1743             }
1744         }
1745     }
1746
1747     pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1748         self.inh.item_substs.borrow()
1749     }
1750
1751     pub fn opt_node_ty_substs<F>(&self,
1752                                  id: ast::NodeId,
1753                                  f: F) where
1754         F: FnOnce(&ty::ItemSubsts<'tcx>),
1755     {
1756         match self.inh.item_substs.borrow().get(&id) {
1757             Some(s) => { f(s) }
1758             None => { }
1759         }
1760     }
1761
1762     pub fn mk_subty(&self,
1763                     a_is_expected: bool,
1764                     origin: infer::TypeOrigin,
1765                     sub: Ty<'tcx>,
1766                     sup: Ty<'tcx>)
1767                     -> Result<(), ty::type_err<'tcx>> {
1768         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1769     }
1770
1771     pub fn mk_eqty(&self,
1772                    a_is_expected: bool,
1773                    origin: infer::TypeOrigin,
1774                    sub: Ty<'tcx>,
1775                    sup: Ty<'tcx>)
1776                    -> Result<(), ty::type_err<'tcx>> {
1777         infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1778     }
1779
1780     pub fn mk_subr(&self,
1781                    origin: infer::SubregionOrigin<'tcx>,
1782                    sub: ty::Region,
1783                    sup: ty::Region) {
1784         infer::mk_subr(self.infcx(), origin, sub, sup)
1785     }
1786
1787     pub fn type_error_message<M>(&self,
1788                                  sp: Span,
1789                                  mk_msg: M,
1790                                  actual_ty: Ty<'tcx>,
1791                                  err: Option<&ty::type_err<'tcx>>) where
1792         M: FnOnce(String) -> String,
1793     {
1794         self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1795     }
1796
1797     pub fn report_mismatched_types(&self,
1798                                    sp: Span,
1799                                    e: Ty<'tcx>,
1800                                    a: Ty<'tcx>,
1801                                    err: &ty::type_err<'tcx>) {
1802         self.infcx().report_mismatched_types(sp, e, a, err)
1803     }
1804
1805     /// Registers an obligation for checking later, during regionck, that the type `ty` must
1806     /// outlive the region `r`.
1807     pub fn register_region_obligation(&self,
1808                                       ty: Ty<'tcx>,
1809                                       region: ty::Region,
1810                                       cause: traits::ObligationCause<'tcx>)
1811     {
1812         let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1813         fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1814     }
1815
1816     pub fn add_default_region_param_bounds(&self,
1817                                            substs: &Substs<'tcx>,
1818                                            expr: &ast::Expr)
1819     {
1820         for &ty in substs.types.iter() {
1821             let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1822             let cause = traits::ObligationCause::new(expr.span, self.body_id,
1823                                                      traits::MiscObligation);
1824             self.register_region_obligation(ty, default_bound, cause);
1825         }
1826     }
1827
1828     /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1829     /// type/region parameter was instantiated (`substs`), creates and registers suitable
1830     /// trait/region obligations.
1831     ///
1832     /// For example, if there is a function:
1833     ///
1834     /// ```
1835     /// fn foo<'a,T:'a>(...)
1836     /// ```
1837     ///
1838     /// and a reference:
1839     ///
1840     /// ```
1841     /// let f = foo;
1842     /// ```
1843     ///
1844     /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1845     /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1846     pub fn add_obligations_for_parameters(&self,
1847                                           cause: traits::ObligationCause<'tcx>,
1848                                           predicates: &ty::InstantiatedPredicates<'tcx>)
1849     {
1850         assert!(!predicates.has_escaping_regions());
1851
1852         debug!("add_obligations_for_parameters(predicates={})",
1853                predicates.repr(self.tcx()));
1854
1855         let obligations = traits::predicates_for_generics(self.tcx(),
1856                                                           cause,
1857                                                           predicates);
1858
1859         obligations.map_move(|o| self.register_predicate(o));
1860     }
1861
1862     // Only for fields! Returns <none> for methods>
1863     // Indifferent to privacy flags
1864     pub fn lookup_field_ty(&self,
1865                            span: Span,
1866                            class_id: ast::DefId,
1867                            items: &[ty::field_ty],
1868                            fieldname: ast::Name,
1869                            substs: &subst::Substs<'tcx>)
1870                            -> Option<Ty<'tcx>>
1871     {
1872         let o_field = items.iter().find(|f| f.name == fieldname);
1873         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1874                .map(|t| self.normalize_associated_types_in(span, &t))
1875     }
1876
1877     pub fn lookup_tup_field_ty(&self,
1878                                span: Span,
1879                                class_id: ast::DefId,
1880                                items: &[ty::field_ty],
1881                                idx: uint,
1882                                substs: &subst::Substs<'tcx>)
1883                                -> Option<Ty<'tcx>>
1884     {
1885         let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1886         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1887                .map(|t| self.normalize_associated_types_in(span, &t))
1888     }
1889 }
1890
1891 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1892     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1893         // RFC #599 specifies that object lifetime defaults take
1894         // precedence over other defaults. But within a fn body we
1895         // don't have a *default* region, rather we use inference to
1896         // find the *correct* region, which is strictly more general
1897         // (and anyway, within a fn body the right region may not even
1898         // be something the user can write explicitly, since it might
1899         // be some expression).
1900         Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1901     }
1902
1903     fn anon_regions(&self, span: Span, count: uint)
1904                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1905         Ok((0..count).map(|_| {
1906             self.infcx().next_region_var(infer::MiscVariable(span))
1907         }).collect())
1908     }
1909 }
1910
1911 #[derive(Copy, Debug, PartialEq, Eq)]
1912 pub enum LvaluePreference {
1913     PreferMutLvalue,
1914     NoPreference
1915 }
1916
1917 /// Whether `autoderef` requires types to resolve.
1918 #[derive(Copy, Debug, PartialEq, Eq)]
1919 pub enum UnresolvedTypeAction {
1920     /// Produce an error and return `ty_err` whenever a type cannot
1921     /// be resolved (i.e. it is `ty_infer`).
1922     Error,
1923     /// Go on without emitting any errors, and return the unresolved
1924     /// type. Useful for probing, e.g. in coercions.
1925     Ignore
1926 }
1927
1928 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1929 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1930 ///
1931 /// Note: this method does not modify the adjustments table. The caller is responsible for
1932 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1933 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1934                                  sp: Span,
1935                                  base_ty: Ty<'tcx>,
1936                                  opt_expr: Option<&ast::Expr>,
1937                                  unresolved_type_action: UnresolvedTypeAction,
1938                                  mut lvalue_pref: LvaluePreference,
1939                                  mut should_stop: F)
1940                                  -> (Ty<'tcx>, uint, Option<T>)
1941     where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1942 {
1943     debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1944            base_ty.repr(fcx.tcx()),
1945            opt_expr.repr(fcx.tcx()),
1946            lvalue_pref);
1947
1948     let mut t = base_ty;
1949     for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1950         let resolved_t = match unresolved_type_action {
1951             UnresolvedTypeAction::Error => {
1952                 let resolved_t = structurally_resolved_type(fcx, sp, t);
1953                 if ty::type_is_error(resolved_t) {
1954                     return (resolved_t, autoderefs, None);
1955                 }
1956                 resolved_t
1957             }
1958             UnresolvedTypeAction::Ignore => {
1959                 // We can continue even when the type cannot be resolved
1960                 // (i.e. it is an inference variable) because `ty::deref`
1961                 // and `try_overloaded_deref` both simply return `None`
1962                 // in such a case without producing spurious errors.
1963                 fcx.resolve_type_vars_if_possible(t)
1964             }
1965         };
1966
1967         match should_stop(resolved_t, autoderefs) {
1968             Some(x) => return (resolved_t, autoderefs, Some(x)),
1969             None => {}
1970         }
1971
1972         // Otherwise, deref if type is derefable:
1973         let mt = match ty::deref(resolved_t, false) {
1974             Some(mt) => Some(mt),
1975             None => {
1976                 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1977
1978                 // Super subtle: it might seem as though we should
1979                 // pass `opt_expr` to `try_overloaded_deref`, so that
1980                 // the (implicit) autoref of using an overloaded deref
1981                 // would get added to the adjustment table. However we
1982                 // do not do that, because it's kind of a
1983                 // "meta-adjustment" -- instead, we just leave it
1984                 // unrecorded and know that there "will be" an
1985                 // autoref. regionck and other bits of the code base,
1986                 // when they encounter an overloaded autoderef, have
1987                 // to do some reconstructive surgery. This is a pretty
1988                 // complex mess that is begging for a proper MIR.
1989                 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1990             }
1991         };
1992         match mt {
1993             Some(mt) => {
1994                 t = mt.ty;
1995                 if mt.mutbl == ast::MutImmutable {
1996                     lvalue_pref = NoPreference;
1997                 }
1998             }
1999             None => return (resolved_t, autoderefs, None)
2000         }
2001     }
2002
2003     // We've reached the recursion limit, error gracefully.
2004     span_err!(fcx.tcx().sess, sp, E0055,
2005         "reached the recursion limit while auto-dereferencing {}",
2006         base_ty.repr(fcx.tcx()));
2007     (fcx.tcx().types.err, 0, None)
2008 }
2009
2010 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2011                                   span: Span,
2012                                   method_call: Option<MethodCall>,
2013                                   base_expr: Option<&ast::Expr>,
2014                                   base_ty: Ty<'tcx>,
2015                                   lvalue_pref: LvaluePreference)
2016                                   -> Option<ty::mt<'tcx>>
2017 {
2018     // Try DerefMut first, if preferred.
2019     let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2020         (PreferMutLvalue, Some(trait_did)) => {
2021             method::lookup_in_trait(fcx, span, base_expr,
2022                                     token::intern("deref_mut"), trait_did,
2023                                     base_ty, None)
2024         }
2025         _ => None
2026     };
2027
2028     // Otherwise, fall back to Deref.
2029     let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2030         (None, Some(trait_did)) => {
2031             method::lookup_in_trait(fcx, span, base_expr,
2032                                     token::intern("deref"), trait_did,
2033                                     base_ty, None)
2034         }
2035         (method, _) => method
2036     };
2037
2038     make_overloaded_lvalue_return_type(fcx, method_call, method)
2039 }
2040
2041 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2042 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2043 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2044 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2045                                                 method_call: Option<MethodCall>,
2046                                                 method: Option<MethodCallee<'tcx>>)
2047                                                 -> Option<ty::mt<'tcx>>
2048 {
2049     match method {
2050         Some(method) => {
2051             let ref_ty = // invoked methods have all LB regions instantiated
2052                 ty::no_late_bound_regions(
2053                     fcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
2054             match method_call {
2055                 Some(method_call) => {
2056                     fcx.inh.method_map.borrow_mut().insert(method_call,
2057                                                            method);
2058                 }
2059                 None => {}
2060             }
2061             match ref_ty {
2062                 ty::FnConverging(ref_ty) => {
2063                     ty::deref(ref_ty, true)
2064                 }
2065                 ty::FnDiverging => {
2066                     fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2067                 }
2068             }
2069         }
2070         None => None,
2071     }
2072 }
2073
2074 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2075                                        base_expr: &ast::Expr,
2076                                        base_ty: Ty<'tcx>,
2077                                        lvalue_pref: LvaluePreference,
2078                                        mut step: F)
2079                                        -> Option<T> where
2080     F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2081 {
2082     // FIXME(#18741) -- this is almost but not quite the same as the
2083     // autoderef that normal method probing does. They could likely be
2084     // consolidated.
2085
2086     let (ty, autoderefs, final_mt) = autoderef(fcx,
2087                                                base_expr.span,
2088                                                base_ty,
2089                                                Some(base_expr),
2090                                                UnresolvedTypeAction::Error,
2091                                                lvalue_pref,
2092                                                |adj_ty, idx| {
2093             let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2094             step(adj_ty, autoderefref)
2095         });
2096
2097     if final_mt.is_some() {
2098         return final_mt;
2099     }
2100
2101     // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2102     // do a final unsized coercion to yield [T].
2103     match ty.sty {
2104         ty::ty_vec(element_ty, Some(n)) => {
2105             let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2106             let autoderefref = ty::AutoDerefRef {
2107                 autoderefs: autoderefs,
2108                 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2109             };
2110             step(adjusted_ty, autoderefref)
2111         }
2112         _ => {
2113             None
2114         }
2115     }
2116 }
2117
2118 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2119 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2120 /// This loop implements one step in that search; the autoderef loop is implemented by
2121 /// `autoderef_for_index`.
2122 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2123                             method_call: MethodCall,
2124                             expr: &ast::Expr,
2125                             base_expr: &'tcx ast::Expr,
2126                             adjusted_ty: Ty<'tcx>,
2127                             adjustment: ty::AutoDerefRef<'tcx>,
2128                             lvalue_pref: LvaluePreference,
2129                             index_ty: Ty<'tcx>)
2130                             -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2131 {
2132     let tcx = fcx.tcx();
2133     debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2134            expr.repr(tcx),
2135            base_expr.repr(tcx),
2136            adjusted_ty.repr(tcx),
2137            adjustment,
2138            index_ty.repr(tcx));
2139
2140     let input_ty = fcx.infcx().next_ty_var();
2141
2142     // First, try built-in indexing.
2143     match (ty::index(adjusted_ty), &index_ty.sty) {
2144         (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2145             debug!("try_index_step: success, using built-in indexing");
2146             fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2147             return Some((tcx.types.uint, ty));
2148         }
2149         _ => {}
2150     }
2151
2152     // Try `IndexMut` first, if preferred.
2153     let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2154         (PreferMutLvalue, Some(trait_did)) => {
2155             method::lookup_in_trait_adjusted(fcx,
2156                                              expr.span,
2157                                              Some(&*base_expr),
2158                                              token::intern("index_mut"),
2159                                              trait_did,
2160                                              adjustment.clone(),
2161                                              adjusted_ty,
2162                                              Some(vec![input_ty]))
2163         }
2164         _ => None,
2165     };
2166
2167     // Otherwise, fall back to `Index`.
2168     let method = match (method, tcx.lang_items.index_trait()) {
2169         (None, Some(trait_did)) => {
2170             method::lookup_in_trait_adjusted(fcx,
2171                                              expr.span,
2172                                              Some(&*base_expr),
2173                                              token::intern("index"),
2174                                              trait_did,
2175                                              adjustment.clone(),
2176                                              adjusted_ty,
2177                                              Some(vec![input_ty]))
2178         }
2179         (method, _) => method,
2180     };
2181
2182     // If some lookup succeeds, write callee into table and extract index/element
2183     // type from the method signature.
2184     // If some lookup succeeded, install method in table
2185     method.and_then(|method| {
2186         debug!("try_index_step: success, using overloaded indexing");
2187         make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2188             map(|ret| (input_ty, ret.ty))
2189     })
2190 }
2191
2192 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2193                                          sp: Span,
2194                                          method_fn_ty: Ty<'tcx>,
2195                                          callee_expr: &'tcx ast::Expr,
2196                                          args_no_rcvr: &'tcx [P<ast::Expr>],
2197                                          autoref_args: AutorefArgs,
2198                                          tuple_arguments: TupleArgumentsFlag,
2199                                          expected: Expectation<'tcx>)
2200                                          -> ty::FnOutput<'tcx> {
2201     if ty::type_is_error(method_fn_ty) {
2202         let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2203
2204         let err_inputs = match tuple_arguments {
2205             DontTupleArguments => err_inputs,
2206             TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2207         };
2208
2209         check_argument_types(fcx,
2210                              sp,
2211                              &err_inputs[..],
2212                              &[],
2213                              args_no_rcvr,
2214                              autoref_args,
2215                              false,
2216                              tuple_arguments);
2217         ty::FnConverging(fcx.tcx().types.err)
2218     } else {
2219         match method_fn_ty.sty {
2220             ty::ty_bare_fn(_, ref fty) => {
2221                 // HACK(eddyb) ignore self in the definition (see above).
2222                 let expected_arg_tys = expected_types_for_fn_args(fcx,
2223                                                                   sp,
2224                                                                   expected,
2225                                                                   fty.sig.0.output,
2226                                                                   &fty.sig.0.inputs[1..]);
2227                 check_argument_types(fcx,
2228                                      sp,
2229                                      &fty.sig.0.inputs[1..],
2230                                      &expected_arg_tys[..],
2231                                      args_no_rcvr,
2232                                      autoref_args,
2233                                      fty.sig.0.variadic,
2234                                      tuple_arguments);
2235                 fty.sig.0.output
2236             }
2237             _ => {
2238                 fcx.tcx().sess.span_bug(callee_expr.span,
2239                                         "method without bare fn type");
2240             }
2241         }
2242     }
2243 }
2244
2245 /// Generic function that factors out common logic from function calls, method calls and overloaded
2246 /// operators.
2247 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2248                                   sp: Span,
2249                                   fn_inputs: &[Ty<'tcx>],
2250                                   expected_arg_tys: &[Ty<'tcx>],
2251                                   args: &'tcx [P<ast::Expr>],
2252                                   autoref_args: AutorefArgs,
2253                                   variadic: bool,
2254                                   tuple_arguments: TupleArgumentsFlag) {
2255     let tcx = fcx.ccx.tcx;
2256
2257     // Grab the argument types, supplying fresh type variables
2258     // if the wrong number of arguments were supplied
2259     let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2260         args.len()
2261     } else {
2262         1
2263     };
2264
2265     let mut expected_arg_tys = expected_arg_tys;
2266     let expected_arg_count = fn_inputs.len();
2267     let formal_tys = if tuple_arguments == TupleArguments {
2268         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2269         match tuple_type.sty {
2270             ty::ty_tup(ref arg_types) => {
2271                 if arg_types.len() != args.len() {
2272                     span_err!(tcx.sess, sp, E0057,
2273                         "this function takes {} parameter{} but {} parameter{} supplied",
2274                         arg_types.len(),
2275                         if arg_types.len() == 1 {""} else {"s"},
2276                         args.len(),
2277                         if args.len() == 1 {" was"} else {"s were"});
2278                     expected_arg_tys = &[][];
2279                     err_args(fcx.tcx(), args.len())
2280                 } else {
2281                     expected_arg_tys = match expected_arg_tys.get(0) {
2282                         Some(&ty) => match ty.sty {
2283                             ty::ty_tup(ref tys) => &**tys,
2284                             _ => &[]
2285                         },
2286                         None => &[]
2287                     };
2288                     (*arg_types).clone()
2289                 }
2290             }
2291             _ => {
2292                 span_err!(tcx.sess, sp, E0059,
2293                     "cannot use call notation; the first type parameter \
2294                      for the function trait is neither a tuple nor unit");
2295                 expected_arg_tys = &[][];
2296                 err_args(fcx.tcx(), args.len())
2297             }
2298         }
2299     } else if expected_arg_count == supplied_arg_count {
2300         fn_inputs.to_vec()
2301     } else if variadic {
2302         if supplied_arg_count >= expected_arg_count {
2303             fn_inputs.to_vec()
2304         } else {
2305             span_err!(tcx.sess, sp, E0060,
2306                 "this function takes at least {} parameter{} \
2307                  but {} parameter{} supplied",
2308                 expected_arg_count,
2309                 if expected_arg_count == 1 {""} else {"s"},
2310                 supplied_arg_count,
2311                 if supplied_arg_count == 1 {" was"} else {"s were"});
2312             expected_arg_tys = &[][];
2313             err_args(fcx.tcx(), supplied_arg_count)
2314         }
2315     } else {
2316         span_err!(tcx.sess, sp, E0061,
2317             "this function takes {} parameter{} but {} parameter{} supplied",
2318             expected_arg_count,
2319             if expected_arg_count == 1 {""} else {"s"},
2320             supplied_arg_count,
2321             if supplied_arg_count == 1 {" was"} else {"s were"});
2322         expected_arg_tys = &[][];
2323         err_args(fcx.tcx(), supplied_arg_count)
2324     };
2325
2326     debug!("check_argument_types: formal_tys={:?}",
2327            formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2328
2329     // Check the arguments.
2330     // We do this in a pretty awful way: first we typecheck any arguments
2331     // that are not anonymous functions, then we typecheck the anonymous
2332     // functions. This is so that we have more information about the types
2333     // of arguments when we typecheck the functions. This isn't really the
2334     // right way to do this.
2335     let xs = [false, true];
2336     for check_blocks in &xs {
2337         let check_blocks = *check_blocks;
2338         debug!("check_blocks={}", check_blocks);
2339
2340         // More awful hacks: before we check argument types, try to do
2341         // an "opportunistic" vtable resolution of any trait bounds on
2342         // the call. This helps coercions.
2343         if check_blocks {
2344             vtable::select_new_fcx_obligations(fcx);
2345         }
2346
2347         // For variadic functions, we don't have a declared type for all of
2348         // the arguments hence we only do our usual type checking with
2349         // the arguments who's types we do know.
2350         let t = if variadic {
2351             expected_arg_count
2352         } else if tuple_arguments == TupleArguments {
2353             args.len()
2354         } else {
2355             supplied_arg_count
2356         };
2357         for (i, arg) in args.iter().take(t).enumerate() {
2358             let is_block = match arg.node {
2359                 ast::ExprClosure(..) => true,
2360                 _ => false
2361             };
2362
2363             if is_block == check_blocks {
2364                 debug!("checking the argument");
2365                 let mut formal_ty = formal_tys[i];
2366
2367                 match autoref_args {
2368                     AutorefArgs::Yes => {
2369                         match formal_ty.sty {
2370                             ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2371                             ty::ty_err => (),
2372                             _ => {
2373                                 // So we hit this case when one implements the
2374                                 // operator traits but leaves an argument as
2375                                 // just T instead of &T. We'll catch it in the
2376                                 // mismatch impl/trait method phase no need to
2377                                 // ICE here.
2378                                 // See: #11450
2379                                 formal_ty = tcx.types.err;
2380                             }
2381                         }
2382                     }
2383                     AutorefArgs::No => {}
2384                 }
2385
2386                 // The special-cased logic below has three functions:
2387                 // 1. Provide as good of an expected type as possible.
2388                 let expected = expected_arg_tys.get(i).map(|&ty| {
2389                     Expectation::rvalue_hint(ty)
2390                 });
2391
2392                 check_expr_with_unifier(fcx, &**arg,
2393                                         expected.unwrap_or(ExpectHasType(formal_ty)),
2394                                         NoPreference, || {
2395                     // 2. Coerce to the most detailed type that could be coerced
2396                     //    to, which is `expected_ty` if `rvalue_hint` returns an
2397                     //    `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2398                     let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2399                     demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2400
2401                     // 3. Relate the expected type and the formal one,
2402                     //    if the expected type was used for the coercion.
2403                     coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2404                 });
2405             }
2406         }
2407     }
2408
2409     // We also need to make sure we at least write the ty of the other
2410     // arguments which we skipped above.
2411     if variadic {
2412         for arg in args.iter().skip(expected_arg_count) {
2413             check_expr(fcx, &**arg);
2414
2415             // There are a few types which get autopromoted when passed via varargs
2416             // in C but we just error out instead and require explicit casts.
2417             let arg_ty = structurally_resolved_type(fcx, arg.span,
2418                                                     fcx.expr_ty(&**arg));
2419             match arg_ty.sty {
2420                 ty::ty_float(ast::TyF32) => {
2421                     fcx.type_error_message(arg.span,
2422                                            |t| {
2423                         format!("can't pass an {} to variadic \
2424                                  function, cast to c_double", t)
2425                     }, arg_ty, None);
2426                 }
2427                 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2428                     fcx.type_error_message(arg.span, |t| {
2429                         format!("can't pass {} to variadic \
2430                                  function, cast to c_int",
2431                                        t)
2432                     }, arg_ty, None);
2433                 }
2434                 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2435                     fcx.type_error_message(arg.span, |t| {
2436                         format!("can't pass {} to variadic \
2437                                  function, cast to c_uint",
2438                                        t)
2439                     }, arg_ty, None);
2440                 }
2441                 _ => {}
2442             }
2443         }
2444     }
2445 }
2446
2447 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2448 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2449     (0..len).map(|_| tcx.types.err).collect()
2450 }
2451
2452 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2453                         call_expr: &ast::Expr,
2454                         output: ty::FnOutput<'tcx>) {
2455     fcx.write_ty(call_expr.id, match output {
2456         ty::FnConverging(output_ty) => output_ty,
2457         ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2458     });
2459 }
2460
2461 // AST fragment checking
2462 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2463                        lit: &ast::Lit,
2464                        expected: Expectation<'tcx>)
2465                        -> Ty<'tcx>
2466 {
2467     let tcx = fcx.ccx.tcx;
2468
2469     match lit.node {
2470         ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2471         ast::LitBinary(..) => {
2472             ty::mk_slice(tcx,
2473                          tcx.mk_region(ty::ReStatic),
2474                          ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2475         }
2476         ast::LitByte(_) => tcx.types.u8,
2477         ast::LitChar(_) => tcx.types.char,
2478         ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2479         ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2480         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2481             let opt_ty = expected.to_option(fcx).and_then(|ty| {
2482                 match ty.sty {
2483                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2484                     ty::ty_char => Some(tcx.types.u8),
2485                     ty::ty_ptr(..) => Some(tcx.types.uint),
2486                     ty::ty_bare_fn(..) => Some(tcx.types.uint),
2487                     _ => None
2488                 }
2489             });
2490             opt_ty.unwrap_or_else(
2491                 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2492         }
2493         ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2494         ast::LitFloatUnsuffixed(_) => {
2495             let opt_ty = expected.to_option(fcx).and_then(|ty| {
2496                 match ty.sty {
2497                     ty::ty_float(_) => Some(ty),
2498                     _ => None
2499                 }
2500             });
2501             opt_ty.unwrap_or_else(
2502                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2503         }
2504         ast::LitBool(_) => tcx.types.bool
2505     }
2506 }
2507
2508 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2509                                      expr: &'tcx ast::Expr,
2510                                      expected: Ty<'tcx>) {
2511     check_expr_with_unifier(
2512         fcx, expr, ExpectHasType(expected), NoPreference,
2513         || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2514 }
2515
2516 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2517                                           expr: &'tcx ast::Expr,
2518                                           expected: Ty<'tcx>) {
2519     check_expr_with_unifier(
2520         fcx, expr, ExpectHasType(expected), NoPreference,
2521         || demand::coerce(fcx, expr.span, expected, expr));
2522 }
2523
2524 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2525                                   expected: Ty<'tcx>) {
2526     check_expr_with_unifier(
2527         fcx, expr, ExpectHasType(expected), NoPreference,
2528         || ())
2529 }
2530
2531 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2532                                          expr: &'tcx ast::Expr,
2533                                          expected: Expectation<'tcx>) {
2534     check_expr_with_unifier(
2535         fcx, expr, expected, NoPreference,
2536         || ())
2537 }
2538
2539 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2540                                                          expr: &'tcx ast::Expr,
2541                                                          expected: Expectation<'tcx>,
2542                                                          lvalue_pref: LvaluePreference)
2543 {
2544     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2545 }
2546
2547 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr)  {
2548     check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2549 }
2550
2551 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2552                                         lvalue_pref: LvaluePreference)  {
2553     check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2554 }
2555
2556 // determine the `self` type, using fresh variables for all variables
2557 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2558 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2559 // variables.
2560 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2561                               span: Span, // (potential) receiver for this impl
2562                               did: ast::DefId)
2563                               -> TypeAndSubsts<'tcx> {
2564     let tcx = fcx.tcx();
2565
2566     let ity = ty::lookup_item_type(tcx, did);
2567     let (n_tps, rps, raw_ty) =
2568         (ity.generics.types.len(subst::TypeSpace),
2569          ity.generics.regions.get_slice(subst::TypeSpace),
2570          ity.ty);
2571
2572     let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2573     let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2574     let substs = subst::Substs::new_type(tps, rps);
2575     let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2576
2577     TypeAndSubsts { substs: substs, ty: substd_ty }
2578 }
2579
2580 // Controls whether the arguments are automatically referenced. This is useful
2581 // for overloaded binary and unary operators.
2582 #[derive(Copy, PartialEq)]
2583 pub enum AutorefArgs {
2584     Yes,
2585     No,
2586 }
2587
2588 /// Controls whether the arguments are tupled. This is used for the call
2589 /// operator.
2590 ///
2591 /// Tupling means that all call-side arguments are packed into a tuple and
2592 /// passed as a single parameter. For example, if tupling is enabled, this
2593 /// function:
2594 ///
2595 ///     fn f(x: (int, int))
2596 ///
2597 /// Can be called as:
2598 ///
2599 ///     f(1, 2);
2600 ///
2601 /// Instead of:
2602 ///
2603 ///     f((1, 2));
2604 #[derive(Clone, Eq, PartialEq)]
2605 enum TupleArgumentsFlag {
2606     DontTupleArguments,
2607     TupleArguments,
2608 }
2609
2610 /// Unifies the return type with the expected type early, for more coercions
2611 /// and forward type information on the argument expressions.
2612 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2613                                         call_span: Span,
2614                                         expected_ret: Expectation<'tcx>,
2615                                         formal_ret: ty::FnOutput<'tcx>,
2616                                         formal_args: &[Ty<'tcx>])
2617                                         -> Vec<Ty<'tcx>> {
2618     let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2619         if let ty::FnConverging(formal_ret_ty) = formal_ret {
2620             fcx.infcx().commit_regions_if_ok(|| {
2621                 // Attempt to apply a subtyping relationship between the formal
2622                 // return type (likely containing type variables if the function
2623                 // is polymorphic) and the expected return type.
2624                 // No argument expectations are produced if unification fails.
2625                 let origin = infer::Misc(call_span);
2626                 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2627                 // FIXME(#15760) can't use try! here, FromError doesn't default
2628                 // to identity so the resulting type is not constrained.
2629                 if let Err(e) = ures {
2630                     return Err(e);
2631                 }
2632
2633                 // Record all the argument types, with the substitutions
2634                 // produced from the above subtyping unification.
2635                 Ok(formal_args.iter().map(|ty| {
2636                     fcx.infcx().resolve_type_vars_if_possible(ty)
2637                 }).collect())
2638             }).ok()
2639         } else {
2640             None
2641         }
2642     }).unwrap_or(vec![]);
2643     debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2644            formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2645            expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2646     expected_args
2647 }
2648
2649 /// Invariant:
2650 /// If an expression has any sub-expressions that result in a type error,
2651 /// inspecting that expression's type with `ty::type_is_error` will return
2652 /// true. Likewise, if an expression is known to diverge, inspecting its
2653 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2654 /// strict, _|_ can appear in the type of an expression that does not,
2655 /// itself, diverge: for example, fn() -> _|_.)
2656 /// Note that inspecting a type's structure *directly* may expose the fact
2657 /// that there are actually multiple representations for `ty_err`, so avoid
2658 /// that when err needs to be handled differently.
2659 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2660                                         expr: &'tcx ast::Expr,
2661                                         expected: Expectation<'tcx>,
2662                                         lvalue_pref: LvaluePreference,
2663                                         unifier: F) where
2664     F: FnOnce(),
2665 {
2666     debug!(">> typechecking: expr={} expected={}",
2667            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2668
2669     // Checks a method call.
2670     fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2671                                    expr: &'tcx ast::Expr,
2672                                    method_name: ast::SpannedIdent,
2673                                    args: &'tcx [P<ast::Expr>],
2674                                    tps: &[P<ast::Ty>],
2675                                    expected: Expectation<'tcx>,
2676                                    lvalue_pref: LvaluePreference) {
2677         let rcvr = &*args[0];
2678         check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2679
2680         // no need to check for bot/err -- callee does that
2681         let expr_t = structurally_resolved_type(fcx,
2682                                                 expr.span,
2683                                                 fcx.expr_ty(&*rcvr));
2684
2685         let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2686         let fn_ty = match method::lookup(fcx,
2687                                          method_name.span,
2688                                          method_name.node.name,
2689                                          expr_t,
2690                                          tps,
2691                                          expr,
2692                                          rcvr) {
2693             Ok(method) => {
2694                 let method_ty = method.ty;
2695                 let method_call = MethodCall::expr(expr.id);
2696                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2697                 method_ty
2698             }
2699             Err(error) => {
2700                 method::report_error(fcx, method_name.span, expr_t,
2701                                      method_name.node.name, rcvr, error);
2702                 fcx.write_error(expr.id);
2703                 fcx.tcx().types.err
2704             }
2705         };
2706
2707         // Call the generic checker.
2708         let ret_ty = check_method_argument_types(fcx,
2709                                                  method_name.span,
2710                                                  fn_ty,
2711                                                  expr,
2712                                                  &args[1..],
2713                                                  AutorefArgs::No,
2714                                                  DontTupleArguments,
2715                                                  expected);
2716
2717         write_call(fcx, expr, ret_ty);
2718     }
2719
2720     // A generic function for checking the then and else in an if
2721     // or if-else.
2722     fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2723                                  cond_expr: &'tcx ast::Expr,
2724                                  then_blk: &'tcx ast::Block,
2725                                  opt_else_expr: Option<&'tcx ast::Expr>,
2726                                  id: ast::NodeId,
2727                                  sp: Span,
2728                                  expected: Expectation<'tcx>) {
2729         check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2730
2731         let expected = expected.adjust_for_branches(fcx);
2732         check_block_with_expected(fcx, then_blk, expected);
2733         let then_ty = fcx.node_ty(then_blk.id);
2734
2735         let branches_ty = match opt_else_expr {
2736             Some(ref else_expr) => {
2737                 check_expr_with_expectation(fcx, &**else_expr, expected);
2738                 let else_ty = fcx.expr_ty(&**else_expr);
2739                 infer::common_supertype(fcx.infcx(),
2740                                         infer::IfExpression(sp),
2741                                         true,
2742                                         then_ty,
2743                                         else_ty)
2744             }
2745             None => {
2746                 infer::common_supertype(fcx.infcx(),
2747                                         infer::IfExpressionWithNoElse(sp),
2748                                         false,
2749                                         then_ty,
2750                                         ty::mk_nil(fcx.tcx()))
2751             }
2752         };
2753
2754         let cond_ty = fcx.expr_ty(cond_expr);
2755         let if_ty = if ty::type_is_error(cond_ty) {
2756             fcx.tcx().types.err
2757         } else {
2758             branches_ty
2759         };
2760
2761         fcx.write_ty(id, if_ty);
2762     }
2763
2764     fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2765                                      op_ex: &'tcx ast::Expr,
2766                                      lhs_ty: Ty<'tcx>,
2767                                      opname: ast::Name,
2768                                      trait_did: Option<ast::DefId>,
2769                                      lhs: &'a ast::Expr,
2770                                      rhs: Option<&'tcx P<ast::Expr>>,
2771                                      unbound_method: F,
2772                                      autoref_args: AutorefArgs) -> Ty<'tcx> where
2773         F: FnOnce(),
2774     {
2775         let method = match trait_did {
2776             Some(trait_did) => {
2777                 // We do eager coercions to make using operators
2778                 // more ergonomic:
2779                 //
2780                 // - If the input is of type &'a T (resp. &'a mut T),
2781                 //   then reborrow it to &'b T (resp. &'b mut T) where
2782                 //   'b <= 'a.  This makes things like `x == y`, where
2783                 //   `x` and `y` are both region pointers, work.  We
2784                 //   could also solve this with variance or different
2785                 //   traits that don't force left and right to have same
2786                 //   type.
2787                 let (adj_ty, adjustment) = match lhs_ty.sty {
2788                     ty::ty_rptr(r_in, mt) => {
2789                         let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2790                         fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2791                         let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2792                         let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2793                         let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2794                         (adjusted_ty, adjustment)
2795                     }
2796                     _ => {
2797                         (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2798                     }
2799                 };
2800
2801                 debug!("adjusted_ty={} adjustment={:?}",
2802                        adj_ty.repr(fcx.tcx()),
2803                        adjustment);
2804
2805                 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2806                                                  trait_did, adjustment, adj_ty, None)
2807             }
2808             None => None
2809         };
2810         let args = match rhs {
2811             Some(rhs) => slice::ref_slice(rhs),
2812             None => &[][]
2813         };
2814         match method {
2815             Some(method) => {
2816                 let method_ty = method.ty;
2817                 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2818                 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2819                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2820                 match check_method_argument_types(fcx,
2821                                                   op_ex.span,
2822                                                   method_ty,
2823                                                   op_ex,
2824                                                   args,
2825                                                   autoref_args,
2826                                                   DontTupleArguments,
2827                                                   NoExpectation) {
2828                     ty::FnConverging(result_type) => result_type,
2829                     ty::FnDiverging => fcx.tcx().types.err
2830                 }
2831             }
2832             None => {
2833                 unbound_method();
2834                 // Check the args anyway
2835                 // so we get all the error messages
2836                 let expected_ty = fcx.tcx().types.err;
2837                 check_method_argument_types(fcx,
2838                                             op_ex.span,
2839                                             expected_ty,
2840                                             op_ex,
2841                                             args,
2842                                             autoref_args,
2843                                             DontTupleArguments,
2844                                             NoExpectation);
2845                 fcx.tcx().types.err
2846             }
2847         }
2848     }
2849
2850     // could be either an expr_binop or an expr_assign_binop
2851     fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2852                             expr: &'tcx ast::Expr,
2853                             op: ast::BinOp,
2854                             lhs: &'tcx ast::Expr,
2855                             rhs: &'tcx P<ast::Expr>,
2856                             is_binop_assignment: IsBinopAssignment) {
2857         let tcx = fcx.ccx.tcx;
2858
2859         let lvalue_pref = match is_binop_assignment {
2860             BinopAssignment => PreferMutLvalue,
2861             SimpleBinop => NoPreference
2862         };
2863         check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
2864
2865         // Callee does bot / err checking
2866         let lhs_t =
2867             structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || {
2868                 if ast_util::is_symmetric_binop(op.node) {
2869                     // Try RHS first
2870                     check_expr(fcx, &**rhs);
2871                     fcx.expr_ty(&**rhs)
2872                 } else {
2873                     fcx.tcx().types.err
2874                 }
2875             });
2876
2877         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
2878             // Shift is a special case: rhs must be uint, no matter what lhs is
2879             check_expr(fcx, &**rhs);
2880             let rhs_ty = fcx.expr_ty(&**rhs);
2881             let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty);
2882             if ty::type_is_integral(rhs_ty) {
2883                 fcx.write_ty(expr.id, lhs_t);
2884             } else {
2885                 fcx.type_error_message(
2886                     expr.span,
2887                     |actual| {
2888                         format!(
2889                             "right-hand-side of a shift operation must have integral type, \
2890                              not `{}`",
2891                             actual)
2892                     },
2893                     rhs_ty,
2894                     None);
2895                 fcx.write_ty(expr.id, fcx.tcx().types.err);
2896             }
2897             return;
2898         }
2899
2900         if ty::is_binopable(tcx, lhs_t, op) {
2901             let tvar = fcx.infcx().next_ty_var();
2902             demand::suptype(fcx, expr.span, tvar, lhs_t);
2903             check_expr_has_type(fcx, &**rhs, tvar);
2904
2905             let result_t = match op.node {
2906                 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2907                 ast::BiGt => {
2908                     if ty::type_is_simd(tcx, lhs_t) {
2909                         if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2910                             fcx.type_error_message(expr.span,
2911                                 |actual| {
2912                                     format!("binary comparison \
2913                                              operation `{}` not \
2914                                              supported for floating \
2915                                              point SIMD vector `{}`",
2916                                             ast_util::binop_to_string(op.node),
2917                                             actual)
2918                                 },
2919                                 lhs_t,
2920                                 None
2921                             );
2922                             fcx.tcx().types.err
2923                         } else {
2924                             lhs_t
2925                         }
2926                     } else {
2927                         fcx.tcx().types.bool
2928                     }
2929                 },
2930                 _ => lhs_t,
2931             };
2932
2933             fcx.write_ty(expr.id, result_t);
2934             return;
2935         }
2936
2937         if op.node == ast::BiOr || op.node == ast::BiAnd {
2938             // This is an error; one of the operands must have the wrong
2939             // type
2940             fcx.write_error(expr.id);
2941             fcx.write_error(rhs.id);
2942             fcx.type_error_message(expr.span,
2943                                    |actual| {
2944                     format!("binary operation `{}` cannot be applied \
2945                              to type `{}`",
2946                             ast_util::binop_to_string(op.node),
2947                             actual)
2948                 },
2949                 lhs_t,
2950                 None)
2951         }
2952
2953         // Check for overloaded operators if not an assignment.
2954         let result_t = if is_binop_assignment == SimpleBinop {
2955             check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2956         } else {
2957             fcx.type_error_message(expr.span,
2958                                    |actual| {
2959                                         format!("binary assignment \
2960                                                  operation `{}=` \
2961                                                  cannot be applied to \
2962                                                  type `{}`",
2963                                                 ast_util::binop_to_string(op.node),
2964                                                 actual)
2965                                    },
2966                                    lhs_t,
2967                                    None);
2968             check_expr(fcx, &**rhs);
2969             fcx.tcx().types.err
2970         };
2971
2972         fcx.write_ty(expr.id, result_t);
2973         if ty::type_is_error(result_t) {
2974             fcx.write_ty(rhs.id, result_t);
2975         }
2976     }
2977
2978     fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2979                                   ex: &'tcx ast::Expr,
2980                                   lhs_expr: &'tcx ast::Expr,
2981                                   lhs_resolved_t: Ty<'tcx>,
2982                                   op: ast::BinOp,
2983                                   rhs: &'tcx P<ast::Expr>) -> Ty<'tcx> {
2984         let tcx = fcx.ccx.tcx;
2985         let lang = &tcx.lang_items;
2986         let (name, trait_did) = match op.node {
2987             ast::BiAdd => ("add", lang.add_trait()),
2988             ast::BiSub => ("sub", lang.sub_trait()),
2989             ast::BiMul => ("mul", lang.mul_trait()),
2990             ast::BiDiv => ("div", lang.div_trait()),
2991             ast::BiRem => ("rem", lang.rem_trait()),
2992             ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2993             ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2994             ast::BiBitOr => ("bitor", lang.bitor_trait()),
2995             ast::BiShl => ("shl", lang.shl_trait()),
2996             ast::BiShr => ("shr", lang.shr_trait()),
2997             ast::BiLt => ("lt", lang.ord_trait()),
2998             ast::BiLe => ("le", lang.ord_trait()),
2999             ast::BiGe => ("ge", lang.ord_trait()),
3000             ast::BiGt => ("gt", lang.ord_trait()),
3001             ast::BiEq => ("eq", lang.eq_trait()),
3002             ast::BiNe => ("ne", lang.eq_trait()),
3003             ast::BiAnd | ast::BiOr => {
3004                 check_expr(fcx, &**rhs);
3005                 return tcx.types.err;
3006             }
3007         };
3008         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3009                          trait_did, lhs_expr, Some(rhs), || {
3010             fcx.type_error_message(ex.span, |actual| {
3011                 format!("binary operation `{}` cannot be applied to type `{}`",
3012                         ast_util::binop_to_string(op.node),
3013                         actual)
3014             }, lhs_resolved_t, None)
3015         }, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes })
3016     }
3017
3018     fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3019                                  op_str: &str,
3020                                  mname: &str,
3021                                  trait_did: Option<ast::DefId>,
3022                                  ex: &'tcx ast::Expr,
3023                                  rhs_expr: &'tcx ast::Expr,
3024                                  rhs_t: Ty<'tcx>,
3025                                  op: ast::UnOp) -> Ty<'tcx> {
3026        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3027                         trait_did, rhs_expr, None, || {
3028             fcx.type_error_message(ex.span, |actual| {
3029                 format!("cannot apply unary operator `{}` to type `{}`",
3030                         op_str, actual)
3031             }, rhs_t, None);
3032         }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3033     }
3034
3035     // Check field access expressions
3036     fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3037                             expr: &'tcx ast::Expr,
3038                             lvalue_pref: LvaluePreference,
3039                             base: &'tcx ast::Expr,
3040                             field: &ast::SpannedIdent) {
3041         let tcx = fcx.ccx.tcx;
3042         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3043         let expr_t = structurally_resolved_type(fcx, expr.span,
3044                                                 fcx.expr_ty(base));
3045         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3046         let (_, autoderefs, field_ty) = autoderef(fcx,
3047                                                   expr.span,
3048                                                   expr_t,
3049                                                   Some(base),
3050                                                   UnresolvedTypeAction::Error,
3051                                                   lvalue_pref,
3052                                                   |base_t, _| {
3053                 match base_t.sty {
3054                     ty::ty_struct(base_id, substs) => {
3055                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3056                         let fields = ty::lookup_struct_fields(tcx, base_id);
3057                         fcx.lookup_field_ty(expr.span, base_id, &fields[..],
3058                                             field.node.name, &(*substs))
3059                     }
3060                     _ => None
3061                 }
3062             });
3063         match field_ty {
3064             Some(field_ty) => {
3065                 fcx.write_ty(expr.id, field_ty);
3066                 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3067                 return;
3068             }
3069             None => {}
3070         }
3071
3072         if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3073             fcx.type_error_message(
3074                 field.span,
3075                 |actual| {
3076                     format!("attempted to take value of method `{}` on type \
3077                             `{}`", token::get_ident(field.node), actual)
3078                 },
3079                 expr_t, None);
3080
3081             tcx.sess.span_help(field.span,
3082                                "maybe a `()` to call it is missing? \
3083                                If not, try an anonymous function");
3084         } else {
3085             fcx.type_error_message(
3086                 expr.span,
3087                 |actual| {
3088                     format!("attempted access of field `{}` on \
3089                             type `{}`, but no field with that \
3090                             name was found",
3091                             token::get_ident(field.node),
3092                             actual)
3093                 },
3094                 expr_t, None);
3095             if let Some(t) = ty::ty_to_def_id(expr_t) {
3096                 suggest_field_names(t, field, tcx, vec![]);
3097             }
3098         }
3099
3100         fcx.write_error(expr.id);
3101     }
3102
3103     // displays hints about the closest matches in field names
3104     fn suggest_field_names<'tcx>(id : DefId,
3105                                  field : &ast::SpannedIdent,
3106                                  tcx : &ty::ctxt<'tcx>,
3107                                  skip : Vec<&str>) {
3108         let ident = token::get_ident(field.node);
3109         let name = &ident;
3110         // only find fits with at least one matching letter
3111         let mut best_dist = name.len();
3112         let fields = ty::lookup_struct_fields(tcx, id);
3113         let mut best = None;
3114         for elem in &fields {
3115             let n = elem.name.as_str();
3116             // ignore already set fields
3117             if skip.iter().any(|&x| x == n) {
3118                 continue;
3119             }
3120             let dist = lev_distance(n, name);
3121             if dist < best_dist {
3122                 best = Some(n);
3123                 best_dist = dist;
3124             }
3125         }
3126         if let Some(n) = best {
3127             tcx.sess.span_help(field.span,
3128                 &format!("did you mean `{}`?", n));
3129         }
3130     }
3131
3132     // Check tuple index expressions
3133     fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3134                                 expr: &'tcx ast::Expr,
3135                                 lvalue_pref: LvaluePreference,
3136                                 base: &'tcx ast::Expr,
3137                                 idx: codemap::Spanned<uint>) {
3138         let tcx = fcx.ccx.tcx;
3139         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3140         let expr_t = structurally_resolved_type(fcx, expr.span,
3141                                                 fcx.expr_ty(base));
3142         let mut tuple_like = false;
3143         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3144         let (_, autoderefs, field_ty) = autoderef(fcx,
3145                                                   expr.span,
3146                                                   expr_t,
3147                                                   Some(base),
3148                                                   UnresolvedTypeAction::Error,
3149                                                   lvalue_pref,
3150                                                   |base_t, _| {
3151                 match base_t.sty {
3152                     ty::ty_struct(base_id, substs) => {
3153                         tuple_like = ty::is_tuple_struct(tcx, base_id);
3154                         if tuple_like {
3155                             debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3156                             let fields = ty::lookup_struct_fields(tcx, base_id);
3157                             fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
3158                                                     idx.node, &(*substs))
3159                         } else {
3160                             None
3161                         }
3162                     }
3163                     ty::ty_tup(ref v) => {
3164                         tuple_like = true;
3165                         if idx.node < v.len() { Some(v[idx.node]) } else { None }
3166                     }
3167                     _ => None
3168                 }
3169             });
3170         match field_ty {
3171             Some(field_ty) => {
3172                 fcx.write_ty(expr.id, field_ty);
3173                 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3174                 return;
3175             }
3176             None => {}
3177         }
3178         fcx.type_error_message(
3179             expr.span,
3180             |actual| {
3181                 if tuple_like {
3182                     format!("attempted out-of-bounds tuple index `{}` on \
3183                                     type `{}`",
3184                                    idx.node,
3185                                    actual)
3186                 } else {
3187                     format!("attempted tuple index `{}` on type `{}`, but the \
3188                                      type was not a tuple or tuple struct",
3189                                     idx.node,
3190                                     actual)
3191                 }
3192             },
3193             expr_t, None);
3194
3195         fcx.write_error(expr.id);
3196     }
3197
3198     fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3199                                                 struct_ty: Ty<'tcx>,
3200                                                 span: Span,
3201                                                 class_id: ast::DefId,
3202                                                 node_id: ast::NodeId,
3203                                                 substitutions: &'tcx subst::Substs<'tcx>,
3204                                                 field_types: &[ty::field_ty],
3205                                                 ast_fields: &'tcx [ast::Field],
3206                                                 check_completeness: bool,
3207                                                 enum_id_opt: Option<ast::DefId>)  {
3208         let tcx = fcx.ccx.tcx;
3209
3210         let mut class_field_map = FnvHashMap();
3211         let mut fields_found = 0;
3212         for field in field_types {
3213             class_field_map.insert(field.name, (field.id, false));
3214         }
3215
3216         let mut error_happened = false;
3217
3218         // Typecheck each field.
3219         for field in ast_fields {
3220             let mut expected_field_type = tcx.types.err;
3221
3222             let pair = class_field_map.get(&field.ident.node.name).cloned();
3223             match pair {
3224                 None => {
3225                     fcx.type_error_message(
3226                         field.ident.span,
3227                         |actual| match enum_id_opt {
3228                             Some(enum_id) => {
3229                                 let variant_type = ty::enum_variant_with_id(tcx,
3230                                                                             enum_id,
3231                                                                             class_id);
3232                                 format!("struct variant `{}::{}` has no field named `{}`",
3233                                         actual, variant_type.name.as_str(),
3234                                         token::get_ident(field.ident.node))
3235                             }
3236                             None => {
3237                                 format!("structure `{}` has no field named `{}`",
3238                                         actual,
3239                                         token::get_ident(field.ident.node))
3240                             }
3241                         },
3242                         struct_ty,
3243                         None);
3244                     // prevent all specified fields from being suggested
3245                     let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
3246                     let actual_id = match enum_id_opt {
3247                         Some(_) => class_id,
3248                         None => ty::ty_to_def_id(struct_ty).unwrap()
3249                     };
3250                     suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3251                     error_happened = true;
3252                 }
3253                 Some((_, true)) => {
3254                     span_err!(fcx.tcx().sess, field.ident.span, E0062,
3255                         "field `{}` specified more than once",
3256                         token::get_ident(field.ident.node));
3257                     error_happened = true;
3258                 }
3259                 Some((field_id, false)) => {
3260                     expected_field_type =
3261                         ty::lookup_field_type(
3262                             tcx, class_id, field_id, substitutions);
3263                     expected_field_type =
3264                         fcx.normalize_associated_types_in(
3265                             field.span, &expected_field_type);
3266                     class_field_map.insert(
3267                         field.ident.node.name, (field_id, true));
3268                     fields_found += 1;
3269                 }
3270             }
3271
3272             // Make sure to give a type to the field even if there's
3273             // an error, so we can continue typechecking
3274             check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3275         }
3276
3277         if error_happened {
3278             fcx.write_error(node_id);
3279         }
3280
3281         if check_completeness && !error_happened {
3282             // Make sure the programmer specified all the fields.
3283             assert!(fields_found <= field_types.len());
3284             if fields_found < field_types.len() {
3285                 let mut missing_fields = Vec::new();
3286                 for class_field in field_types {
3287                     let name = class_field.name;
3288                     let (_, seen) = class_field_map[name];
3289                     if !seen {
3290                         missing_fields.push(
3291                             format!("`{}`", &token::get_name(name)))
3292                     }
3293                 }
3294
3295                 span_err!(tcx.sess, span, E0063,
3296                     "missing field{}: {}",
3297                     if missing_fields.len() == 1 {""} else {"s"},
3298                     missing_fields.connect(", "));
3299              }
3300         }
3301
3302         if !error_happened {
3303             fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3304                                 class_id, substitutions));
3305         }
3306     }
3307
3308     fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3309                                          id: ast::NodeId,
3310                                          span: codemap::Span,
3311                                          class_id: ast::DefId,
3312                                          fields: &'tcx [ast::Field],
3313                                          base_expr: Option<&'tcx ast::Expr>) {
3314         let tcx = fcx.ccx.tcx;
3315
3316         // Generate the struct type.
3317         let TypeAndSubsts {
3318             ty: mut struct_type,
3319             substs: struct_substs
3320         } = fcx.instantiate_type(span, class_id);
3321
3322         // Look up and check the fields.
3323         let class_fields = ty::lookup_struct_fields(tcx, class_id);
3324         check_struct_or_variant_fields(fcx,
3325                                        struct_type,
3326                                        span,
3327                                        class_id,
3328                                        id,
3329                                        fcx.ccx.tcx.mk_substs(struct_substs),
3330                                        &class_fields[..],
3331                                        fields,
3332                                        base_expr.is_none(),
3333                                        None);
3334         if ty::type_is_error(fcx.node_ty(id)) {
3335             struct_type = tcx.types.err;
3336         }
3337
3338         // Check the base expression if necessary.
3339         match base_expr {
3340             None => {}
3341             Some(base_expr) => {
3342                 check_expr_has_type(fcx, &*base_expr, struct_type);
3343             }
3344         }
3345
3346         // Write in the resulting type.
3347         fcx.write_ty(id, struct_type);
3348     }
3349
3350     fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3351                                           id: ast::NodeId,
3352                                           span: codemap::Span,
3353                                           enum_id: ast::DefId,
3354                                           variant_id: ast::DefId,
3355                                           fields: &'tcx [ast::Field]) {
3356         let tcx = fcx.ccx.tcx;
3357
3358         // Look up the number of type parameters and the raw type, and
3359         // determine whether the enum is region-parameterized.
3360         let TypeAndSubsts {
3361             ty: enum_type,
3362             substs: substitutions
3363         } = fcx.instantiate_type(span, enum_id);
3364
3365         // Look up and check the enum variant fields.
3366         let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3367         check_struct_or_variant_fields(fcx,
3368                                        enum_type,
3369                                        span,
3370                                        variant_id,
3371                                        id,
3372                                        fcx.ccx.tcx.mk_substs(substitutions),
3373                                        &variant_fields[..],
3374                                        fields,
3375                                        true,
3376                                        Some(enum_id));
3377         fcx.write_ty(id, enum_type);
3378     }
3379
3380     fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3381                                              id: ast::NodeId,
3382                                              fields: &'tcx [ast::Field],
3383                                              base_expr: &'tcx Option<P<ast::Expr>>) {
3384         // Make sure to still write the types
3385         // otherwise we might ICE
3386         fcx.write_error(id);
3387         for field in fields {
3388             check_expr(fcx, &*field.expr);
3389         }
3390         match *base_expr {
3391             Some(ref base) => check_expr(fcx, &**base),
3392             None => {}
3393         }
3394     }
3395
3396     type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3397
3398     let tcx = fcx.ccx.tcx;
3399     let id = expr.id;
3400     match expr.node {
3401       ast::ExprBox(ref opt_place, ref subexpr) => {
3402           opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3403           check_expr(fcx, &**subexpr);
3404
3405           let mut checked = false;
3406           opt_place.as_ref().map(|place| match place.node {
3407               ast::ExprPath(ref path) => {
3408                   // FIXME(pcwalton): For now we hardcode the two permissible
3409                   // places: the exchange heap and the managed heap.
3410                   let definition = lookup_def(fcx, path.span, place.id);
3411                   let def_id = definition.def_id();
3412                   let referent_ty = fcx.expr_ty(&**subexpr);
3413                   if tcx.lang_items.exchange_heap() == Some(def_id) {
3414                       fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3415                       checked = true
3416                   }
3417               }
3418               _ => {}
3419           });
3420
3421           if !checked {
3422               span_err!(tcx.sess, expr.span, E0066,
3423                   "only the managed heap and exchange heap are currently supported");
3424               fcx.write_ty(id, tcx.types.err);
3425           }
3426       }
3427
3428       ast::ExprLit(ref lit) => {
3429         let typ = check_lit(fcx, &**lit, expected);
3430         fcx.write_ty(id, typ);
3431       }
3432       ast::ExprBinary(op, ref lhs, ref rhs) => {
3433         check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3434
3435         let lhs_ty = fcx.expr_ty(&**lhs);
3436         let rhs_ty = fcx.expr_ty(&**rhs);
3437         if ty::type_is_error(lhs_ty) ||
3438             ty::type_is_error(rhs_ty) {
3439             fcx.write_error(id);
3440         }
3441       }
3442       ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3443         check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3444
3445         let lhs_t = fcx.expr_ty(&**lhs);
3446         let result_t = fcx.expr_ty(expr);
3447         demand::suptype(fcx, expr.span, result_t, lhs_t);
3448
3449         let tcx = fcx.tcx();
3450         if !ty::expr_is_lval(tcx, &**lhs) {
3451             span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3452         }
3453
3454         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3455
3456         // Overwrite result of check_binop...this preserves existing behavior
3457         // but seems quite dubious with regard to user-defined methods
3458         // and so forth. - Niko
3459         if !ty::type_is_error(result_t) {
3460             fcx.write_nil(expr.id);
3461         }
3462       }
3463       ast::ExprUnary(unop, ref oprnd) => {
3464         let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3465             match unop {
3466                 ast::UnUniq => match ty.sty {
3467                     ty::ty_uniq(ty) => {
3468                         Expectation::rvalue_hint(ty)
3469                     }
3470                     _ => {
3471                         NoExpectation
3472                     }
3473                 },
3474                 ast::UnNot | ast::UnNeg => {
3475                     expected
3476                 }
3477                 ast::UnDeref => {
3478                     NoExpectation
3479                 }
3480             }
3481         });
3482         let lvalue_pref = match unop {
3483             ast::UnDeref => lvalue_pref,
3484             _ => NoPreference
3485         };
3486         check_expr_with_expectation_and_lvalue_pref(
3487             fcx, &**oprnd, expected_inner, lvalue_pref);
3488         let mut oprnd_t = fcx.expr_ty(&**oprnd);
3489
3490         if !ty::type_is_error(oprnd_t) {
3491             match unop {
3492                 ast::UnUniq => {
3493                     oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3494                 }
3495                 ast::UnDeref => {
3496                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3497                     oprnd_t = match ty::deref(oprnd_t, true) {
3498                         Some(mt) => mt.ty,
3499                         None => match try_overloaded_deref(fcx, expr.span,
3500                                                            Some(MethodCall::expr(expr.id)),
3501                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
3502                             Some(mt) => mt.ty,
3503                             None => {
3504                                 let is_newtype = match oprnd_t.sty {
3505                                     ty::ty_struct(did, substs) => {
3506                                         let fields = ty::struct_fields(fcx.tcx(), did, substs);
3507                                         fields.len() == 1
3508                                         && fields[0].name ==
3509                                         token::special_idents::unnamed_field.name
3510                                     }
3511                                     _ => false
3512                                 };
3513                                 if is_newtype {
3514                                     // This is an obsolete struct deref
3515                                     span_err!(tcx.sess, expr.span, E0068,
3516                                         "single-field tuple-structs can \
3517                                          no longer be dereferenced");
3518                                 } else {
3519                                     fcx.type_error_message(expr.span, |actual| {
3520                                         format!("type `{}` cannot be \
3521                                                 dereferenced", actual)
3522                                     }, oprnd_t, None);
3523                                 }
3524                                 tcx.types.err
3525                             }
3526                         }
3527                     };
3528                 }
3529                 ast::UnNot => {
3530                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3531                                                          oprnd_t);
3532                     if !(ty::type_is_integral(oprnd_t) ||
3533                          oprnd_t.sty == ty::ty_bool) {
3534                         oprnd_t = check_user_unop(fcx, "!", "not",
3535                                                   tcx.lang_items.not_trait(),
3536                                                   expr, &**oprnd, oprnd_t, unop);
3537                     }
3538                 }
3539                 ast::UnNeg => {
3540                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3541                                                          oprnd_t);
3542                     if !(ty::type_is_integral(oprnd_t) ||
3543                          ty::type_is_fp(oprnd_t)) {
3544                         oprnd_t = check_user_unop(fcx, "-", "neg",
3545                                                   tcx.lang_items.neg_trait(),
3546                                                   expr, &**oprnd, oprnd_t, unop);
3547                     }
3548                 }
3549             }
3550         }
3551         fcx.write_ty(id, oprnd_t);
3552       }
3553       ast::ExprAddrOf(mutbl, ref oprnd) => {
3554         let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3555             match ty.sty {
3556                 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3557                     if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3558                         // Lvalues may legitimately have unsized types.
3559                         // For example, dereferences of a fat pointer and
3560                         // the last field of a struct can be unsized.
3561                         ExpectHasType(mt.ty)
3562                     } else {
3563                         Expectation::rvalue_hint(mt.ty)
3564                     }
3565                 }
3566                 _ => NoExpectation
3567             }
3568         });
3569         let lvalue_pref = match mutbl {
3570             ast::MutMutable => PreferMutLvalue,
3571             ast::MutImmutable => NoPreference
3572         };
3573         check_expr_with_expectation_and_lvalue_pref(fcx,
3574                                                     &**oprnd,
3575                                                     hint,
3576                                                     lvalue_pref);
3577
3578         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3579         let oprnd_t = if ty::type_is_error(tm.ty) {
3580             tcx.types.err
3581         } else {
3582             // Note: at this point, we cannot say what the best lifetime
3583             // is to use for resulting pointer.  We want to use the
3584             // shortest lifetime possible so as to avoid spurious borrowck
3585             // errors.  Moreover, the longest lifetime will depend on the
3586             // precise details of the value whose address is being taken
3587             // (and how long it is valid), which we don't know yet until type
3588             // inference is complete.
3589             //
3590             // Therefore, here we simply generate a region variable.  The
3591             // region inferencer will then select the ultimate value.
3592             // Finally, borrowck is charged with guaranteeing that the
3593             // value whose address was taken can actually be made to live
3594             // as long as it needs to live.
3595             let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3596             ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3597         };
3598         fcx.write_ty(id, oprnd_t);
3599       }
3600       ast::ExprPath(ref path) => {
3601           let defn = lookup_def(fcx, path.span, id);
3602           let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
3603           instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
3604
3605           // We always require that the type provided as the value for
3606           // a type parameter outlives the moment of instantiation.
3607           constrain_path_type_parameters(fcx, expr);
3608       }
3609       ast::ExprQPath(ref qpath) => {
3610           // Require explicit type params for the trait.
3611           let self_ty = fcx.to_ty(&*qpath.self_type);
3612           astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3613
3614           let defn = lookup_def(fcx, expr.span, id);
3615           let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
3616           let mut path = qpath.trait_ref.path.clone();
3617           path.segments.push(qpath.item_path.clone());
3618           instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
3619                            defn, expr.span, expr.id);
3620
3621           // We always require that the type provided as the value for
3622           // a type parameter outlives the moment of instantiation.
3623           constrain_path_type_parameters(fcx, expr);
3624       }
3625       ast::ExprInlineAsm(ref ia) => {
3626           for &(_, ref input) in &ia.inputs {
3627               check_expr(fcx, &**input);
3628           }
3629           for &(_, ref out, _) in &ia.outputs {
3630               check_expr(fcx, &**out);
3631           }
3632           fcx.write_nil(id);
3633       }
3634       ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3635       ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3636       ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3637       ast::ExprRet(ref expr_opt) => {
3638         match fcx.ret_ty {
3639             ty::FnConverging(result_type) => {
3640                 match *expr_opt {
3641                     None =>
3642                         if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3643                                                     result_type, ty::mk_nil(fcx.tcx())) {
3644                             span_err!(tcx.sess, expr.span, E0069,
3645                                 "`return;` in function returning non-nil");
3646                         },
3647                     Some(ref e) => {
3648                         check_expr_coercable_to_type(fcx, &**e, result_type);
3649                     }
3650                 }
3651             }
3652             ty::FnDiverging => {
3653                 if let Some(ref e) = *expr_opt {
3654                     check_expr(fcx, &**e);
3655                 }
3656                 span_err!(tcx.sess, expr.span, E0166,
3657                     "`return` in a function declared as diverging");
3658             }
3659         }
3660         fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3661       }
3662       ast::ExprParen(ref a) => {
3663         check_expr_with_expectation_and_lvalue_pref(fcx,
3664                                                     &**a,
3665                                                     expected,
3666                                                     lvalue_pref);
3667         fcx.write_ty(id, fcx.expr_ty(&**a));
3668       }
3669       ast::ExprAssign(ref lhs, ref rhs) => {
3670         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3671
3672         let tcx = fcx.tcx();
3673         if !ty::expr_is_lval(tcx, &**lhs) {
3674             span_err!(tcx.sess, expr.span, E0070,
3675                 "illegal left-hand side expression");
3676         }
3677
3678         let lhs_ty = fcx.expr_ty(&**lhs);
3679         check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3680         let rhs_ty = fcx.expr_ty(&**rhs);
3681
3682         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3683
3684         if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3685             fcx.write_error(id);
3686         } else {
3687             fcx.write_nil(id);
3688         }
3689       }
3690       ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3691         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3692                         id, expr.span, expected);
3693       }
3694       ast::ExprIfLet(..) => {
3695         tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3696       }
3697       ast::ExprWhile(ref cond, ref body, _) => {
3698         check_expr_has_type(fcx, &**cond, tcx.types.bool);
3699         check_block_no_value(fcx, &**body);
3700         let cond_ty = fcx.expr_ty(&**cond);
3701         let body_ty = fcx.node_ty(body.id);
3702         if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3703             fcx.write_error(id);
3704         }
3705         else {
3706             fcx.write_nil(id);
3707         }
3708       }
3709       ast::ExprWhileLet(..) => {
3710         tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3711       }
3712       ast::ExprForLoop(..) => {
3713         tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3714       }
3715       ast::ExprLoop(ref body, _) => {
3716         check_block_no_value(fcx, &**body);
3717         if !may_break(tcx, expr.id, &**body) {
3718             fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3719         } else {
3720             fcx.write_nil(id);
3721         }
3722       }
3723       ast::ExprMatch(ref discrim, ref arms, match_src) => {
3724         _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3725       }
3726       ast::ExprClosure(capture, ref decl, ref body) => {
3727           closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3728       }
3729       ast::ExprBlock(ref b) => {
3730         check_block_with_expected(fcx, &**b, expected);
3731         fcx.write_ty(id, fcx.node_ty(b.id));
3732       }
3733       ast::ExprCall(ref callee, ref args) => {
3734           callee::check_call(fcx, expr, &**callee, &args[..], expected);
3735       }
3736       ast::ExprMethodCall(ident, ref tps, ref args) => {
3737         check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3738         let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3739         let  args_err = arg_tys.fold(false,
3740              |rest_err, a| {
3741               rest_err || ty::type_is_error(a)});
3742         if args_err {
3743             fcx.write_error(id);
3744         }
3745       }
3746       ast::ExprCast(ref e, ref t) => {
3747         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3748             check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3749         }
3750         check_cast(fcx, expr, &**e, &**t);
3751       }
3752       ast::ExprVec(ref args) => {
3753         let uty = expected.to_option(fcx).and_then(|uty| {
3754             match uty.sty {
3755                 ty::ty_vec(ty, _) => Some(ty),
3756                 _ => None
3757             }
3758         });
3759
3760         let typ = match uty {
3761             Some(uty) => {
3762                 for e in args {
3763                     check_expr_coercable_to_type(fcx, &**e, uty);
3764                 }
3765                 uty
3766             }
3767             None => {
3768                 let t: Ty = fcx.infcx().next_ty_var();
3769                 for e in args {
3770                     check_expr_has_type(fcx, &**e, t);
3771                 }
3772                 t
3773             }
3774         };
3775         let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3776         fcx.write_ty(id, typ);
3777       }
3778       ast::ExprRepeat(ref element, ref count_expr) => {
3779         check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3780         let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3781
3782         let uty = match expected {
3783             ExpectHasType(uty) => {
3784                 match uty.sty {
3785                     ty::ty_vec(ty, _) => Some(ty),
3786                     _ => None
3787                 }
3788             }
3789             _ => None
3790         };
3791
3792         let (element_ty, t) = match uty {
3793             Some(uty) => {
3794                 check_expr_coercable_to_type(fcx, &**element, uty);
3795                 (uty, uty)
3796             }
3797             None => {
3798                 let t: Ty = fcx.infcx().next_ty_var();
3799                 check_expr_has_type(fcx, &**element, t);
3800                 (fcx.expr_ty(&**element), t)
3801             }
3802         };
3803
3804         if count > 1 {
3805             // For [foo, ..n] where n > 1, `foo` must have
3806             // Copy type:
3807             fcx.require_type_meets(
3808                 t,
3809                 expr.span,
3810                 traits::RepeatVec,
3811                 ty::BoundCopy);
3812         }
3813
3814         if ty::type_is_error(element_ty) {
3815             fcx.write_error(id);
3816         } else {
3817             let t = ty::mk_vec(tcx, t, Some(count));
3818             fcx.write_ty(id, t);
3819         }
3820       }
3821       ast::ExprTup(ref elts) => {
3822         let flds = expected.only_has_type(fcx).and_then(|ty| {
3823             match ty.sty {
3824                 ty::ty_tup(ref flds) => Some(&flds[..]),
3825                 _ => None
3826             }
3827         });
3828         let mut err_field = false;
3829
3830         let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3831             let t = match flds {
3832                 Some(ref fs) if i < fs.len() => {
3833                     let ety = fs[i];
3834                     check_expr_coercable_to_type(fcx, &**e, ety);
3835                     ety
3836                 }
3837                 _ => {
3838                     check_expr_with_expectation(fcx, &**e, NoExpectation);
3839                     fcx.expr_ty(&**e)
3840                 }
3841             };
3842             err_field = err_field || ty::type_is_error(t);
3843             t
3844         }).collect();
3845         if err_field {
3846             fcx.write_error(id);
3847         } else {
3848             let typ = ty::mk_tup(tcx, elt_ts);
3849             fcx.write_ty(id, typ);
3850         }
3851       }
3852       ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3853         // Resolve the path.
3854         let def = tcx.def_map.borrow().get(&id).cloned();
3855         let struct_id = match def {
3856             Some(def::DefVariant(enum_id, variant_id, true)) => {
3857                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3858                                           variant_id, &fields[..]);
3859                 enum_id
3860             }
3861             Some(def::DefTrait(def_id)) => {
3862                 span_err!(tcx.sess, path.span, E0159,
3863                     "use of trait `{}` as a struct constructor",
3864                     pprust::path_to_string(path));
3865                 check_struct_fields_on_error(fcx,
3866                                              id,
3867                                              &fields[..],
3868                                              base_expr);
3869                 def_id
3870             },
3871             Some(def) => {
3872                 // Verify that this was actually a struct.
3873                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3874                 match typ.ty.sty {
3875                     ty::ty_struct(struct_did, _) => {
3876                         check_struct_constructor(fcx,
3877                                                  id,
3878                                                  expr.span,
3879                                                  struct_did,
3880                                                  &fields[..],
3881                                                  base_expr.as_ref().map(|e| &**e));
3882                     }
3883                     _ => {
3884                         span_err!(tcx.sess, path.span, E0071,
3885                             "`{}` does not name a structure",
3886                             pprust::path_to_string(path));
3887                         check_struct_fields_on_error(fcx,
3888                                                      id,
3889                                                      &fields[..],
3890                                                      base_expr);
3891                     }
3892                 }
3893
3894                 def.def_id()
3895             }
3896             _ => {
3897                 tcx.sess.span_bug(path.span,
3898                                   "structure constructor wasn't resolved")
3899             }
3900         };
3901
3902         // Turn the path into a type and verify that that type unifies with
3903         // the resulting structure type. This is needed to handle type
3904         // parameters correctly.
3905         let actual_structure_type = fcx.expr_ty(&*expr);
3906         if !ty::type_is_error(actual_structure_type) {
3907             let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3908             match fcx.mk_subty(false,
3909                                infer::Misc(path.span),
3910                                actual_structure_type,
3911                                type_and_substs.ty) {
3912                 Ok(()) => {}
3913                 Err(type_error) => {
3914                     let type_error_description =
3915                         ty::type_err_to_str(tcx, &type_error);
3916                     span_err!(fcx.tcx().sess, path.span, E0235,
3917                                  "structure constructor specifies a \
3918                                          structure of type `{}`, but this \
3919                                          structure has type `{}`: {}",
3920                                          fcx.infcx()
3921                                             .ty_to_string(type_and_substs.ty),
3922                                          fcx.infcx()
3923                                             .ty_to_string(
3924                                                 actual_structure_type),
3925                                          type_error_description);
3926                     ty::note_and_explain_type_err(tcx, &type_error);
3927                 }
3928             }
3929         }
3930
3931         fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3932       }
3933       ast::ExprField(ref base, ref field) => {
3934         check_field(fcx, expr, lvalue_pref, &**base, field);
3935       }
3936       ast::ExprTupField(ref base, idx) => {
3937         check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3938       }
3939       ast::ExprIndex(ref base, ref idx) => {
3940           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3941           let base_t = fcx.expr_ty(&**base);
3942           if ty::type_is_error(base_t) {
3943               fcx.write_ty(id, base_t);
3944           } else {
3945               check_expr(fcx, &**idx);
3946               let idx_t = fcx.expr_ty(&**idx);
3947               if ty::type_is_error(idx_t) {
3948                   fcx.write_ty(id, idx_t);
3949               } else {
3950                   let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3951
3952                   let result =
3953                       autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3954                           try_index_step(fcx,
3955                                          MethodCall::expr(expr.id),
3956                                          expr,
3957                                          &**base,
3958                                          adj_ty,
3959                                          adj,
3960                                          lvalue_pref,
3961                                          idx_t)
3962                       });
3963
3964                   match result {
3965                       Some((index_ty, element_ty)) => {
3966                           // FIXME: we've already checked idx above, we should
3967                           // probably just demand subtype or something here.
3968                           check_expr_has_type(fcx, &**idx, index_ty);
3969                           fcx.write_ty(id, element_ty);
3970                       }
3971                       _ => {
3972                           check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3973                           fcx.type_error_message(
3974                               expr.span,
3975                               |actual| {
3976                                   format!("cannot index a value of type `{}`",
3977                                           actual)
3978                               },
3979                               base_t,
3980                               None);
3981                           fcx.write_ty(id, fcx.tcx().types.err);
3982                       }
3983                   }
3984               }
3985           }
3986        }
3987        ast::ExprRange(ref start, ref end) => {
3988           let t_start = start.as_ref().map(|e| {
3989             check_expr(fcx, &**e);
3990             fcx.expr_ty(&**e)
3991           });
3992           let t_end = end.as_ref().map(|e| {
3993             check_expr(fcx, &**e);
3994             fcx.expr_ty(&**e)
3995           });
3996
3997           let idx_type = match (t_start, t_end) {
3998               (Some(ty), None) | (None, Some(ty)) => {
3999                   Some(ty)
4000               }
4001               (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
4002                                                ty::type_is_error(t_end)) => {
4003                   Some(fcx.tcx().types.err)
4004               }
4005               (Some(t_start), Some(t_end)) => {
4006                   Some(infer::common_supertype(fcx.infcx(),
4007                                                infer::RangeExpression(expr.span),
4008                                                true,
4009                                                t_start,
4010                                                t_end))
4011               }
4012               _ => None
4013           };
4014
4015           // Note that we don't check the type of start/end satisfy any
4016           // bounds because right now the range structs do not have any. If we add
4017           // some bounds, then we'll need to check `t_start` against them here.
4018
4019           let range_type = match idx_type {
4020             Some(idx_type) if ty::type_is_error(idx_type) => {
4021                 fcx.tcx().types.err
4022             }
4023             Some(idx_type) => {
4024                 // Find the did from the appropriate lang item.
4025                 let did = match (start, end) {
4026                     (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
4027                     (&Some(_), &None) => tcx.lang_items.range_from_struct(),
4028                     (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4029                     (&None, &None) => {
4030                         tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4031                     }
4032                 };
4033
4034                 if let Some(did) = did {
4035                     let predicates = ty::lookup_predicates(tcx, did);
4036                     let substs = Substs::new_type(vec![idx_type], vec![]);
4037                     let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
4038                     fcx.add_obligations_for_parameters(
4039                         traits::ObligationCause::new(expr.span,
4040                                                      fcx.body_id,
4041                                                      traits::ItemObligation(did)),
4042                         &bounds);
4043
4044                     ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4045                 } else {
4046                     span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
4047                     fcx.tcx().types.err
4048                 }
4049             }
4050             None => {
4051                 // Neither start nor end => RangeFull
4052                 if let Some(did) = tcx.lang_items.range_full_struct() {
4053                     let substs = Substs::new_type(vec![], vec![]);
4054                     ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4055                 } else {
4056                     span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
4057                     fcx.tcx().types.err
4058                 }
4059             }
4060           };
4061
4062           fcx.write_ty(id, range_type);
4063        }
4064
4065     }
4066
4067     debug!("type of expr({}) {} is...", expr.id,
4068            syntax::print::pprust::expr_to_string(expr));
4069     debug!("... {}, expected is {}",
4070            ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4071            expected.repr(tcx));
4072
4073     unifier();
4074 }
4075
4076 fn constrain_path_type_parameters(fcx: &FnCtxt,
4077                                   expr: &ast::Expr)
4078 {
4079     fcx.opt_node_ty_substs(expr.id, |item_substs| {
4080         fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4081     });
4082 }
4083
4084 impl<'tcx> Expectation<'tcx> {
4085     /// Provide an expectation for an rvalue expression given an *optional*
4086     /// hint, which is not required for type safety (the resulting type might
4087     /// be checked higher up, as is the case with `&expr` and `box expr`), but
4088     /// is useful in determining the concrete type.
4089     ///
4090     /// The primary use case is where the expected type is a fat pointer,
4091     /// like `&[int]`. For example, consider the following statement:
4092     ///
4093     ///    let x: &[int] = &[1, 2, 3];
4094     ///
4095     /// In this case, the expected type for the `&[1, 2, 3]` expression is
4096     /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4097     /// expectation `ExpectHasType([int])`, that would be too strong --
4098     /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4099     /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4100     /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4101     /// which still is useful, because it informs integer literals and the like.
4102     /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4103     /// for examples of where this comes up,.
4104     fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4105         match ty.sty {
4106             ty::ty_vec(_, None) | ty::ty_trait(..) => {
4107                 ExpectRvalueLikeUnsized(ty)
4108             }
4109             _ => ExpectHasType(ty)
4110         }
4111     }
4112
4113     // Resolves `expected` by a single level if it is a variable. If
4114     // there is no expected type or resolution is not possible (e.g.,
4115     // no constraints yet present), just returns `None`.
4116     fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4117         match self {
4118             NoExpectation => {
4119                 NoExpectation
4120             }
4121             ExpectCastableToType(t) => {
4122                 ExpectCastableToType(
4123                     fcx.infcx().resolve_type_vars_if_possible(&t))
4124             }
4125             ExpectHasType(t) => {
4126                 ExpectHasType(
4127                     fcx.infcx().resolve_type_vars_if_possible(&t))
4128             }
4129             ExpectRvalueLikeUnsized(t) => {
4130                 ExpectRvalueLikeUnsized(
4131                     fcx.infcx().resolve_type_vars_if_possible(&t))
4132             }
4133         }
4134     }
4135
4136     fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4137         match self.resolve(fcx) {
4138             NoExpectation => None,
4139             ExpectCastableToType(ty) |
4140             ExpectHasType(ty) |
4141             ExpectRvalueLikeUnsized(ty) => Some(ty),
4142         }
4143     }
4144
4145     fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4146         match self.resolve(fcx) {
4147             ExpectHasType(ty) => Some(ty),
4148             _ => None
4149         }
4150     }
4151 }
4152
4153 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4154     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4155         match *self {
4156             NoExpectation => format!("NoExpectation"),
4157             ExpectHasType(t) => format!("ExpectHasType({})",
4158                                         t.repr(tcx)),
4159             ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4160                                                t.repr(tcx)),
4161             ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4162                                                   t.repr(tcx)),
4163         }
4164     }
4165 }
4166
4167 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
4168                                        nid: ast::NodeId,
4169                                        init: &'tcx ast::Expr)
4170 {
4171     let local_ty = fcx.local_ty(init.span, nid);
4172     check_expr_coercable_to_type(fcx, init, local_ty)
4173 }
4174
4175 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)  {
4176     let tcx = fcx.ccx.tcx;
4177
4178     let t = fcx.local_ty(local.span, local.id);
4179     fcx.write_ty(local.id, t);
4180
4181     if let Some(ref init) = local.init {
4182         check_decl_initializer(fcx, local.id, &**init);
4183         let init_ty = fcx.expr_ty(&**init);
4184         if ty::type_is_error(init_ty) {
4185             fcx.write_ty(local.id, init_ty);
4186         }
4187     }
4188
4189     let pcx = pat_ctxt {
4190         fcx: fcx,
4191         map: pat_id_map(&tcx.def_map, &*local.pat),
4192     };
4193     _match::check_pat(&pcx, &*local.pat, t);
4194     let pat_ty = fcx.node_ty(local.pat.id);
4195     if ty::type_is_error(pat_ty) {
4196         fcx.write_ty(local.id, pat_ty);
4197     }
4198 }
4199
4200 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
4201     let node_id;
4202     let mut saw_bot = false;
4203     let mut saw_err = false;
4204     match stmt.node {
4205       ast::StmtDecl(ref decl, id) => {
4206         node_id = id;
4207         match decl.node {
4208           ast::DeclLocal(ref l) => {
4209               check_decl_local(fcx, &**l);
4210               let l_t = fcx.node_ty(l.id);
4211               saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4212               saw_err = saw_err || ty::type_is_error(l_t);
4213           }
4214           ast::DeclItem(_) => {/* ignore for now */ }
4215         }
4216       }
4217       ast::StmtExpr(ref expr, id) => {
4218         node_id = id;
4219         // Check with expected type of ()
4220         check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4221         let expr_ty = fcx.expr_ty(&**expr);
4222         saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4223         saw_err = saw_err || ty::type_is_error(expr_ty);
4224       }
4225       ast::StmtSemi(ref expr, id) => {
4226         node_id = id;
4227         check_expr(fcx, &**expr);
4228         let expr_ty = fcx.expr_ty(&**expr);
4229         saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4230         saw_err |= ty::type_is_error(expr_ty);
4231       }
4232       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4233     }
4234     if saw_bot {
4235         fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4236     }
4237     else if saw_err {
4238         fcx.write_error(node_id);
4239     }
4240     else {
4241         fcx.write_nil(node_id)
4242     }
4243 }
4244
4245 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block)  {
4246     check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4247     let blkty = fcx.node_ty(blk.id);
4248     if ty::type_is_error(blkty) {
4249         fcx.write_error(blk.id);
4250     } else {
4251         let nilty = ty::mk_nil(fcx.tcx());
4252         demand::suptype(fcx, blk.span, nilty, blkty);
4253     }
4254 }
4255
4256 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4257                                        blk: &'tcx ast::Block,
4258                                        expected: Expectation<'tcx>) {
4259     let prev = {
4260         let mut fcx_ps = fcx.ps.borrow_mut();
4261         let unsafety_state = fcx_ps.recurse(blk);
4262         replace(&mut *fcx_ps, unsafety_state)
4263     };
4264
4265     let mut warned = false;
4266     let mut any_diverges = false;
4267     let mut any_err = false;
4268     for s in &blk.stmts {
4269         check_stmt(fcx, &**s);
4270         let s_id = ast_util::stmt_id(&**s);
4271         let s_ty = fcx.node_ty(s_id);
4272         if any_diverges && !warned && match s.node {
4273             ast::StmtDecl(ref decl, _) => {
4274                 match decl.node {
4275                     ast::DeclLocal(_) => true,
4276                     _ => false,
4277                 }
4278             }
4279             ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4280             _ => false
4281         } {
4282             fcx.ccx
4283                 .tcx
4284                 .sess
4285                 .add_lint(lint::builtin::UNREACHABLE_CODE,
4286                           s_id,
4287                           s.span,
4288                           "unreachable statement".to_string());
4289             warned = true;
4290         }
4291         any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4292         any_err = any_err || ty::type_is_error(s_ty);
4293     }
4294     match blk.expr {
4295         None => if any_err {
4296             fcx.write_error(blk.id);
4297         } else if any_diverges {
4298             fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4299         } else {
4300             fcx.write_nil(blk.id);
4301         },
4302         Some(ref e) => {
4303             if any_diverges && !warned {
4304                 fcx.ccx
4305                     .tcx
4306                     .sess
4307                     .add_lint(lint::builtin::UNREACHABLE_CODE,
4308                               e.id,
4309                               e.span,
4310                               "unreachable expression".to_string());
4311             }
4312             let ety = match expected {
4313                 ExpectHasType(ety) => {
4314                     check_expr_coercable_to_type(fcx, &**e, ety);
4315                     ety
4316                 }
4317                 _ => {
4318                     check_expr_with_expectation(fcx, &**e, expected);
4319                     fcx.expr_ty(&**e)
4320                 }
4321             };
4322
4323             if any_err {
4324                 fcx.write_error(blk.id);
4325             } else if any_diverges {
4326                 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4327             } else {
4328                 fcx.write_ty(blk.id, ety);
4329             }
4330         }
4331     };
4332
4333     *fcx.ps.borrow_mut() = prev;
4334 }
4335
4336 /// Checks a constant appearing in a type. At the moment this is just the
4337 /// length expression in a fixed-length vector, but someday it might be
4338 /// extended to type-level numeric literals.
4339 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4340                                 expr: &'tcx ast::Expr,
4341                                 expected_type: Ty<'tcx>) {
4342     let inh = static_inherited_fields(ccx);
4343     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4344     check_const_with_ty(&fcx, expr.span, expr, expected_type);
4345 }
4346
4347 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4348                         sp: Span,
4349                         e: &'tcx ast::Expr,
4350                         id: ast::NodeId) {
4351     let inh = static_inherited_fields(ccx);
4352     let rty = ty::node_id_to_type(ccx.tcx, id);
4353     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4354     let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4355     check_const_with_ty(&fcx, sp, e, declty);
4356 }
4357
4358 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4359                                  _: Span,
4360                                  e: &'tcx ast::Expr,
4361                                  declty: Ty<'tcx>) {
4362     // Gather locals in statics (because of block expressions).
4363     // This is technically unnecessary because locals in static items are forbidden,
4364     // but prevents type checking from blowing up before const checking can properly
4365     // emit a error.
4366     GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4367
4368     check_expr_with_hint(fcx, e, declty);
4369     demand::coerce(fcx, e.span, declty, e);
4370     vtable::select_all_fcx_obligations_or_error(fcx);
4371     regionck::regionck_expr(fcx, e);
4372     writeback::resolve_type_vars_in_expr(fcx, e);
4373 }
4374
4375 /// Checks whether a type can be represented in memory. In particular, it
4376 /// identifies types that contain themselves without indirection through a
4377 /// pointer, which would mean their size is unbounded. This is different from
4378 /// the question of whether a type can be instantiated. See the definition of
4379 /// `check_instantiable`.
4380 pub fn check_representable(tcx: &ty::ctxt,
4381                            sp: Span,
4382                            item_id: ast::NodeId,
4383                            designation: &str) -> bool {
4384     let rty = ty::node_id_to_type(tcx, item_id);
4385
4386     // Check that it is possible to represent this type. This call identifies
4387     // (1) types that contain themselves and (2) types that contain a different
4388     // recursive type. It is only necessary to throw an error on those that
4389     // contain themselves. For case 2, there must be an inner type that will be
4390     // caught by case 1.
4391     match ty::is_type_representable(tcx, sp, rty) {
4392       ty::SelfRecursive => {
4393         span_err!(tcx.sess, sp, E0072,
4394             "illegal recursive {} type; \
4395              wrap the inner value in a box to make it representable",
4396             designation);
4397         return false
4398       }
4399       ty::Representable | ty::ContainsRecursive => (),
4400     }
4401     return true
4402 }
4403
4404 /// Checks whether a type can be created without an instance of itself.
4405 /// This is similar but different from the question of whether a type
4406 /// can be represented.  For example, the following type:
4407 ///
4408 ///     enum foo { None, Some(foo) }
4409 ///
4410 /// is instantiable but is not representable.  Similarly, the type
4411 ///
4412 ///     enum foo { Some(@foo) }
4413 ///
4414 /// is representable, but not instantiable.
4415 pub fn check_instantiable(tcx: &ty::ctxt,
4416                           sp: Span,
4417                           item_id: ast::NodeId)
4418                           -> bool {
4419     let item_ty = ty::node_id_to_type(tcx, item_id);
4420     if !ty::is_instantiable(tcx, item_ty) {
4421         span_err!(tcx.sess, sp, E0073,
4422             "this type cannot be instantiated without an \
4423              instance of itself");
4424         span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4425             ppaux::ty_to_string(tcx, item_ty));
4426         false
4427     } else {
4428         true
4429     }
4430 }
4431
4432 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4433     let t = ty::node_id_to_type(tcx, id);
4434     if ty::type_needs_subst(t) {
4435         span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4436         return;
4437     }
4438     match t.sty {
4439         ty::ty_struct(did, substs) => {
4440             let fields = ty::lookup_struct_fields(tcx, did);
4441             if fields.is_empty() {
4442                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4443                 return;
4444             }
4445             let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4446             if !fields.iter().all(
4447                          |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4448                 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4449                 return;
4450             }
4451             if !ty::type_is_machine(e) {
4452                 span_err!(tcx.sess, sp, E0077,
4453                     "SIMD vector element type should be machine type");
4454                 return;
4455             }
4456         }
4457         _ => ()
4458     }
4459 }
4460
4461 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4462                                     sp: Span,
4463                                     vs: &'tcx [P<ast::Variant>],
4464                                     id: ast::NodeId) {
4465
4466     fn disr_in_range(ccx: &CrateCtxt,
4467                      ty: attr::IntType,
4468                      disr: ty::Disr) -> bool {
4469         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4470             match ty {
4471                 ast::TyU8 => disr as u8 as Disr == disr,
4472                 ast::TyU16 => disr as u16 as Disr == disr,
4473                 ast::TyU32 => disr as u32 as Disr == disr,
4474                 ast::TyU64 => disr as u64 as Disr == disr,
4475                 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4476             }
4477         }
4478         fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4479             match ty {
4480                 ast::TyI8 => disr as i8 as Disr == disr,
4481                 ast::TyI16 => disr as i16 as Disr == disr,
4482                 ast::TyI32 => disr as i32 as Disr == disr,
4483                 ast::TyI64 => disr as i64 as Disr == disr,
4484                 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4485             }
4486         }
4487         match ty {
4488             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4489             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4490         }
4491     }
4492
4493     fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4494                           vs: &'tcx [P<ast::Variant>],
4495                           id: ast::NodeId,
4496                           hint: attr::ReprAttr)
4497                           -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4498
4499         let rty = ty::node_id_to_type(ccx.tcx, id);
4500         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4501         let mut disr_vals: Vec<ty::Disr> = Vec::new();
4502         let mut prev_disr_val: Option<ty::Disr> = None;
4503
4504         for v in vs {
4505
4506             // If the discriminant value is specified explicitly in the enum check whether the
4507             // initialization expression is valid, otherwise use the last value plus one.
4508             let mut current_disr_val = match prev_disr_val {
4509                 Some(prev_disr_val) => prev_disr_val + 1,
4510                 None => ty::INITIAL_DISCRIMINANT_VALUE
4511             };
4512
4513             match v.node.disr_expr {
4514                 Some(ref e) => {
4515                     debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4516
4517                     let inh = static_inherited_fields(ccx);
4518                     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4519                     let declty = match hint {
4520                         attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4521                         attr::ReprInt(_, attr::SignedInt(ity)) => {
4522                             ty::mk_mach_int(fcx.tcx(), ity)
4523                         }
4524                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4525                             ty::mk_mach_uint(fcx.tcx(), ity)
4526                         },
4527                     };
4528                     check_const_with_ty(&fcx, e.span, &**e, declty);
4529                     // check_expr (from check_const pass) doesn't guarantee
4530                     // that the expression is in a form that eval_const_expr can
4531                     // handle, so we may still get an internal compiler error
4532
4533                     match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
4534                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4535                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4536                         Ok(_) => {
4537                             span_err!(ccx.tcx.sess, e.span, E0079,
4538                                 "expected signed integer constant");
4539                         }
4540                         Err(ref err) => {
4541                             span_err!(ccx.tcx.sess, e.span, E0080,
4542                                 "expected constant: {}", *err);
4543                         }
4544                     }
4545                 },
4546                 None => ()
4547             };
4548
4549             // Check for duplicate discriminant values
4550             match disr_vals.iter().position(|&x| x == current_disr_val) {
4551                 Some(i) => {
4552                     span_err!(ccx.tcx.sess, v.span, E0081,
4553                         "discriminant value `{}` already exists", disr_vals[i]);
4554                     span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4555                         "conflicting discriminant here")
4556                 }
4557                 None => {}
4558             }
4559             // Check for unrepresentable discriminant values
4560             match hint {
4561                 attr::ReprAny | attr::ReprExtern => (),
4562                 attr::ReprInt(sp, ity) => {
4563                     if !disr_in_range(ccx, ity, current_disr_val) {
4564                         span_err!(ccx.tcx.sess, v.span, E0082,
4565                             "discriminant value outside specified type");
4566                         span_note!(ccx.tcx.sess, sp,
4567                             "discriminant type specified here");
4568                     }
4569                 }
4570                 attr::ReprPacked => {
4571                     ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4572                 }
4573             }
4574             disr_vals.push(current_disr_val);
4575
4576             let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4577                                                                      current_disr_val));
4578             prev_disr_val = Some(current_disr_val);
4579
4580             variants.push(variant_info);
4581         }
4582
4583         return variants;
4584     }
4585
4586     let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4587         [].get(0).unwrap_or(&attr::ReprAny);
4588
4589     if hint != attr::ReprAny && vs.len() <= 1 {
4590         if vs.len() == 1 {
4591             span_err!(ccx.tcx.sess, sp, E0083,
4592                 "unsupported representation for univariant enum");
4593         } else {
4594             span_err!(ccx.tcx.sess, sp, E0084,
4595                 "unsupported representation for zero-variant enum");
4596         };
4597     }
4598
4599     let variants = do_check(ccx, vs, id, hint);
4600
4601     // cache so that ty::enum_variants won't repeat this work
4602     ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4603
4604     check_representable(ccx.tcx, sp, id, "enum");
4605
4606     // Check that it is possible to instantiate this enum:
4607     //
4608     // This *sounds* like the same that as representable, but it's
4609     // not.  See def'n of `check_instantiable()` for details.
4610     check_instantiable(ccx.tcx, sp, id);
4611 }
4612
4613 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4614     lookup_def_ccx(fcx.ccx, sp, id)
4615 }
4616
4617 // Returns the type parameter count and the type for the given definition.
4618 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4619                                                 sp: Span,
4620                                                 defn: def::Def)
4621                                                 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4622     match defn {
4623         def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4624             let typ = fcx.local_ty(sp, nid);
4625             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4626              ty::GenericPredicates::empty())
4627         }
4628         def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4629         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4630         def::DefStruct(id) | def::DefConst(id) => {
4631             (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4632         }
4633         def::DefTrait(_) |
4634         def::DefTy(..) |
4635         def::DefAssociatedTy(..) |
4636         def::DefAssociatedPath(..) |
4637         def::DefPrimTy(_) |
4638         def::DefTyParam(..) |
4639         def::DefMod(..) |
4640         def::DefForeignMod(..) |
4641         def::DefUse(..) |
4642         def::DefRegion(..) |
4643         def::DefTyParamBinder(..) |
4644         def::DefLabel(..) |
4645         def::DefSelfTy(..) => {
4646             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4647         }
4648     }
4649 }
4650
4651 // Instantiates the given path, which must refer to an item with the given
4652 // number of type parameters and type.
4653 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4654                                   path: &ast::Path,
4655                                   type_scheme: TypeScheme<'tcx>,
4656                                   type_predicates: &ty::GenericPredicates<'tcx>,
4657                                   opt_self_ty: Option<Ty<'tcx>>,
4658                                   def: def::Def,
4659                                   span: Span,
4660                                   node_id: ast::NodeId) {
4661     debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4662            path.repr(fcx.tcx()),
4663            def.repr(fcx.tcx()),
4664            node_id,
4665            type_scheme.repr(fcx.tcx()));
4666
4667     // We need to extract the type parameters supplied by the user in
4668     // the path `path`. Due to the current setup, this is a bit of a
4669     // tricky-process; the problem is that resolve only tells us the
4670     // end-point of the path resolution, and not the intermediate steps.
4671     // Luckily, we can (at least for now) deduce the intermediate steps
4672     // just from the end-point.
4673     //
4674     // There are basically three cases to consider:
4675     //
4676     // 1. Reference to a *type*, such as a struct or enum:
4677     //
4678     //        mod a { struct Foo<T> { ... } }
4679     //
4680     //    Because we don't allow types to be declared within one
4681     //    another, a path that leads to a type will always look like
4682     //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
4683     //    that only the final segment can have type parameters, and
4684     //    they are located in the TypeSpace.
4685     //
4686     //    *Note:* Generally speaking, references to types don't
4687     //    actually pass through this function, but rather the
4688     //    `ast_ty_to_ty` function in `astconv`. However, in the case
4689     //    of struct patterns (and maybe literals) we do invoke
4690     //    `instantiate_path` to get the general type of an instance of
4691     //    a struct. (In these cases, there are actually no type
4692     //    parameters permitted at present, but perhaps we will allow
4693     //    them in the future.)
4694     //
4695     // 1b. Reference to a enum variant or tuple-like struct:
4696     //
4697     //        struct foo<T>(...)
4698     //        enum E<T> { foo(...) }
4699     //
4700     //    In these cases, the parameters are declared in the type
4701     //    space.
4702     //
4703     // 2. Reference to a *fn item*:
4704     //
4705     //        fn foo<T>() { }
4706     //
4707     //    In this case, the path will again always have the form
4708     //    `a::b::foo::<T>` where only the final segment should have
4709     //    type parameters. However, in this case, those parameters are
4710     //    declared on a value, and hence are in the `FnSpace`.
4711     //
4712     // 3. Reference to a *method*:
4713     //
4714     //        impl<A> SomeStruct<A> {
4715     //            fn foo<B>(...)
4716     //        }
4717     //
4718     //    Here we can have a path like
4719     //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4720     //    may appear in two places. The penultimate segment,
4721     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4722     //    final segment, `foo::<B>` contains parameters in fn space.
4723     //
4724     // The first step then is to categorize the segments appropriately.
4725
4726     assert!(path.segments.len() >= 1);
4727     let mut segment_spaces: Vec<_>;
4728     match def {
4729         // Case 1 and 1b. Reference to a *type* or *enum variant*.
4730         def::DefSelfTy(..) |
4731         def::DefStruct(..) |
4732         def::DefVariant(..) |
4733         def::DefTyParamBinder(..) |
4734         def::DefTy(..) |
4735         def::DefAssociatedTy(..) |
4736         def::DefAssociatedPath(..) |
4737         def::DefTrait(..) |
4738         def::DefPrimTy(..) |
4739         def::DefTyParam(..) => {
4740             // Everything but the final segment should have no
4741             // parameters at all.
4742             segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4743             segment_spaces.push(Some(subst::TypeSpace));
4744         }
4745
4746         // Case 2. Reference to a top-level value.
4747         def::DefFn(..) |
4748         def::DefConst(..) |
4749         def::DefStatic(..) => {
4750             segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4751             segment_spaces.push(Some(subst::FnSpace));
4752         }
4753
4754         // Case 3. Reference to a method.
4755         def::DefStaticMethod(_, providence) |
4756         def::DefMethod(_, _, providence) => {
4757             assert!(path.segments.len() >= 2);
4758
4759             match providence {
4760                 def::FromTrait(trait_did) => {
4761                     callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4762                 }
4763                 def::FromImpl(_) => {}
4764             }
4765
4766             segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4767             segment_spaces.push(Some(subst::TypeSpace));
4768             segment_spaces.push(Some(subst::FnSpace));
4769         }
4770
4771         // Other cases. Various nonsense that really shouldn't show up
4772         // here. If they do, an error will have been reported
4773         // elsewhere. (I hope)
4774         def::DefMod(..) |
4775         def::DefForeignMod(..) |
4776         def::DefLocal(..) |
4777         def::DefUse(..) |
4778         def::DefRegion(..) |
4779         def::DefLabel(..) |
4780         def::DefUpvar(..) => {
4781             segment_spaces = repeat(None).take(path.segments.len()).collect();
4782         }
4783     }
4784     assert_eq!(segment_spaces.len(), path.segments.len());
4785
4786     debug!("segment_spaces={:?}", segment_spaces);
4787
4788     // Next, examine the definition, and determine how many type
4789     // parameters we expect from each space.
4790     let type_defs = &type_scheme.generics.types;
4791     let region_defs = &type_scheme.generics.regions;
4792
4793     // Now that we have categorized what space the parameters for each
4794     // segment belong to, let's sort out the parameters that the user
4795     // provided (if any) into their appropriate spaces. We'll also report
4796     // errors if type parameters are provided in an inappropriate place.
4797     let mut substs = Substs::empty();
4798     for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4799         match *opt_space {
4800             None => {
4801                 report_error_if_segment_contains_type_parameters(fcx, segment);
4802             }
4803
4804             Some(space) => {
4805                 push_explicit_parameters_from_segment_to_substs(fcx,
4806                                                                 space,
4807                                                                 path.span,
4808                                                                 type_defs,
4809                                                                 region_defs,
4810                                                                 segment,
4811                                                                 &mut substs);
4812             }
4813         }
4814     }
4815     if let Some(self_ty) = opt_self_ty {
4816         // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4817         assert_eq!(type_defs.len(subst::SelfSpace), 1);
4818         substs.types.push(subst::SelfSpace, self_ty);
4819     }
4820
4821     // Now we have to compare the types that the user *actually*
4822     // provided against the types that were *expected*. If the user
4823     // did not provide any types, then we want to substitute inference
4824     // variables. If the user provided some types, we may still need
4825     // to add defaults. If the user provided *too many* types, that's
4826     // a problem.
4827     for &space in &ParamSpace::all() {
4828         adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4829         assert_eq!(substs.types.len(space), type_defs.len(space));
4830
4831         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4832         assert_eq!(substs.regions().len(space), region_defs.len(space));
4833     }
4834
4835     // The things we are substituting into the type should not contain
4836     // escaping late-bound regions, and nor should the base type scheme.
4837     assert!(!substs.has_regions_escaping_depth(0));
4838     assert!(!type_scheme.has_escaping_regions());
4839
4840     // Add all the obligations that are required, substituting and
4841     // normalized appropriately.
4842     let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4843     fcx.add_obligations_for_parameters(
4844         traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4845         &bounds);
4846
4847     // Substitute the values for the type parameters into the type of
4848     // the referenced item.
4849     let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4850
4851     fcx.write_ty(node_id, ty_substituted);
4852     fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4853     return;
4854
4855     fn report_error_if_segment_contains_type_parameters(
4856         fcx: &FnCtxt,
4857         segment: &ast::PathSegment)
4858     {
4859         for typ in &segment.parameters.types() {
4860             span_err!(fcx.tcx().sess, typ.span, E0085,
4861                 "type parameters may not appear here");
4862             break;
4863         }
4864
4865         for lifetime in &segment.parameters.lifetimes() {
4866             span_err!(fcx.tcx().sess, lifetime.span, E0086,
4867                 "lifetime parameters may not appear here");
4868             break;
4869         }
4870     }
4871
4872     /// Finds the parameters that the user provided and adds them to `substs`. If too many
4873     /// parameters are provided, then reports an error and clears the output vector.
4874     ///
4875     /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4876     /// use inference variables. This seems less likely to lead to derived errors.
4877     ///
4878     /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4879     /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4880     /// here because we can easily use the precise span of the N+1'th parameter.
4881     fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4882         fcx: &FnCtxt<'a, 'tcx>,
4883         space: subst::ParamSpace,
4884         span: Span,
4885         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4886         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4887         segment: &ast::PathSegment,
4888         substs: &mut Substs<'tcx>)
4889     {
4890         match segment.parameters {
4891             ast::AngleBracketedParameters(ref data) => {
4892                 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4893                     fcx, space, type_defs, region_defs, data, substs);
4894             }
4895
4896             ast::ParenthesizedParameters(ref data) => {
4897                 span_err!(fcx.tcx().sess, span, E0238,
4898                     "parenthesized parameters may only be used with a trait");
4899                 push_explicit_parenthesized_parameters_from_segment_to_substs(
4900                     fcx, space, span, type_defs, data, substs);
4901             }
4902         }
4903     }
4904
4905     fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4906         fcx: &FnCtxt<'a, 'tcx>,
4907         space: subst::ParamSpace,
4908         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4909         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4910         data: &ast::AngleBracketedParameterData,
4911         substs: &mut Substs<'tcx>)
4912     {
4913         {
4914             let type_count = type_defs.len(space);
4915             assert_eq!(substs.types.len(space), 0);
4916             for (i, typ) in data.types.iter().enumerate() {
4917                 let t = fcx.to_ty(&**typ);
4918                 if i < type_count {
4919                     substs.types.push(space, t);
4920                 } else if i == type_count {
4921                     span_err!(fcx.tcx().sess, typ.span, E0087,
4922                         "too many type parameters provided: \
4923                          expected at most {} parameter(s), \
4924                          found {} parameter(s)",
4925                          type_count, data.types.len());
4926                     substs.types.truncate(space, 0);
4927                     break;
4928                 }
4929             }
4930         }
4931
4932         if data.bindings.len() > 0 {
4933             span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4934                       "unexpected binding of associated item in expression path \
4935                        (only allowed in type paths)");
4936         }
4937
4938         {
4939             let region_count = region_defs.len(space);
4940             assert_eq!(substs.regions().len(space), 0);
4941             for (i, lifetime) in data.lifetimes.iter().enumerate() {
4942                 let r = ast_region_to_region(fcx.tcx(), lifetime);
4943                 if i < region_count {
4944                     substs.mut_regions().push(space, r);
4945                 } else if i == region_count {
4946                     span_err!(fcx.tcx().sess, lifetime.span, E0088,
4947                         "too many lifetime parameters provided: \
4948                          expected {} parameter(s), found {} parameter(s)",
4949                         region_count,
4950                         data.lifetimes.len());
4951                     substs.mut_regions().truncate(space, 0);
4952                     break;
4953                 }
4954             }
4955         }
4956     }
4957
4958     /// As with
4959     /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4960     /// but intended for `Foo(A,B) -> C` form. This expands to
4961     /// roughly the same thing as `Foo<(A,B),C>`. One important
4962     /// difference has to do with the treatment of anonymous
4963     /// regions, which are translated into bound regions (NYI).
4964     fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4965         fcx: &FnCtxt<'a, 'tcx>,
4966         space: subst::ParamSpace,
4967         span: Span,
4968         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4969         data: &ast::ParenthesizedParameterData,
4970         substs: &mut Substs<'tcx>)
4971     {
4972         let type_count = type_defs.len(space);
4973         if type_count < 2 {
4974             span_err!(fcx.tcx().sess, span, E0167,
4975                       "parenthesized form always supplies 2 type parameters, \
4976                       but only {} parameter(s) were expected",
4977                       type_count);
4978         }
4979
4980         let input_tys: Vec<Ty> =
4981             data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4982
4983         let tuple_ty =
4984             ty::mk_tup(fcx.tcx(), input_tys);
4985
4986         if type_count >= 1 {
4987             substs.types.push(space, tuple_ty);
4988         }
4989
4990         let output_ty: Option<Ty> =
4991             data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4992
4993         let output_ty =
4994             output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4995
4996         if type_count >= 2 {
4997             substs.types.push(space, output_ty);
4998         }
4999     }
5000
5001     fn adjust_type_parameters<'a, 'tcx>(
5002         fcx: &FnCtxt<'a, 'tcx>,
5003         span: Span,
5004         space: ParamSpace,
5005         defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5006         substs: &mut Substs<'tcx>)
5007     {
5008         let provided_len = substs.types.len(space);
5009         let desired = defs.get_slice(space);
5010         let required_len = desired.iter()
5011                               .take_while(|d| d.default.is_none())
5012                               .count();
5013
5014         debug!("adjust_type_parameters(space={:?}, \
5015                provided_len={}, \
5016                desired_len={}, \
5017                required_len={})",
5018                space,
5019                provided_len,
5020                desired.len(),
5021                required_len);
5022
5023         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5024         assert!(provided_len <= desired.len());
5025
5026         // Nothing specified at all: supply inference variables for
5027         // everything.
5028         if provided_len == 0 {
5029             substs.types.replace(space,
5030                                  fcx.infcx().next_ty_vars(desired.len()));
5031             return;
5032         }
5033
5034         // Too few parameters specified: report an error and use Err
5035         // for everything.
5036         if provided_len < required_len {
5037             let qualifier =
5038                 if desired.len() != required_len { "at least " } else { "" };
5039             span_err!(fcx.tcx().sess, span, E0089,
5040                 "too few type parameters provided: expected {}{} parameter(s) \
5041                 , found {} parameter(s)",
5042                 qualifier, required_len, provided_len);
5043             substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5044             return;
5045         }
5046
5047         // Otherwise, add in any optional parameters that the user
5048         // omitted. The case of *too many* parameters is handled
5049         // already by
5050         // push_explicit_parameters_from_segment_to_substs(). Note
5051         // that the *default* type are expressed in terms of all prior
5052         // parameters, so we have to substitute as we go with the
5053         // partial substitution that we have built up.
5054         for i in provided_len..desired.len() {
5055             let default = desired[i].default.unwrap();
5056             let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5057             substs.types.push(space, default);
5058         }
5059         assert_eq!(substs.types.len(space), desired.len());
5060
5061         debug!("Final substs: {}", substs.repr(fcx.tcx()));
5062     }
5063
5064     fn adjust_region_parameters(
5065         fcx: &FnCtxt,
5066         span: Span,
5067         space: ParamSpace,
5068         defs: &VecPerParamSpace<ty::RegionParameterDef>,
5069         substs: &mut Substs)
5070     {
5071         let provided_len = substs.mut_regions().len(space);
5072         let desired = defs.get_slice(space);
5073
5074         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5075         assert!(provided_len <= desired.len());
5076
5077         // If nothing was provided, just use inference variables.
5078         if provided_len == 0 {
5079             substs.mut_regions().replace(
5080                 space,
5081                 fcx.infcx().region_vars_for_defs(span, desired));
5082             return;
5083         }
5084
5085         // If just the right number were provided, everybody is happy.
5086         if provided_len == desired.len() {
5087             return;
5088         }
5089
5090         // Otherwise, too few were provided. Report an error and then
5091         // use inference variables.
5092         span_err!(fcx.tcx().sess, span, E0090,
5093             "too few lifetime parameters provided: expected {} parameter(s), \
5094              found {} parameter(s)",
5095             desired.len(), provided_len);
5096
5097         substs.mut_regions().replace(
5098             space,
5099             fcx.infcx().region_vars_for_defs(span, desired));
5100     }
5101 }
5102
5103 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
5104                                                   sp: Span,
5105                                                   ty: Ty<'tcx>,
5106                                                   f: F) -> Ty<'tcx>
5107     where F: Fn() -> Ty<'tcx>
5108 {
5109     let mut ty = fcx.resolve_type_vars_if_possible(ty);
5110
5111     if ty::type_is_ty_var(ty) {
5112         let alternative = f();
5113
5114         // If not, error.
5115         if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
5116             fcx.type_error_message(sp, |_actual| {
5117                 "the type of this value must be known in this context".to_string()
5118             }, ty, None);
5119             demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5120             ty = fcx.tcx().types.err;
5121         } else {
5122             demand::suptype(fcx, sp, alternative, ty);
5123             ty = alternative;
5124         }
5125     }
5126
5127     ty
5128 }
5129
5130 // Resolves `typ` by a single level if `typ` is a type variable.  If no
5131 // resolution is possible, then an error is reported.
5132 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5133                                             sp: Span,
5134                                             ty: Ty<'tcx>)
5135                                             -> Ty<'tcx>
5136 {
5137     structurally_resolve_type_or_else(fcx, sp, ty, || {
5138         fcx.tcx().types.err
5139     })
5140 }
5141
5142 // Returns true if b contains a break that can exit from b
5143 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5144     // First: is there an unlabeled break immediately
5145     // inside the loop?
5146     (loop_query(&*b, |e| {
5147         match *e {
5148             ast::ExprBreak(_) => true,
5149             _ => false
5150         }
5151     })) ||
5152    // Second: is there a labeled break with label
5153    // <id> nested anywhere inside the loop?
5154     (block_query(b, |e| {
5155         match e.node {
5156             ast::ExprBreak(Some(_)) => {
5157                 match cx.def_map.borrow().get(&e.id) {
5158                     Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5159                     _ => false,
5160                 }
5161             }
5162             _ => false
5163         }}))
5164 }
5165
5166 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5167                                        span: Span,
5168                                        tps: &OwnedSlice<ast::TyParam>,
5169                                        ty: Ty<'tcx>) {
5170     debug!("check_bounds_are_used(n_tps={}, ty={})",
5171            tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5172
5173     // make a vector of booleans initially false, set to true when used
5174     if tps.len() == 0 { return; }
5175     let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5176
5177     ty::walk_ty(ty, |t| {
5178             match t.sty {
5179                 ty::ty_param(ParamTy {idx, ..}) => {
5180                     debug!("Found use of ty param num {}", idx);
5181                     tps_used[idx as uint] = true;
5182                 }
5183                 _ => ()
5184             }
5185         });
5186
5187     for (i, b) in tps_used.iter().enumerate() {
5188         if !*b {
5189             span_err!(ccx.tcx.sess, span, E0091,
5190                 "type parameter `{}` is unused",
5191                 token::get_ident(tps[i].ident));
5192         }
5193     }
5194 }
5195
5196 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5197     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5198         let name = token::intern(&format!("P{}", n));
5199         ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5200     }
5201
5202     let tcx = ccx.tcx;
5203     let name = token::get_ident(it.ident);
5204     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5205         let split : Vec<&str> = name.split('_').collect();
5206         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5207
5208         //We only care about the operation here
5209         let (n_tps, inputs, output) = match split[1] {
5210             "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5211                                 param(ccx, 0),
5212                                 param(ccx, 0)),
5213                         param(ccx, 0)),
5214             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5215                        param(ccx, 0)),
5216             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5217                         ty::mk_nil(tcx)),
5218
5219             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
5220             "min"  | "umax" | "umin" => {
5221                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5222                  param(ccx, 0))
5223             }
5224             "fence" => {
5225                 (0, Vec::new(), ty::mk_nil(tcx))
5226             }
5227             op => {
5228                 span_err!(tcx.sess, it.span, E0092,
5229                     "unrecognized atomic operation function: `{}`", op);
5230                 return;
5231             }
5232         };
5233         (n_tps, inputs, ty::FnConverging(output))
5234     } else if &name[..] == "abort" || &name[..] == "unreachable" {
5235         (0, Vec::new(), ty::FnDiverging)
5236     } else {
5237         let (n_tps, inputs, output) = match &name[..] {
5238             "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5239             "size_of" |
5240             "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.uint),
5241             "init" => (1, Vec::new(), param(ccx, 0)),
5242             "uninit" => (1, Vec::new(), param(ccx, 0)),
5243             "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5244             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5245             "move_val_init" => {
5246                 (1,
5247                  vec!(
5248                     ty::mk_mut_rptr(tcx,
5249                                     tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5250                                                                   ty::BrAnon(0))),
5251                                     param(ccx, 0)),
5252                     param(ccx, 0)
5253                   ),
5254                ty::mk_nil(tcx))
5255             }
5256             "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5257             "owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
5258
5259             "get_tydesc" => {
5260               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5261                   Ok(t) => t,
5262                   Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); }
5263               };
5264               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5265                   ty: tydesc_ty,
5266                   mutbl: ast::MutImmutable
5267               });
5268               (1, Vec::new(), td_ptr)
5269             }
5270             "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5271             "offset" => {
5272               (1,
5273                vec!(
5274                   ty::mk_ptr(tcx, ty::mt {
5275                       ty: param(ccx, 0),
5276                       mutbl: ast::MutImmutable
5277                   }),
5278                   ccx.tcx.types.int
5279                ),
5280                ty::mk_ptr(tcx, ty::mt {
5281                    ty: param(ccx, 0),
5282                    mutbl: ast::MutImmutable
5283                }))
5284             }
5285             "copy_memory" | "copy_nonoverlapping_memory" |
5286             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5287               (1,
5288                vec!(
5289                   ty::mk_ptr(tcx, ty::mt {
5290                       ty: param(ccx, 0),
5291                       mutbl: ast::MutMutable
5292                   }),
5293                   ty::mk_ptr(tcx, ty::mt {
5294                       ty: param(ccx, 0),
5295                       mutbl: ast::MutImmutable
5296                   }),
5297                   tcx.types.uint,
5298                ),
5299                ty::mk_nil(tcx))
5300             }
5301             "set_memory" | "volatile_set_memory" => {
5302               (1,
5303                vec!(
5304                   ty::mk_ptr(tcx, ty::mt {
5305                       ty: param(ccx, 0),
5306                       mutbl: ast::MutMutable
5307                   }),
5308                   tcx.types.u8,
5309                   tcx.types.uint,
5310                ),
5311                ty::mk_nil(tcx))
5312             }
5313             "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5314             "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5315             "powif32" => {
5316                (0,
5317                 vec!( tcx.types.f32, tcx.types.i32 ),
5318                 tcx.types.f32)
5319             }
5320             "powif64" => {
5321                (0,
5322                 vec!( tcx.types.f64, tcx.types.i32 ),
5323                 tcx.types.f64)
5324             }
5325             "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5326             "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5327             "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5328             "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5329             "powf32" => {
5330                (0,
5331                 vec!( tcx.types.f32, tcx.types.f32 ),
5332                 tcx.types.f32)
5333             }
5334             "powf64" => {
5335                (0,
5336                 vec!( tcx.types.f64, tcx.types.f64 ),
5337                 tcx.types.f64)
5338             }
5339             "expf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5340             "expf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5341             "exp2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5342             "exp2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5343             "logf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5344             "logf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5345             "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5346             "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5347             "log2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5348             "log2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5349             "fmaf32" => {
5350                 (0,
5351                  vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5352                  tcx.types.f32)
5353             }
5354             "fmaf64" => {
5355                 (0,
5356                  vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5357                  tcx.types.f64)
5358             }
5359             "fabsf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5360             "fabsf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5361             "copysignf32"  => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5362             "copysignf64"  => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5363             "floorf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5364             "floorf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5365             "ceilf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5366             "ceilf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5367             "truncf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5368             "truncf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5369             "rintf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5370             "rintf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5371             "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5372             "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5373             "roundf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5374             "roundf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5375             "ctpop8"       => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5376             "ctpop16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5377             "ctpop32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5378             "ctpop64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5379             "ctlz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5380             "ctlz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5381             "ctlz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5382             "ctlz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5383             "cttz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5384             "cttz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5385             "cttz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5386             "cttz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5387             "bswap16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5388             "bswap32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5389             "bswap64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5390
5391             "volatile_load" =>
5392                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5393             "volatile_store" =>
5394                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5395
5396             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5397                 (0, vec!(tcx.types.i8, tcx.types.i8),
5398                 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5399
5400             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5401                 (0, vec!(tcx.types.i16, tcx.types.i16),
5402                 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5403
5404             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5405                 (0, vec!(tcx.types.i32, tcx.types.i32),
5406                 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5407
5408             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5409                 (0, vec!(tcx.types.i64, tcx.types.i64),
5410                 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5411
5412             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5413                 (0, vec!(tcx.types.u8, tcx.types.u8),
5414                 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5415
5416             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5417                 (0, vec!(tcx.types.u16, tcx.types.u16),
5418                 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5419
5420             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5421                 (0, vec!(tcx.types.u32, tcx.types.u32),
5422                 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5423
5424             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
5425                 (0, vec!(tcx.types.u64, tcx.types.u64),
5426                 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5427
5428             "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5429
5430             "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5431
5432             ref other => {
5433                 span_err!(tcx.sess, it.span, E0093,
5434                     "unrecognized intrinsic function: `{}`", *other);
5435                 return;
5436             }
5437         };
5438         (n_tps, inputs, ty::FnConverging(output))
5439     };
5440     let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5441         unsafety: ast::Unsafety::Unsafe,
5442         abi: abi::RustIntrinsic,
5443         sig: ty::Binder(FnSig {
5444             inputs: inputs,
5445             output: output,
5446             variadic: false,
5447         }),
5448     }));
5449     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5450     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5451     if i_n_tps != n_tps {
5452         span_err!(tcx.sess, it.span, E0094,
5453             "intrinsic has wrong number of type \
5454              parameters: found {}, expected {}",
5455              i_n_tps, n_tps);
5456     } else {
5457         require_same_types(tcx,
5458                            None,
5459                            false,
5460                            it.span,
5461                            i_ty.ty,
5462                            fty,
5463                            || {
5464                 format!("intrinsic has wrong type: expected `{}`",
5465                         ppaux::ty_to_string(ccx.tcx, fty))
5466             });
5467     }
5468 }