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