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