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