]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/mod.rs
rollup merge of #21191: Zoxc/lto
[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
1601         self.inh.fulfillment_cx
1602             .borrow_mut()
1603             .register_predicate_obligation(self.infcx(), obligation);
1604     }
1605
1606     pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1607         let t = ast_ty_to_ty(self, self, ast_t);
1608
1609         let mut bounds_checker = wf::BoundsChecker::new(self,
1610                                                         ast_t.span,
1611                                                         CodeExtent::from_node_id(self.body_id),
1612                                                         None);
1613         bounds_checker.check_ty(t);
1614
1615         t
1616     }
1617
1618     pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1619         pat.repr(self.tcx())
1620     }
1621
1622     pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1623         match self.inh.node_types.borrow().get(&ex.id) {
1624             Some(&t) => t,
1625             None => {
1626                 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1627                                             self.tag())[]);
1628             }
1629         }
1630     }
1631
1632     /// Apply `adjustment` to the type of `expr`
1633     pub fn adjust_expr_ty(&self,
1634                           expr: &ast::Expr,
1635                           adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1636                           -> Ty<'tcx>
1637     {
1638         let raw_ty = self.expr_ty(expr);
1639         let raw_ty = self.infcx().shallow_resolve(raw_ty);
1640         ty::adjust_ty(self.tcx(),
1641                       expr.span,
1642                       expr.id,
1643                       raw_ty,
1644                       adjustment,
1645                       |method_call| self.inh.method_map.borrow()
1646                                                        .get(&method_call)
1647                                                        .map(|method| method.ty))
1648     }
1649
1650     pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1651         match self.inh.node_types.borrow().get(&id) {
1652             Some(&t) => t,
1653             None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1654             None => {
1655                 self.tcx().sess.bug(
1656                     &format!("no type for node {}: {} in fcx {}",
1657                             id, self.tcx().map.node_to_string(id),
1658                             self.tag())[]);
1659             }
1660         }
1661     }
1662
1663     pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1664         self.inh.item_substs.borrow()
1665     }
1666
1667     pub fn opt_node_ty_substs<F>(&self,
1668                                  id: ast::NodeId,
1669                                  f: F) where
1670         F: FnOnce(&ty::ItemSubsts<'tcx>),
1671     {
1672         match self.inh.item_substs.borrow().get(&id) {
1673             Some(s) => { f(s) }
1674             None => { }
1675         }
1676     }
1677
1678     pub fn mk_subty(&self,
1679                     a_is_expected: bool,
1680                     origin: infer::TypeOrigin,
1681                     sub: Ty<'tcx>,
1682                     sup: Ty<'tcx>)
1683                     -> Result<(), ty::type_err<'tcx>> {
1684         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1685     }
1686
1687     pub fn mk_assignty(&self,
1688                        expr: &ast::Expr,
1689                        sub: Ty<'tcx>,
1690                        sup: Ty<'tcx>)
1691                        -> Result<(), ty::type_err<'tcx>> {
1692         match infer::mk_coercety(self.infcx(),
1693                                  false,
1694                                  infer::ExprAssignable(expr.span),
1695                                  sub,
1696                                  sup) {
1697             Ok(None) => Ok(()),
1698             Err(ref e) => Err((*e)),
1699             Ok(Some(adjustment)) => {
1700                 self.write_adjustment(expr.id, expr.span, adjustment);
1701                 Ok(())
1702             }
1703         }
1704     }
1705
1706     pub fn mk_eqty(&self,
1707                    a_is_expected: bool,
1708                    origin: infer::TypeOrigin,
1709                    sub: Ty<'tcx>,
1710                    sup: Ty<'tcx>)
1711                    -> Result<(), ty::type_err<'tcx>> {
1712         infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1713     }
1714
1715     pub fn mk_subr(&self,
1716                    origin: infer::SubregionOrigin<'tcx>,
1717                    sub: ty::Region,
1718                    sup: ty::Region) {
1719         infer::mk_subr(self.infcx(), origin, sub, sup)
1720     }
1721
1722     pub fn type_error_message<M>(&self,
1723                                  sp: Span,
1724                                  mk_msg: M,
1725                                  actual_ty: Ty<'tcx>,
1726                                  err: Option<&ty::type_err<'tcx>>) where
1727         M: FnOnce(String) -> String,
1728     {
1729         self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1730     }
1731
1732     pub fn report_mismatched_types(&self,
1733                                    sp: Span,
1734                                    e: Ty<'tcx>,
1735                                    a: Ty<'tcx>,
1736                                    err: &ty::type_err<'tcx>) {
1737         self.infcx().report_mismatched_types(sp, e, a, err)
1738     }
1739
1740     /// Registers an obligation for checking later, during regionck, that the type `ty` must
1741     /// outlive the region `r`.
1742     pub fn register_region_obligation(&self,
1743                                       ty: Ty<'tcx>,
1744                                       region: ty::Region,
1745                                       cause: traits::ObligationCause<'tcx>)
1746     {
1747         let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1748         fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1749     }
1750
1751     pub fn add_default_region_param_bounds(&self,
1752                                            substs: &Substs<'tcx>,
1753                                            expr: &ast::Expr)
1754     {
1755         for &ty in substs.types.iter() {
1756             let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1757             let cause = traits::ObligationCause::new(expr.span, self.body_id,
1758                                                      traits::MiscObligation);
1759             self.register_region_obligation(ty, default_bound, cause);
1760         }
1761     }
1762
1763     /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1764     /// type/region parameter was instantiated (`substs`), creates and registers suitable
1765     /// trait/region obligations.
1766     ///
1767     /// For example, if there is a function:
1768     ///
1769     /// ```
1770     /// fn foo<'a,T:'a>(...)
1771     /// ```
1772     ///
1773     /// and a reference:
1774     ///
1775     /// ```
1776     /// let f = foo;
1777     /// ```
1778     ///
1779     /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1780     /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1781     pub fn add_obligations_for_parameters(&self,
1782                                           cause: traits::ObligationCause<'tcx>,
1783                                           generic_bounds: &ty::GenericBounds<'tcx>)
1784     {
1785         assert!(!generic_bounds.has_escaping_regions());
1786
1787         debug!("add_obligations_for_parameters(generic_bounds={})",
1788                generic_bounds.repr(self.tcx()));
1789
1790         let obligations = traits::predicates_for_generics(self.tcx(),
1791                                                           cause,
1792                                                           generic_bounds);
1793
1794         obligations.map_move(|o| self.register_predicate(o));
1795     }
1796
1797     // Only for fields! Returns <none> for methods>
1798     // Indifferent to privacy flags
1799     pub fn lookup_field_ty(&self,
1800                            span: Span,
1801                            class_id: ast::DefId,
1802                            items: &[ty::field_ty],
1803                            fieldname: ast::Name,
1804                            substs: &subst::Substs<'tcx>)
1805                            -> Option<Ty<'tcx>>
1806     {
1807         let o_field = items.iter().find(|f| f.name == fieldname);
1808         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1809                .map(|t| self.normalize_associated_types_in(span, &t))
1810     }
1811
1812     pub fn lookup_tup_field_ty(&self,
1813                                span: Span,
1814                                class_id: ast::DefId,
1815                                items: &[ty::field_ty],
1816                                idx: uint,
1817                                substs: &subst::Substs<'tcx>)
1818                                -> Option<Ty<'tcx>>
1819     {
1820         let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1821         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1822                .map(|t| self.normalize_associated_types_in(span, &t))
1823     }
1824 }
1825
1826 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1827     fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1828         Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1829     }
1830
1831     fn anon_regions(&self, span: Span, count: uint)
1832                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1833         Ok(range(0, count).map(|_| {
1834             self.infcx().next_region_var(infer::MiscVariable(span))
1835         }).collect())
1836     }
1837 }
1838
1839 #[derive(Copy, Show, PartialEq, Eq)]
1840 pub enum LvaluePreference {
1841     PreferMutLvalue,
1842     NoPreference
1843 }
1844
1845 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1846 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1847 ///
1848 /// Note: this method does not modify the adjustments table. The caller is responsible for
1849 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1850 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1851                                  sp: Span,
1852                                  base_ty: Ty<'tcx>,
1853                                  opt_expr: Option<&ast::Expr>,
1854                                  mut lvalue_pref: LvaluePreference,
1855                                  mut should_stop: F)
1856                                  -> (Ty<'tcx>, uint, Option<T>)
1857     where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1858 {
1859     debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1860            base_ty.repr(fcx.tcx()),
1861            opt_expr.repr(fcx.tcx()),
1862            lvalue_pref);
1863
1864     let mut t = base_ty;
1865     for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1866         let resolved_t = structurally_resolved_type(fcx, sp, t);
1867
1868         if ty::type_is_error(resolved_t) {
1869             return (resolved_t, autoderefs, None);
1870         }
1871
1872         match should_stop(resolved_t, autoderefs) {
1873             Some(x) => return (resolved_t, autoderefs, Some(x)),
1874             None => {}
1875         }
1876
1877         // Otherwise, deref if type is derefable:
1878         let mt = match ty::deref(resolved_t, false) {
1879             Some(mt) => Some(mt),
1880             None => {
1881                 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1882
1883                 // Super subtle: it might seem as though we should
1884                 // pass `opt_expr` to `try_overloaded_deref`, so that
1885                 // the (implicit) autoref of using an overloaded deref
1886                 // would get added to the adjustment table. However we
1887                 // do not do that, because it's kind of a
1888                 // "meta-adjustment" -- instead, we just leave it
1889                 // unrecorded and know that there "will be" an
1890                 // autoref. regionck and other bits of the code base,
1891                 // when they encounter an overloaded autoderef, have
1892                 // to do some reconstructive surgery. This is a pretty
1893                 // complex mess that is begging for a proper MIR.
1894                 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1895             }
1896         };
1897         match mt {
1898             Some(mt) => {
1899                 t = mt.ty;
1900                 if mt.mutbl == ast::MutImmutable {
1901                     lvalue_pref = NoPreference;
1902                 }
1903             }
1904             None => return (resolved_t, autoderefs, None)
1905         }
1906     }
1907
1908     // We've reached the recursion limit, error gracefully.
1909     span_err!(fcx.tcx().sess, sp, E0055,
1910         "reached the recursion limit while auto-dereferencing {}",
1911         base_ty.repr(fcx.tcx()));
1912     (fcx.tcx().types.err, 0, None)
1913 }
1914
1915 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1916                                   span: Span,
1917                                   method_call: Option<MethodCall>,
1918                                   base_expr: Option<&ast::Expr>,
1919                                   base_ty: Ty<'tcx>,
1920                                   lvalue_pref: LvaluePreference)
1921                                   -> Option<ty::mt<'tcx>>
1922 {
1923     // Try DerefMut first, if preferred.
1924     let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1925         (PreferMutLvalue, Some(trait_did)) => {
1926             method::lookup_in_trait(fcx, span, base_expr,
1927                                     token::intern("deref_mut"), trait_did,
1928                                     base_ty, None)
1929         }
1930         _ => None
1931     };
1932
1933     // Otherwise, fall back to Deref.
1934     let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1935         (None, Some(trait_did)) => {
1936             method::lookup_in_trait(fcx, span, base_expr,
1937                                     token::intern("deref"), trait_did,
1938                                     base_ty, None)
1939         }
1940         (method, _) => method
1941     };
1942
1943     make_overloaded_lvalue_return_type(fcx, method_call, method)
1944 }
1945
1946 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
1947 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
1948 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
1949 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1950                                                 method_call: Option<MethodCall>,
1951                                                 method: Option<MethodCallee<'tcx>>)
1952                                                 -> Option<ty::mt<'tcx>>
1953 {
1954     match method {
1955         Some(method) => {
1956             let ref_ty = // invoked methods have all LB regions instantiated
1957                 ty::assert_no_late_bound_regions(
1958                     fcx.tcx(), &ty::ty_fn_ret(method.ty));
1959             match method_call {
1960                 Some(method_call) => {
1961                     fcx.inh.method_map.borrow_mut().insert(method_call,
1962                                                            method);
1963                 }
1964                 None => {}
1965             }
1966             match ref_ty {
1967                 ty::FnConverging(ref_ty) => {
1968                     ty::deref(ref_ty, true)
1969                 }
1970                 ty::FnDiverging => {
1971                     fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
1972                 }
1973             }
1974         }
1975         None => None,
1976     }
1977 }
1978
1979 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1980                                        base_expr: &ast::Expr,
1981                                        base_ty: Ty<'tcx>,
1982                                        lvalue_pref: LvaluePreference,
1983                                        mut step: F)
1984                                        -> Option<T> where
1985     F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
1986 {
1987     // FIXME(#18741) -- this is almost but not quite the same as the
1988     // autoderef that normal method probing does. They could likely be
1989     // consolidated.
1990
1991     let (ty, autoderefs, final_mt) =
1992         autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
1993             let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
1994             step(adj_ty, autoderefref)
1995         });
1996
1997     if final_mt.is_some() {
1998         return final_mt;
1999     }
2000
2001     // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2002     // do a final unsized coercion to yield [T].
2003     match ty.sty {
2004         ty::ty_vec(element_ty, Some(n)) => {
2005             let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2006             let autoderefref = ty::AutoDerefRef {
2007                 autoderefs: autoderefs,
2008                 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2009             };
2010             step(adjusted_ty, autoderefref)
2011         }
2012         _ => {
2013             None
2014         }
2015     }
2016 }
2017
2018 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2019 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2020 /// This loop implements one step in that search; the autoderef loop is implemented by
2021 /// `autoderef_for_index`.
2022 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2023                             method_call: MethodCall,
2024                             expr: &ast::Expr,
2025                             base_expr: &ast::Expr,
2026                             adjusted_ty: Ty<'tcx>,
2027                             adjustment: ty::AutoDerefRef<'tcx>,
2028                             lvalue_pref: LvaluePreference,
2029                             index_ty: Ty<'tcx>)
2030                             -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2031 {
2032     let tcx = fcx.tcx();
2033     debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2034            expr.repr(tcx),
2035            base_expr.repr(tcx),
2036            adjusted_ty.repr(tcx),
2037            adjustment,
2038            index_ty.repr(tcx));
2039
2040     let input_ty = fcx.infcx().next_ty_var();
2041
2042     // First, try built-in indexing.
2043     match (ty::index(adjusted_ty), &index_ty.sty) {
2044         (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2045             debug!("try_index_step: success, using built-in indexing");
2046             fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2047             return Some((tcx.types.uint, ty));
2048         }
2049         _ => {}
2050     }
2051
2052     // Try `IndexMut` first, if preferred.
2053     let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2054         (PreferMutLvalue, Some(trait_did)) => {
2055             method::lookup_in_trait_adjusted(fcx,
2056                                              expr.span,
2057                                              Some(&*base_expr),
2058                                              token::intern("index_mut"),
2059                                              trait_did,
2060                                              adjustment.clone(),
2061                                              adjusted_ty,
2062                                              Some(vec![input_ty]))
2063         }
2064         _ => None,
2065     };
2066
2067     // Otherwise, fall back to `Index`.
2068     let method = match (method, tcx.lang_items.index_trait()) {
2069         (None, Some(trait_did)) => {
2070             method::lookup_in_trait_adjusted(fcx,
2071                                              expr.span,
2072                                              Some(&*base_expr),
2073                                              token::intern("index"),
2074                                              trait_did,
2075                                              adjustment.clone(),
2076                                              adjusted_ty,
2077                                              Some(vec![input_ty]))
2078         }
2079         (method, _) => method,
2080     };
2081
2082     // If some lookup succeeds, write callee into table and extract index/element
2083     // type from the method signature.
2084     // If some lookup succeeded, install method in table
2085     method.and_then(|method| {
2086         debug!("try_index_step: success, using overloaded indexing");
2087         make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2088             map(|ret| (input_ty, ret.ty))
2089     })
2090 }
2091
2092 /// Given the head of a `for` expression, looks up the `next` method in the
2093 /// `Iterator` trait. Panics if the expression does not implement `next`.
2094 ///
2095 /// The return type of this function represents the concrete element type
2096 /// `A` in the type `Iterator<A>` that the method returns.
2097 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2098                                         iterator_expr: &ast::Expr,
2099                                         loop_id: ast::NodeId)
2100                                         -> Ty<'tcx> {
2101     let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2102         Ok(trait_did) => trait_did,
2103         Err(ref err_string) => {
2104             fcx.tcx().sess.span_err(iterator_expr.span,
2105                                     &err_string[]);
2106             return fcx.tcx().types.err
2107         }
2108     };
2109
2110     let expr_type = fcx.expr_ty(&*iterator_expr);
2111     let method = method::lookup_in_trait(fcx,
2112                                          iterator_expr.span,
2113                                          Some(&*iterator_expr),
2114                                          token::intern("next"),
2115                                          trait_did,
2116                                          expr_type,
2117                                          None);
2118
2119     // Regardless of whether the lookup succeeds, check the method arguments
2120     // so that we have *some* type for each argument.
2121     let method_type = match method {
2122         Some(ref method) => method.ty,
2123         None => {
2124             let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2125
2126             if !ty::type_is_error(true_expr_type) {
2127                 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2128                 fcx.tcx().sess.span_err(iterator_expr.span,
2129                                         &format!("`for` loop expression has type `{}` which does \
2130                                                 not implement the `Iterator` trait; \
2131                                                 maybe try .iter()",
2132                                                 ty_string)[]);
2133             }
2134             fcx.tcx().types.err
2135         }
2136     };
2137     let return_type = check_method_argument_types(fcx,
2138                                                   iterator_expr.span,
2139                                                   method_type,
2140                                                   iterator_expr,
2141                                                   &[],
2142                                                   AutorefArgs::No,
2143                                                   DontTupleArguments,
2144                                                   NoExpectation);
2145
2146     match method {
2147         Some(method) => {
2148             fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2149                                                    method);
2150
2151             // We expect the return type to be `Option` or something like it.
2152             // Grab the first parameter of its type substitution.
2153             let return_type = match return_type {
2154                 ty::FnConverging(return_type) =>
2155                     structurally_resolved_type(fcx, iterator_expr.span, return_type),
2156                 ty::FnDiverging => fcx.tcx().types.err
2157             };
2158             match return_type.sty {
2159                 ty::ty_enum(_, ref substs)
2160                         if !substs.types.is_empty_in(subst::TypeSpace) => {
2161                     *substs.types.get(subst::TypeSpace, 0)
2162                 }
2163                 ty::ty_err => {
2164                     fcx.tcx().types.err
2165                 }
2166                 _ => {
2167                     fcx.tcx().sess.span_err(iterator_expr.span,
2168                                             &format!("`next` method of the `Iterator` \
2169                                                     trait has an unexpected type `{}`",
2170                                                     fcx.infcx().ty_to_string(return_type))
2171                                             []);
2172                     fcx.tcx().types.err
2173                 }
2174             }
2175         }
2176         None => fcx.tcx().types.err
2177     }
2178 }
2179
2180 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2181                                          sp: Span,
2182                                          method_fn_ty: Ty<'tcx>,
2183                                          callee_expr: &ast::Expr,
2184                                          args_no_rcvr: &[P<ast::Expr>],
2185                                          autoref_args: AutorefArgs,
2186                                          tuple_arguments: TupleArgumentsFlag,
2187                                          expected: Expectation<'tcx>)
2188                                          -> ty::FnOutput<'tcx> {
2189     if ty::type_is_error(method_fn_ty) {
2190         let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2191
2192         let err_inputs = match tuple_arguments {
2193             DontTupleArguments => err_inputs,
2194             TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2195         };
2196
2197         check_argument_types(fcx,
2198                              sp,
2199                              &err_inputs[],
2200                              &[],
2201                              args_no_rcvr,
2202                              autoref_args,
2203                              false,
2204                              tuple_arguments);
2205         ty::FnConverging(fcx.tcx().types.err)
2206     } else {
2207         match method_fn_ty.sty {
2208             ty::ty_bare_fn(_, ref fty) => {
2209                 // HACK(eddyb) ignore self in the definition (see above).
2210                 let expected_arg_tys = expected_types_for_fn_args(fcx,
2211                                                                   sp,
2212                                                                   expected,
2213                                                                   fty.sig.0.output,
2214                                                                   &fty.sig.0.inputs[1..]);
2215                 check_argument_types(fcx,
2216                                      sp,
2217                                      &fty.sig.0.inputs[1..],
2218                                      &expected_arg_tys[],
2219                                      args_no_rcvr,
2220                                      autoref_args,
2221                                      fty.sig.0.variadic,
2222                                      tuple_arguments);
2223                 fty.sig.0.output
2224             }
2225             _ => {
2226                 fcx.tcx().sess.span_bug(callee_expr.span,
2227                                         "method without bare fn type");
2228             }
2229         }
2230     }
2231 }
2232
2233 /// Generic function that factors out common logic from function calls, method calls and overloaded
2234 /// operators.
2235 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2236                                   sp: Span,
2237                                   fn_inputs: &[Ty<'tcx>],
2238                                   expected_arg_tys: &[Ty<'tcx>],
2239                                   args: &[P<ast::Expr>],
2240                                   autoref_args: AutorefArgs,
2241                                   variadic: bool,
2242                                   tuple_arguments: TupleArgumentsFlag) {
2243     let tcx = fcx.ccx.tcx;
2244
2245     // Grab the argument types, supplying fresh type variables
2246     // if the wrong number of arguments were supplied
2247     let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2248         args.len()
2249     } else {
2250         1
2251     };
2252
2253     let mut expected_arg_tys = expected_arg_tys;
2254     let expected_arg_count = fn_inputs.len();
2255     let formal_tys = if tuple_arguments == TupleArguments {
2256         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2257         match tuple_type.sty {
2258             ty::ty_tup(ref arg_types) => {
2259                 if arg_types.len() != args.len() {
2260                     span_err!(tcx.sess, sp, E0057,
2261                         "this function takes {} parameter{} but {} parameter{} supplied",
2262                         arg_types.len(),
2263                         if arg_types.len() == 1 {""} else {"s"},
2264                         args.len(),
2265                         if args.len() == 1 {" was"} else {"s were"});
2266                     expected_arg_tys = &[][];
2267                     err_args(fcx.tcx(), args.len())
2268                 } else {
2269                     expected_arg_tys = match expected_arg_tys.get(0) {
2270                         Some(&ty) => match ty.sty {
2271                             ty::ty_tup(ref tys) => &**tys,
2272                             _ => &[]
2273                         },
2274                         None => &[]
2275                     };
2276                     (*arg_types).clone()
2277                 }
2278             }
2279             _ => {
2280                 span_err!(tcx.sess, sp, E0059,
2281                     "cannot use call notation; the first type parameter \
2282                      for the function trait is neither a tuple nor unit");
2283                 expected_arg_tys = &[][];
2284                 err_args(fcx.tcx(), args.len())
2285             }
2286         }
2287     } else if expected_arg_count == supplied_arg_count {
2288         fn_inputs.to_vec()
2289     } else if variadic {
2290         if supplied_arg_count >= expected_arg_count {
2291             fn_inputs.to_vec()
2292         } else {
2293             span_err!(tcx.sess, sp, E0060,
2294                 "this function takes at least {} parameter{} \
2295                  but {} parameter{} supplied",
2296                 expected_arg_count,
2297                 if expected_arg_count == 1 {""} else {"s"},
2298                 supplied_arg_count,
2299                 if supplied_arg_count == 1 {" was"} else {"s were"});
2300             expected_arg_tys = &[][];
2301             err_args(fcx.tcx(), supplied_arg_count)
2302         }
2303     } else {
2304         span_err!(tcx.sess, sp, E0061,
2305             "this function takes {} parameter{} but {} parameter{} supplied",
2306             expected_arg_count,
2307             if expected_arg_count == 1 {""} else {"s"},
2308             supplied_arg_count,
2309             if supplied_arg_count == 1 {" was"} else {"s were"});
2310         expected_arg_tys = &[][];
2311         err_args(fcx.tcx(), supplied_arg_count)
2312     };
2313
2314     debug!("check_argument_types: formal_tys={:?}",
2315            formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2316
2317     // Check the arguments.
2318     // We do this in a pretty awful way: first we typecheck any arguments
2319     // that are not anonymous functions, then we typecheck the anonymous
2320     // functions. This is so that we have more information about the types
2321     // of arguments when we typecheck the functions. This isn't really the
2322     // right way to do this.
2323     let xs = [false, true];
2324     for check_blocks in xs.iter() {
2325         let check_blocks = *check_blocks;
2326         debug!("check_blocks={}", check_blocks);
2327
2328         // More awful hacks: before we check the blocks, try to do
2329         // an "opportunistic" vtable resolution of any trait
2330         // bounds on the call.
2331         if check_blocks {
2332             vtable::select_new_fcx_obligations(fcx);
2333         }
2334
2335         // For variadic functions, we don't have a declared type for all of
2336         // the arguments hence we only do our usual type checking with
2337         // the arguments who's types we do know.
2338         let t = if variadic {
2339             expected_arg_count
2340         } else if tuple_arguments == TupleArguments {
2341             args.len()
2342         } else {
2343             supplied_arg_count
2344         };
2345         for (i, arg) in args.iter().take(t).enumerate() {
2346             let is_block = match arg.node {
2347                 ast::ExprClosure(..) => true,
2348                 _ => false
2349             };
2350
2351             if is_block == check_blocks {
2352                 debug!("checking the argument");
2353                 let mut formal_ty = formal_tys[i];
2354
2355                 match autoref_args {
2356                     AutorefArgs::Yes => {
2357                         match formal_ty.sty {
2358                             ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2359                             ty::ty_err => (),
2360                             _ => {
2361                                 // So we hit this case when one implements the
2362                                 // operator traits but leaves an argument as
2363                                 // just T instead of &T. We'll catch it in the
2364                                 // mismatch impl/trait method phase no need to
2365                                 // ICE here.
2366                                 // See: #11450
2367                                 formal_ty = tcx.types.err;
2368                             }
2369                         }
2370                     }
2371                     AutorefArgs::No => {}
2372                 }
2373
2374                 // The special-cased logic below has three functions:
2375                 // 1. Provide as good of an expected type as possible.
2376                 let expected = expected_arg_tys.get(i).map(|&ty| {
2377                     Expectation::rvalue_hint(ty)
2378                 });
2379
2380                 check_expr_with_unifier(fcx, &**arg,
2381                                         expected.unwrap_or(ExpectHasType(formal_ty)),
2382                                         NoPreference, || {
2383                     // 2. Coerce to the most detailed type that could be coerced
2384                     //    to, which is `expected_ty` if `rvalue_hint` returns an
2385                     //    `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2386                     let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2387                     demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2388
2389                     // 3. Relate the expected type and the formal one,
2390                     //    if the expected type was used for the coercion.
2391                     coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2392                 });
2393             }
2394         }
2395     }
2396
2397     // We also need to make sure we at least write the ty of the other
2398     // arguments which we skipped above.
2399     if variadic {
2400         for arg in args.iter().skip(expected_arg_count) {
2401             check_expr(fcx, &**arg);
2402
2403             // There are a few types which get autopromoted when passed via varargs
2404             // in C but we just error out instead and require explicit casts.
2405             let arg_ty = structurally_resolved_type(fcx, arg.span,
2406                                                     fcx.expr_ty(&**arg));
2407             match arg_ty.sty {
2408                 ty::ty_float(ast::TyF32) => {
2409                     fcx.type_error_message(arg.span,
2410                                            |t| {
2411                         format!("can't pass an {} to variadic \
2412                                  function, cast to c_double", t)
2413                     }, arg_ty, None);
2414                 }
2415                 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2416                     fcx.type_error_message(arg.span, |t| {
2417                         format!("can't pass {} to variadic \
2418                                  function, cast to c_int",
2419                                        t)
2420                     }, arg_ty, None);
2421                 }
2422                 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2423                     fcx.type_error_message(arg.span, |t| {
2424                         format!("can't pass {} to variadic \
2425                                  function, cast to c_uint",
2426                                        t)
2427                     }, arg_ty, None);
2428                 }
2429                 _ => {}
2430             }
2431         }
2432     }
2433 }
2434
2435 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2436 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2437     range(0, len).map(|_| tcx.types.err).collect()
2438 }
2439
2440 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2441                         call_expr: &ast::Expr,
2442                         output: ty::FnOutput<'tcx>) {
2443     fcx.write_ty(call_expr.id, match output {
2444         ty::FnConverging(output_ty) => output_ty,
2445         ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2446     });
2447 }
2448
2449 // AST fragment checking
2450 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2451                        lit: &ast::Lit,
2452                        expected: Expectation<'tcx>)
2453                        -> Ty<'tcx>
2454 {
2455     let tcx = fcx.ccx.tcx;
2456
2457     match lit.node {
2458         ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2459         ast::LitBinary(..) => {
2460             ty::mk_slice(tcx,
2461                          tcx.mk_region(ty::ReStatic),
2462                          ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2463         }
2464         ast::LitByte(_) => tcx.types.u8,
2465         ast::LitChar(_) => tcx.types.char,
2466         ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2467         ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2468         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2469             let opt_ty = expected.to_option(fcx).and_then(|ty| {
2470                 match ty.sty {
2471                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2472                     ty::ty_char => Some(tcx.types.u8),
2473                     ty::ty_ptr(..) => Some(tcx.types.uint),
2474                     ty::ty_bare_fn(..) => Some(tcx.types.uint),
2475                     _ => None
2476                 }
2477             });
2478             opt_ty.unwrap_or_else(
2479                 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2480         }
2481         ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2482         ast::LitFloatUnsuffixed(_) => {
2483             let opt_ty = expected.to_option(fcx).and_then(|ty| {
2484                 match ty.sty {
2485                     ty::ty_float(_) => Some(ty),
2486                     _ => None
2487                 }
2488             });
2489             opt_ty.unwrap_or_else(
2490                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2491         }
2492         ast::LitBool(_) => tcx.types.bool
2493     }
2494 }
2495
2496 pub fn valid_range_bounds(ccx: &CrateCtxt,
2497                           from: &ast::Expr,
2498                           to: &ast::Expr)
2499                        -> Option<bool> {
2500     match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2501         Some(val) => Some(val <= 0),
2502         None => None
2503     }
2504 }
2505
2506 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2507                                      expr: &ast::Expr,
2508                                      expected: Ty<'tcx>) {
2509     check_expr_with_unifier(
2510         fcx, expr, ExpectHasType(expected), NoPreference,
2511         || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2512 }
2513
2514 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2515                                           expr: &ast::Expr,
2516                                           expected: Ty<'tcx>) {
2517     check_expr_with_unifier(
2518         fcx, expr, ExpectHasType(expected), NoPreference,
2519         || demand::coerce(fcx, expr.span, expected, expr));
2520 }
2521
2522 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2523                                   expected: Ty<'tcx>) {
2524     check_expr_with_unifier(
2525         fcx, expr, ExpectHasType(expected), NoPreference,
2526         || ())
2527 }
2528
2529 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2530                                          expr: &ast::Expr,
2531                                          expected: Expectation<'tcx>) {
2532     check_expr_with_unifier(
2533         fcx, expr, expected, NoPreference,
2534         || ())
2535 }
2536
2537 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2538                                                          expr: &ast::Expr,
2539                                                          expected: Expectation<'tcx>,
2540                                                          lvalue_pref: LvaluePreference)
2541 {
2542     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2543 }
2544
2545 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr)  {
2546     check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2547 }
2548
2549 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2550                                lvalue_pref: LvaluePreference)  {
2551     check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2552 }
2553
2554 // determine the `self` type, using fresh variables for all variables
2555 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2556 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2557 // variables.
2558 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2559                               span: Span, // (potential) receiver for this impl
2560                               did: ast::DefId)
2561                               -> TypeAndSubsts<'tcx> {
2562     let tcx = fcx.tcx();
2563
2564     let ity = ty::lookup_item_type(tcx, did);
2565     let (n_tps, rps, raw_ty) =
2566         (ity.generics.types.len(subst::TypeSpace),
2567          ity.generics.regions.get_slice(subst::TypeSpace),
2568          ity.ty);
2569
2570     let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2571     let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2572     let substs = subst::Substs::new_type(tps, rps);
2573     let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2574
2575     TypeAndSubsts { substs: substs, ty: substd_ty }
2576 }
2577
2578 // Controls whether the arguments are automatically referenced. This is useful
2579 // for overloaded binary and unary operators.
2580 #[derive(Copy, PartialEq)]
2581 pub enum AutorefArgs {
2582     Yes,
2583     No,
2584 }
2585
2586 /// Controls whether the arguments are tupled. This is used for the call
2587 /// operator.
2588 ///
2589 /// Tupling means that all call-side arguments are packed into a tuple and
2590 /// passed as a single parameter. For example, if tupling is enabled, this
2591 /// function:
2592 ///
2593 ///     fn f(x: (int, int))
2594 ///
2595 /// Can be called as:
2596 ///
2597 ///     f(1, 2);
2598 ///
2599 /// Instead of:
2600 ///
2601 ///     f((1, 2));
2602 #[derive(Clone, Eq, PartialEq)]
2603 enum TupleArgumentsFlag {
2604     DontTupleArguments,
2605     TupleArguments,
2606 }
2607
2608 /// Unifies the return type with the expected type early, for more coercions
2609 /// and forward type information on the argument expressions.
2610 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2611                                         call_span: Span,
2612                                         expected_ret: Expectation<'tcx>,
2613                                         formal_ret: ty::FnOutput<'tcx>,
2614                                         formal_args: &[Ty<'tcx>])
2615                                         -> Vec<Ty<'tcx>> {
2616     let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2617         if let ty::FnConverging(formal_ret_ty) = formal_ret {
2618             fcx.infcx().commit_regions_if_ok(|| {
2619                 // Attempt to apply a subtyping relationship between the formal
2620                 // return type (likely containing type variables if the function
2621                 // is polymorphic) and the expected return type.
2622                 // No argument expectations are produced if unification fails.
2623                 let origin = infer::Misc(call_span);
2624                 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2625                 // FIXME(#15760) can't use try! here, FromError doesn't default
2626                 // to identity so the resulting type is not constrained.
2627                 if let Err(e) = ures {
2628                     return Err(e);
2629                 }
2630
2631                 // Record all the argument types, with the substitutions
2632                 // produced from the above subtyping unification.
2633                 Ok(formal_args.iter().map(|ty| {
2634                     fcx.infcx().resolve_type_vars_if_possible(ty)
2635                 }).collect())
2636             }).ok()
2637         } else {
2638             None
2639         }
2640     }).unwrap_or(vec![]);
2641     debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2642            formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2643            expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2644     expected_args
2645 }
2646
2647 /// Invariant:
2648 /// If an expression has any sub-expressions that result in a type error,
2649 /// inspecting that expression's type with `ty::type_is_error` will return
2650 /// true. Likewise, if an expression is known to diverge, inspecting its
2651 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2652 /// strict, _|_ can appear in the type of an expression that does not,
2653 /// itself, diverge: for example, fn() -> _|_.)
2654 /// Note that inspecting a type's structure *directly* may expose the fact
2655 /// that there are actually multiple representations for `ty_err`, so avoid
2656 /// that when err needs to be handled differently.
2657 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2658                                         expr: &ast::Expr,
2659                                         expected: Expectation<'tcx>,
2660                                         lvalue_pref: LvaluePreference,
2661                                         unifier: F) where
2662     F: FnOnce(),
2663 {
2664     debug!(">> typechecking: expr={} expected={}",
2665            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2666
2667     // Checks a method call.
2668     fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2669                                    expr: &ast::Expr,
2670                                    method_name: ast::SpannedIdent,
2671                                    args: &[P<ast::Expr>],
2672                                    tps: &[P<ast::Ty>],
2673                                    expected: Expectation<'tcx>,
2674                                    lvalue_pref: LvaluePreference) {
2675         let rcvr = &*args[0];
2676         check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2677
2678         // no need to check for bot/err -- callee does that
2679         let expr_t = structurally_resolved_type(fcx,
2680                                                 expr.span,
2681                                                 fcx.expr_ty(&*rcvr));
2682
2683         let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2684         let fn_ty = match method::lookup(fcx,
2685                                          method_name.span,
2686                                          method_name.node.name,
2687                                          expr_t,
2688                                          tps,
2689                                          expr,
2690                                          rcvr) {
2691             Ok(method) => {
2692                 let method_ty = method.ty;
2693                 let method_call = MethodCall::expr(expr.id);
2694                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2695                 method_ty
2696             }
2697             Err(error) => {
2698                 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
2699                 fcx.write_error(expr.id);
2700                 fcx.tcx().types.err
2701             }
2702         };
2703
2704         // Call the generic checker.
2705         let ret_ty = check_method_argument_types(fcx,
2706                                                  method_name.span,
2707                                                  fn_ty,
2708                                                  expr,
2709                                                  &args[1..],
2710                                                  AutorefArgs::No,
2711                                                  DontTupleArguments,
2712                                                  expected);
2713
2714         write_call(fcx, expr, ret_ty);
2715     }
2716
2717     // A generic function for checking the then and else in an if
2718     // or if-else.
2719     fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2720                                  cond_expr: &ast::Expr,
2721                                  then_blk: &ast::Block,
2722                                  opt_else_expr: Option<&ast::Expr>,
2723                                  id: ast::NodeId,
2724                                  sp: Span,
2725                                  expected: Expectation<'tcx>) {
2726         check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2727
2728         let expected = expected.adjust_for_branches(fcx);
2729         check_block_with_expected(fcx, then_blk, expected);
2730         let then_ty = fcx.node_ty(then_blk.id);
2731
2732         let branches_ty = match opt_else_expr {
2733             Some(ref else_expr) => {
2734                 check_expr_with_expectation(fcx, &**else_expr, expected);
2735                 let else_ty = fcx.expr_ty(&**else_expr);
2736                 infer::common_supertype(fcx.infcx(),
2737                                         infer::IfExpression(sp),
2738                                         true,
2739                                         then_ty,
2740                                         else_ty)
2741             }
2742             None => {
2743                 infer::common_supertype(fcx.infcx(),
2744                                         infer::IfExpressionWithNoElse(sp),
2745                                         false,
2746                                         then_ty,
2747                                         ty::mk_nil(fcx.tcx()))
2748             }
2749         };
2750
2751         let cond_ty = fcx.expr_ty(cond_expr);
2752         let if_ty = if ty::type_is_error(cond_ty) {
2753             fcx.tcx().types.err
2754         } else {
2755             branches_ty
2756         };
2757
2758         fcx.write_ty(id, if_ty);
2759     }
2760
2761     fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2762                                      op_ex: &ast::Expr,
2763                                      lhs_ty: Ty<'tcx>,
2764                                      opname: ast::Name,
2765                                      trait_did: Option<ast::DefId>,
2766                                      lhs: &'a ast::Expr,
2767                                      rhs: Option<&P<ast::Expr>>,
2768                                      unbound_method: F,
2769                                      autoref_args: AutorefArgs) -> Ty<'tcx> where
2770         F: FnOnce(),
2771     {
2772         let method = match trait_did {
2773             Some(trait_did) => {
2774                 // We do eager coercions to make using operators
2775                 // more ergonomic:
2776                 //
2777                 // - If the input is of type &'a T (resp. &'a mut T),
2778                 //   then reborrow it to &'b T (resp. &'b mut T) where
2779                 //   'b <= 'a.  This makes things like `x == y`, where
2780                 //   `x` and `y` are both region pointers, work.  We
2781                 //   could also solve this with variance or different
2782                 //   traits that don't force left and right to have same
2783                 //   type.
2784                 let (adj_ty, adjustment) = match lhs_ty.sty {
2785                     ty::ty_rptr(r_in, mt) => {
2786                         let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2787                         fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2788                         let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2789                         let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2790                         let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2791                         (adjusted_ty, adjustment)
2792                     }
2793                     _ => {
2794                         (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2795                     }
2796                 };
2797
2798                 debug!("adjusted_ty={} adjustment={:?}",
2799                        adj_ty.repr(fcx.tcx()),
2800                        adjustment);
2801
2802                 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2803                                                  trait_did, adjustment, adj_ty, None)
2804             }
2805             None => None
2806         };
2807         let args = match rhs {
2808             Some(rhs) => slice::ref_slice(rhs),
2809             None => &[][]
2810         };
2811         match method {
2812             Some(method) => {
2813                 let method_ty = method.ty;
2814                 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2815                 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2816                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2817                 match check_method_argument_types(fcx,
2818                                                   op_ex.span,
2819                                                   method_ty,
2820                                                   op_ex,
2821                                                   args,
2822                                                   autoref_args,
2823                                                   DontTupleArguments,
2824                                                   NoExpectation) {
2825                     ty::FnConverging(result_type) => result_type,
2826                     ty::FnDiverging => fcx.tcx().types.err
2827                 }
2828             }
2829             None => {
2830                 unbound_method();
2831                 // Check the args anyway
2832                 // so we get all the error messages
2833                 let expected_ty = fcx.tcx().types.err;
2834                 check_method_argument_types(fcx,
2835                                             op_ex.span,
2836                                             expected_ty,
2837                                             op_ex,
2838                                             args,
2839                                             autoref_args,
2840                                             DontTupleArguments,
2841                                             NoExpectation);
2842                 fcx.tcx().types.err
2843             }
2844         }
2845     }
2846
2847     // could be either an expr_binop or an expr_assign_binop
2848     fn check_binop(fcx: &FnCtxt,
2849                    expr: &ast::Expr,
2850                    op: ast::BinOp,
2851                    lhs: &ast::Expr,
2852                    rhs: &P<ast::Expr>,
2853                    is_binop_assignment: IsBinopAssignment) {
2854         let tcx = fcx.ccx.tcx;
2855
2856         let lvalue_pref = match is_binop_assignment {
2857             BinopAssignment => PreferMutLvalue,
2858             SimpleBinop => NoPreference
2859         };
2860         check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2861
2862         // Callee does bot / err checking
2863         let lhs_t = structurally_resolved_type(fcx, lhs.span,
2864                                                fcx.expr_ty(&*lhs));
2865
2866         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2867             // Shift is a special case: rhs must be uint, no matter what lhs is
2868             check_expr(fcx, &**rhs);
2869             let rhs_ty = fcx.expr_ty(&**rhs);
2870             let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
2871             if ty::type_is_integral(rhs_ty) {
2872                 fcx.write_ty(expr.id, lhs_t);
2873             } else {
2874                 fcx.type_error_message(
2875                     expr.span,
2876                     |actual| {
2877                         format!(
2878                             "right-hand-side of a shift operation must have integral type, \
2879                              not `{}`",
2880                             actual)
2881                     },
2882                     rhs_ty,
2883                     None);
2884                 fcx.write_ty(expr.id, fcx.tcx().types.err);
2885             }
2886             return;
2887         }
2888
2889         if ty::is_binopable(tcx, lhs_t, op) {
2890             let tvar = fcx.infcx().next_ty_var();
2891             demand::suptype(fcx, expr.span, tvar, lhs_t);
2892             check_expr_has_type(fcx, &**rhs, tvar);
2893
2894             let result_t = match op {
2895                 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2896                 ast::BiGt => {
2897                     if ty::type_is_simd(tcx, lhs_t) {
2898                         if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2899                             fcx.type_error_message(expr.span,
2900                                 |actual| {
2901                                     format!("binary comparison \
2902                                              operation `{}` not \
2903                                              supported for floating \
2904                                              point SIMD vector `{}`",
2905                                             ast_util::binop_to_string(op),
2906                                             actual)
2907                                 },
2908                                 lhs_t,
2909                                 None
2910                             );
2911                             fcx.tcx().types.err
2912                         } else {
2913                             lhs_t
2914                         }
2915                     } else {
2916                         fcx.tcx().types.bool
2917                     }
2918                 },
2919                 _ => lhs_t,
2920             };
2921
2922             fcx.write_ty(expr.id, result_t);
2923             return;
2924         }
2925
2926         if op == ast::BiOr || op == ast::BiAnd {
2927             // This is an error; one of the operands must have the wrong
2928             // type
2929             fcx.write_error(expr.id);
2930             fcx.write_error(rhs.id);
2931             fcx.type_error_message(expr.span,
2932                                    |actual| {
2933                     format!("binary operation `{}` cannot be applied \
2934                              to type `{}`",
2935                             ast_util::binop_to_string(op),
2936                             actual)
2937                 },
2938                 lhs_t,
2939                 None)
2940         }
2941
2942         // Check for overloaded operators if not an assignment.
2943         let result_t = if is_binop_assignment == SimpleBinop {
2944             check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2945         } else {
2946             fcx.type_error_message(expr.span,
2947                                    |actual| {
2948                                         format!("binary assignment \
2949                                                  operation `{}=` \
2950                                                  cannot be applied to \
2951                                                  type `{}`",
2952                                                 ast_util::binop_to_string(op),
2953                                                 actual)
2954                                    },
2955                                    lhs_t,
2956                                    None);
2957             check_expr(fcx, &**rhs);
2958             fcx.tcx().types.err
2959         };
2960
2961         fcx.write_ty(expr.id, result_t);
2962         if ty::type_is_error(result_t) {
2963             fcx.write_ty(rhs.id, result_t);
2964         }
2965     }
2966
2967     fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2968                                   ex: &ast::Expr,
2969                                   lhs_expr: &ast::Expr,
2970                                   lhs_resolved_t: Ty<'tcx>,
2971                                   op: ast::BinOp,
2972                                   rhs: &P<ast::Expr>) -> Ty<'tcx> {
2973         let tcx = fcx.ccx.tcx;
2974         let lang = &tcx.lang_items;
2975         let (name, trait_did) = match op {
2976             ast::BiAdd => ("add", lang.add_trait()),
2977             ast::BiSub => ("sub", lang.sub_trait()),
2978             ast::BiMul => ("mul", lang.mul_trait()),
2979             ast::BiDiv => ("div", lang.div_trait()),
2980             ast::BiRem => ("rem", lang.rem_trait()),
2981             ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2982             ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2983             ast::BiBitOr => ("bitor", lang.bitor_trait()),
2984             ast::BiShl => ("shl", lang.shl_trait()),
2985             ast::BiShr => ("shr", lang.shr_trait()),
2986             ast::BiLt => ("lt", lang.ord_trait()),
2987             ast::BiLe => ("le", lang.ord_trait()),
2988             ast::BiGe => ("ge", lang.ord_trait()),
2989             ast::BiGt => ("gt", lang.ord_trait()),
2990             ast::BiEq => ("eq", lang.eq_trait()),
2991             ast::BiNe => ("ne", lang.eq_trait()),
2992             ast::BiAnd | ast::BiOr => {
2993                 check_expr(fcx, &**rhs);
2994                 return tcx.types.err;
2995             }
2996         };
2997         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2998                          trait_did, lhs_expr, Some(rhs), || {
2999             fcx.type_error_message(ex.span, |actual| {
3000                 format!("binary operation `{}` cannot be applied to type `{}`",
3001                         ast_util::binop_to_string(op),
3002                         actual)
3003             }, lhs_resolved_t, None)
3004         }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3005     }
3006
3007     fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3008                                  op_str: &str,
3009                                  mname: &str,
3010                                  trait_did: Option<ast::DefId>,
3011                                  ex: &ast::Expr,
3012                                  rhs_expr: &ast::Expr,
3013                                  rhs_t: Ty<'tcx>,
3014                                  op: ast::UnOp) -> Ty<'tcx> {
3015        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3016                         trait_did, rhs_expr, None, || {
3017             fcx.type_error_message(ex.span, |actual| {
3018                 format!("cannot apply unary operator `{}` to type `{}`",
3019                         op_str, actual)
3020             }, rhs_t, None);
3021         }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3022     }
3023
3024     // Check field access expressions
3025     fn check_field(fcx: &FnCtxt,
3026                    expr: &ast::Expr,
3027                    lvalue_pref: LvaluePreference,
3028                    base: &ast::Expr,
3029                    field: &ast::SpannedIdent) {
3030         let tcx = fcx.ccx.tcx;
3031         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3032         let expr_t = structurally_resolved_type(fcx, expr.span,
3033                                                 fcx.expr_ty(base));
3034         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3035         let (_, autoderefs, field_ty) =
3036             autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3037                 match base_t.sty {
3038                     ty::ty_struct(base_id, substs) => {
3039                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3040                         let fields = ty::lookup_struct_fields(tcx, base_id);
3041                         fcx.lookup_field_ty(expr.span, base_id, &fields[],
3042                                             field.node.name, &(*substs))
3043                     }
3044                     _ => None
3045                 }
3046             });
3047         match field_ty {
3048             Some(field_ty) => {
3049                 fcx.write_ty(expr.id, field_ty);
3050                 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3051                 return;
3052             }
3053             None => {}
3054         }
3055
3056         if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3057             fcx.type_error_message(
3058                 field.span,
3059                 |actual| {
3060                     format!("attempted to take value of method `{}` on type \
3061                             `{}`", token::get_ident(field.node), actual)
3062                 },
3063                 expr_t, None);
3064
3065             tcx.sess.span_help(field.span,
3066                                "maybe a `()` to call it is missing? \
3067                                If not, try an anonymous function");
3068         } else {
3069             fcx.type_error_message(
3070                 expr.span,
3071                 |actual| {
3072                     format!("attempted access of field `{}` on \
3073                             type `{}`, but no field with that \
3074                             name was found",
3075                             token::get_ident(field.node),
3076                             actual)
3077                 },
3078                 expr_t, None);
3079         }
3080
3081         fcx.write_error(expr.id);
3082     }
3083
3084     // Check tuple index expressions
3085     fn check_tup_field(fcx: &FnCtxt,
3086                        expr: &ast::Expr,
3087                        lvalue_pref: LvaluePreference,
3088                        base: &ast::Expr,
3089                        idx: codemap::Spanned<uint>) {
3090         let tcx = fcx.ccx.tcx;
3091         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3092         let expr_t = structurally_resolved_type(fcx, expr.span,
3093                                                 fcx.expr_ty(base));
3094         let mut tuple_like = false;
3095         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3096         let (_, autoderefs, field_ty) =
3097             autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3098                 match base_t.sty {
3099                     ty::ty_struct(base_id, substs) => {
3100                         tuple_like = ty::is_tuple_struct(tcx, base_id);
3101                         if tuple_like {
3102                             debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3103                             let fields = ty::lookup_struct_fields(tcx, base_id);
3104                             fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3105                                                     idx.node, &(*substs))
3106                         } else {
3107                             None
3108                         }
3109                     }
3110                     ty::ty_tup(ref v) => {
3111                         tuple_like = true;
3112                         if idx.node < v.len() { Some(v[idx.node]) } else { None }
3113                     }
3114                     _ => None
3115                 }
3116             });
3117         match field_ty {
3118             Some(field_ty) => {
3119                 fcx.write_ty(expr.id, field_ty);
3120                 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3121                 return;
3122             }
3123             None => {}
3124         }
3125         fcx.type_error_message(
3126             expr.span,
3127             |actual| {
3128                 if tuple_like {
3129                     format!("attempted out-of-bounds tuple index `{}` on \
3130                                     type `{}`",
3131                                    idx.node,
3132                                    actual)
3133                 } else {
3134                     format!("attempted tuple index `{}` on type `{}`, but the \
3135                                      type was not a tuple or tuple struct",
3136                                     idx.node,
3137                                     actual)
3138                 }
3139             },
3140             expr_t, None);
3141
3142         fcx.write_error(expr.id);
3143     }
3144
3145     fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3146                                                 struct_ty: Ty<'tcx>,
3147                                                 span: Span,
3148                                                 class_id: ast::DefId,
3149                                                 node_id: ast::NodeId,
3150                                                 substitutions: &'tcx subst::Substs<'tcx>,
3151                                                 field_types: &[ty::field_ty],
3152                                                 ast_fields: &[ast::Field],
3153                                                 check_completeness: bool,
3154                                                 enum_id_opt: Option<ast::DefId>)  {
3155         let tcx = fcx.ccx.tcx;
3156
3157         let mut class_field_map = FnvHashMap::new();
3158         let mut fields_found = 0;
3159         for field in field_types.iter() {
3160             class_field_map.insert(field.name, (field.id, false));
3161         }
3162
3163         let mut error_happened = false;
3164
3165         // Typecheck each field.
3166         for field in ast_fields.iter() {
3167             let mut expected_field_type = tcx.types.err;
3168
3169             let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3170             match pair {
3171                 None => {
3172                     fcx.type_error_message(
3173                         field.ident.span,
3174                         |actual| match enum_id_opt {
3175                             Some(enum_id) => {
3176                                 let variant_type = ty::enum_variant_with_id(tcx,
3177                                                                             enum_id,
3178                                                                             class_id);
3179                                 format!("struct variant `{}::{}` has no field named `{}`",
3180                                         actual, variant_type.name.as_str(),
3181                                         token::get_ident(field.ident.node))
3182                             }
3183                             None => {
3184                                 format!("structure `{}` has no field named `{}`",
3185                                         actual,
3186                                         token::get_ident(field.ident.node))
3187                             }
3188                         },
3189                         struct_ty,
3190                         None);
3191                     error_happened = true;
3192                 }
3193                 Some((_, true)) => {
3194                     span_err!(fcx.tcx().sess, field.ident.span, E0062,
3195                         "field `{}` specified more than once",
3196                         token::get_ident(field.ident.node));
3197                     error_happened = true;
3198                 }
3199                 Some((field_id, false)) => {
3200                     expected_field_type =
3201                         ty::lookup_field_type(
3202                             tcx, class_id, field_id, substitutions);
3203                     expected_field_type =
3204                         fcx.normalize_associated_types_in(
3205                             field.span, &expected_field_type);
3206                     class_field_map.insert(
3207                         field.ident.node.name, (field_id, true));
3208                     fields_found += 1;
3209                 }
3210             }
3211
3212             // Make sure to give a type to the field even if there's
3213             // an error, so we can continue typechecking
3214             check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3215         }
3216
3217         if error_happened {
3218             fcx.write_error(node_id);
3219         }
3220
3221         if check_completeness && !error_happened {
3222             // Make sure the programmer specified all the fields.
3223             assert!(fields_found <= field_types.len());
3224             if fields_found < field_types.len() {
3225                 let mut missing_fields = Vec::new();
3226                 for class_field in field_types.iter() {
3227                     let name = class_field.name;
3228                     let (_, seen) = class_field_map[name];
3229                     if !seen {
3230                         missing_fields.push(
3231                             format!("`{}`", token::get_name(name).get()))
3232                     }
3233                 }
3234
3235                 span_err!(tcx.sess, span, E0063,
3236                     "missing field{}: {}",
3237                     if missing_fields.len() == 1 {""} else {"s"},
3238                     missing_fields.connect(", "));
3239              }
3240         }
3241
3242         if !error_happened {
3243             fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3244                                 class_id, substitutions));
3245         }
3246     }
3247
3248     fn check_struct_constructor(fcx: &FnCtxt,
3249                                 id: ast::NodeId,
3250                                 span: codemap::Span,
3251                                 class_id: ast::DefId,
3252                                 fields: &[ast::Field],
3253                                 base_expr: Option<&ast::Expr>) {
3254         let tcx = fcx.ccx.tcx;
3255
3256         // Generate the struct type.
3257         let TypeAndSubsts {
3258             ty: mut struct_type,
3259             substs: struct_substs
3260         } = fcx.instantiate_type(span, class_id);
3261
3262         // Look up and check the fields.
3263         let class_fields = ty::lookup_struct_fields(tcx, class_id);
3264         check_struct_or_variant_fields(fcx,
3265                                        struct_type,
3266                                        span,
3267                                        class_id,
3268                                        id,
3269                                        fcx.ccx.tcx.mk_substs(struct_substs),
3270                                        &class_fields[],
3271                                        fields,
3272                                        base_expr.is_none(),
3273                                        None);
3274         if ty::type_is_error(fcx.node_ty(id)) {
3275             struct_type = tcx.types.err;
3276         }
3277
3278         // Check the base expression if necessary.
3279         match base_expr {
3280             None => {}
3281             Some(base_expr) => {
3282                 check_expr_has_type(fcx, &*base_expr, struct_type);
3283             }
3284         }
3285
3286         // Write in the resulting type.
3287         fcx.write_ty(id, struct_type);
3288     }
3289
3290     fn check_struct_enum_variant(fcx: &FnCtxt,
3291                                  id: ast::NodeId,
3292                                  span: codemap::Span,
3293                                  enum_id: ast::DefId,
3294                                  variant_id: ast::DefId,
3295                                  fields: &[ast::Field]) {
3296         let tcx = fcx.ccx.tcx;
3297
3298         // Look up the number of type parameters and the raw type, and
3299         // determine whether the enum is region-parameterized.
3300         let TypeAndSubsts {
3301             ty: enum_type,
3302             substs: substitutions
3303         } = fcx.instantiate_type(span, enum_id);
3304
3305         // Look up and check the enum variant fields.
3306         let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3307         check_struct_or_variant_fields(fcx,
3308                                        enum_type,
3309                                        span,
3310                                        variant_id,
3311                                        id,
3312                                        fcx.ccx.tcx.mk_substs(substitutions),
3313                                        &variant_fields[],
3314                                        fields,
3315                                        true,
3316                                        Some(enum_id));
3317         fcx.write_ty(id, enum_type);
3318     }
3319
3320     fn check_struct_fields_on_error(fcx: &FnCtxt,
3321                                     id: ast::NodeId,
3322                                     fields: &[ast::Field],
3323                                     base_expr: &Option<P<ast::Expr>>) {
3324         // Make sure to still write the types
3325         // otherwise we might ICE
3326         fcx.write_error(id);
3327         for field in fields.iter() {
3328             check_expr(fcx, &*field.expr);
3329         }
3330         match *base_expr {
3331             Some(ref base) => check_expr(fcx, &**base),
3332             None => {}
3333         }
3334     }
3335
3336     type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3337
3338     let tcx = fcx.ccx.tcx;
3339     let id = expr.id;
3340     match expr.node {
3341       ast::ExprBox(ref opt_place, ref subexpr) => {
3342           opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3343           check_expr(fcx, &**subexpr);
3344
3345           let mut checked = false;
3346           opt_place.as_ref().map(|place| match place.node {
3347               ast::ExprPath(ref path) => {
3348                   // FIXME(pcwalton): For now we hardcode the two permissible
3349                   // places: the exchange heap and the managed heap.
3350                   let definition = lookup_def(fcx, path.span, place.id);
3351                   let def_id = definition.def_id();
3352                   let referent_ty = fcx.expr_ty(&**subexpr);
3353                   if tcx.lang_items.exchange_heap() == Some(def_id) {
3354                       fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3355                       checked = true
3356                   }
3357               }
3358               _ => {}
3359           });
3360
3361           if !checked {
3362               span_err!(tcx.sess, expr.span, E0066,
3363                   "only the managed heap and exchange heap are currently supported");
3364               fcx.write_ty(id, tcx.types.err);
3365           }
3366       }
3367
3368       ast::ExprLit(ref lit) => {
3369         let typ = check_lit(fcx, &**lit, expected);
3370         fcx.write_ty(id, typ);
3371       }
3372       ast::ExprBinary(op, ref lhs, ref rhs) => {
3373         check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3374
3375         let lhs_ty = fcx.expr_ty(&**lhs);
3376         let rhs_ty = fcx.expr_ty(&**rhs);
3377         if ty::type_is_error(lhs_ty) ||
3378             ty::type_is_error(rhs_ty) {
3379             fcx.write_error(id);
3380         }
3381       }
3382       ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3383         check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3384
3385         let lhs_t = fcx.expr_ty(&**lhs);
3386         let result_t = fcx.expr_ty(expr);
3387         demand::suptype(fcx, expr.span, result_t, lhs_t);
3388
3389         let tcx = fcx.tcx();
3390         if !ty::expr_is_lval(tcx, &**lhs) {
3391             span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3392         }
3393
3394         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3395
3396         // Overwrite result of check_binop...this preserves existing behavior
3397         // but seems quite dubious with regard to user-defined methods
3398         // and so forth. - Niko
3399         if !ty::type_is_error(result_t) {
3400             fcx.write_nil(expr.id);
3401         }
3402       }
3403       ast::ExprUnary(unop, ref oprnd) => {
3404         let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3405             match unop {
3406                 ast::UnUniq => match ty.sty {
3407                     ty::ty_uniq(ty) => {
3408                         Expectation::rvalue_hint(ty)
3409                     }
3410                     _ => {
3411                         NoExpectation
3412                     }
3413                 },
3414                 ast::UnNot | ast::UnNeg => {
3415                     expected
3416                 }
3417                 ast::UnDeref => {
3418                     NoExpectation
3419                 }
3420             }
3421         });
3422         let lvalue_pref = match unop {
3423             ast::UnDeref => lvalue_pref,
3424             _ => NoPreference
3425         };
3426         check_expr_with_expectation_and_lvalue_pref(
3427             fcx, &**oprnd, expected_inner, lvalue_pref);
3428         let mut oprnd_t = fcx.expr_ty(&**oprnd);
3429
3430         if !ty::type_is_error(oprnd_t) {
3431             match unop {
3432                 ast::UnUniq => {
3433                     oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3434                 }
3435                 ast::UnDeref => {
3436                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3437                     oprnd_t = match ty::deref(oprnd_t, true) {
3438                         Some(mt) => mt.ty,
3439                         None => match try_overloaded_deref(fcx, expr.span,
3440                                                            Some(MethodCall::expr(expr.id)),
3441                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
3442                             Some(mt) => mt.ty,
3443                             None => {
3444                                 let is_newtype = match oprnd_t.sty {
3445                                     ty::ty_struct(did, substs) => {
3446                                         let fields = ty::struct_fields(fcx.tcx(), did, substs);
3447                                         fields.len() == 1
3448                                         && fields[0].name ==
3449                                         token::special_idents::unnamed_field.name
3450                                     }
3451                                     _ => false
3452                                 };
3453                                 if is_newtype {
3454                                     // This is an obsolete struct deref
3455                                     span_err!(tcx.sess, expr.span, E0068,
3456                                         "single-field tuple-structs can \
3457                                          no longer be dereferenced");
3458                                 } else {
3459                                     fcx.type_error_message(expr.span, |actual| {
3460                                         format!("type `{}` cannot be \
3461                                                 dereferenced", actual)
3462                                     }, oprnd_t, None);
3463                                 }
3464                                 tcx.types.err
3465                             }
3466                         }
3467                     };
3468                 }
3469                 ast::UnNot => {
3470                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3471                                                          oprnd_t);
3472                     if !(ty::type_is_integral(oprnd_t) ||
3473                          oprnd_t.sty == ty::ty_bool) {
3474                         oprnd_t = check_user_unop(fcx, "!", "not",
3475                                                   tcx.lang_items.not_trait(),
3476                                                   expr, &**oprnd, oprnd_t, unop);
3477                     }
3478                 }
3479                 ast::UnNeg => {
3480                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3481                                                          oprnd_t);
3482                     if !(ty::type_is_integral(oprnd_t) ||
3483                          ty::type_is_fp(oprnd_t)) {
3484                         oprnd_t = check_user_unop(fcx, "-", "neg",
3485                                                   tcx.lang_items.neg_trait(),
3486                                                   expr, &**oprnd, oprnd_t, unop);
3487                     }
3488                 }
3489             }
3490         }
3491         fcx.write_ty(id, oprnd_t);
3492       }
3493       ast::ExprAddrOf(mutbl, ref oprnd) => {
3494         let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3495             match ty.sty {
3496                 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3497                     if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3498                         // Lvalues may legitimately have unsized types.
3499                         // For example, dereferences of a fat pointer and
3500                         // the last field of a struct can be unsized.
3501                         ExpectHasType(mt.ty)
3502                     } else {
3503                         Expectation::rvalue_hint(mt.ty)
3504                     }
3505                 }
3506                 _ => NoExpectation
3507             }
3508         });
3509         let lvalue_pref = match mutbl {
3510             ast::MutMutable => PreferMutLvalue,
3511             ast::MutImmutable => NoPreference
3512         };
3513         check_expr_with_expectation_and_lvalue_pref(fcx,
3514                                                     &**oprnd,
3515                                                     hint,
3516                                                     lvalue_pref);
3517
3518         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3519         let oprnd_t = if ty::type_is_error(tm.ty) {
3520             tcx.types.err
3521         } else {
3522             // Note: at this point, we cannot say what the best lifetime
3523             // is to use for resulting pointer.  We want to use the
3524             // shortest lifetime possible so as to avoid spurious borrowck
3525             // errors.  Moreover, the longest lifetime will depend on the
3526             // precise details of the value whose address is being taken
3527             // (and how long it is valid), which we don't know yet until type
3528             // inference is complete.
3529             //
3530             // Therefore, here we simply generate a region variable.  The
3531             // region inferencer will then select the ultimate value.
3532             // Finally, borrowck is charged with guaranteeing that the
3533             // value whose address was taken can actually be made to live
3534             // as long as it needs to live.
3535             match oprnd.node {
3536                 // String literals are already, implicitly converted to slices.
3537                 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3538                 // Empty slices live in static memory.
3539                 ast::ExprVec(ref elements) if elements.len() == 0 => {
3540                     // Note: we do not assign a lifetime of
3541                     // static. This is because the resulting type
3542                     // `&'static [T]` would require that T outlives
3543                     // `'static`!
3544                     let region = fcx.infcx().next_region_var(
3545                         infer::AddrOfSlice(expr.span));
3546                     ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3547                 }
3548                 _ => {
3549                     let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3550                     ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3551                 }
3552             }
3553         };
3554         fcx.write_ty(id, oprnd_t);
3555       }
3556       ast::ExprPath(ref path) => {
3557           let defn = lookup_def(fcx, path.span, id);
3558           let pty = type_scheme_for_def(fcx, expr.span, defn);
3559           instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3560
3561           // We always require that the type provided as the value for
3562           // a type parameter outlives the moment of instantiation.
3563           constrain_path_type_parameters(fcx, expr);
3564       }
3565       ast::ExprQPath(ref qpath) => {
3566           // Require explicit type params for the trait.
3567           let self_ty = fcx.to_ty(&*qpath.self_type);
3568           astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3569
3570           let defn = lookup_def(fcx, expr.span, id);
3571           let pty = type_scheme_for_def(fcx, expr.span, defn);
3572           let mut path = qpath.trait_ref.path.clone();
3573           path.segments.push(qpath.item_path.clone());
3574           instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3575
3576           // We always require that the type provided as the value for
3577           // a type parameter outlives the moment of instantiation.
3578           constrain_path_type_parameters(fcx, expr);
3579       }
3580       ast::ExprInlineAsm(ref ia) => {
3581           for &(_, ref input) in ia.inputs.iter() {
3582               check_expr(fcx, &**input);
3583           }
3584           for &(_, ref out, _) in ia.outputs.iter() {
3585               check_expr(fcx, &**out);
3586           }
3587           fcx.write_nil(id);
3588       }
3589       ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3590       ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3591       ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3592       ast::ExprRet(ref expr_opt) => {
3593         match fcx.ret_ty {
3594             ty::FnConverging(result_type) => {
3595                 match *expr_opt {
3596                     None =>
3597                         if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3598                                                     result_type, ty::mk_nil(fcx.tcx())) {
3599                             span_err!(tcx.sess, expr.span, E0069,
3600                                 "`return;` in function returning non-nil");
3601                         },
3602                     Some(ref e) => {
3603                         check_expr_coercable_to_type(fcx, &**e, result_type);
3604                     }
3605                 }
3606             }
3607             ty::FnDiverging => {
3608                 if let Some(ref e) = *expr_opt {
3609                     check_expr(fcx, &**e);
3610                 }
3611                 span_err!(tcx.sess, expr.span, E0166,
3612                     "`return` in a function declared as diverging");
3613             }
3614         }
3615         fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3616       }
3617       ast::ExprParen(ref a) => {
3618         check_expr_with_expectation_and_lvalue_pref(fcx,
3619                                                     &**a,
3620                                                     expected,
3621                                                     lvalue_pref);
3622         fcx.write_ty(id, fcx.expr_ty(&**a));
3623       }
3624       ast::ExprAssign(ref lhs, ref rhs) => {
3625         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3626
3627         let tcx = fcx.tcx();
3628         if !ty::expr_is_lval(tcx, &**lhs) {
3629             span_err!(tcx.sess, expr.span, E0070,
3630                 "illegal left-hand side expression");
3631         }
3632
3633         let lhs_ty = fcx.expr_ty(&**lhs);
3634         check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3635         let rhs_ty = fcx.expr_ty(&**rhs);
3636
3637         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3638
3639         if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3640             fcx.write_error(id);
3641         } else {
3642             fcx.write_nil(id);
3643         }
3644       }
3645       ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3646         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3647                         id, expr.span, expected);
3648       }
3649       ast::ExprIfLet(..) => {
3650         tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3651       }
3652       ast::ExprWhile(ref cond, ref body, _) => {
3653         check_expr_has_type(fcx, &**cond, tcx.types.bool);
3654         check_block_no_value(fcx, &**body);
3655         let cond_ty = fcx.expr_ty(&**cond);
3656         let body_ty = fcx.node_ty(body.id);
3657         if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3658             fcx.write_error(id);
3659         }
3660         else {
3661             fcx.write_nil(id);
3662         }
3663       }
3664       ast::ExprWhileLet(..) => {
3665         tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3666       }
3667       ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3668         check_expr(fcx, &**head);
3669         let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
3670         vtable::select_new_fcx_obligations(fcx);
3671
3672         debug!("ExprForLoop each item has type {}",
3673                fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
3674
3675         let pcx = pat_ctxt {
3676             fcx: fcx,
3677             map: pat_id_map(&tcx.def_map, &**pat),
3678         };
3679         _match::check_pat(&pcx, &**pat, typ);
3680
3681         check_block_no_value(fcx, &**block);
3682         fcx.write_nil(id);
3683       }
3684       ast::ExprLoop(ref body, _) => {
3685         check_block_no_value(fcx, &**body);
3686         if !may_break(tcx, expr.id, &**body) {
3687             fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3688         } else {
3689             fcx.write_nil(id);
3690         }
3691       }
3692       ast::ExprMatch(ref discrim, ref arms, match_src) => {
3693         _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3694       }
3695       ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3696           closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3697       }
3698       ast::ExprBlock(ref b) => {
3699         check_block_with_expected(fcx, &**b, expected);
3700         fcx.write_ty(id, fcx.node_ty(b.id));
3701       }
3702       ast::ExprCall(ref callee, ref args) => {
3703           callee::check_call(fcx, expr, &**callee, &args[], expected);
3704       }
3705       ast::ExprMethodCall(ident, ref tps, ref args) => {
3706         check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3707         let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3708         let  args_err = arg_tys.fold(false,
3709              |rest_err, a| {
3710               rest_err || ty::type_is_error(a)});
3711         if args_err {
3712             fcx.write_error(id);
3713         }
3714       }
3715       ast::ExprCast(ref e, ref t) => {
3716         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3717             check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3718         }
3719         check_cast(fcx, expr, &**e, &**t);
3720       }
3721       ast::ExprVec(ref args) => {
3722         let uty = expected.to_option(fcx).and_then(|uty| {
3723             match uty.sty {
3724                 ty::ty_vec(ty, _) => Some(ty),
3725                 _ => None
3726             }
3727         });
3728
3729         let typ = match uty {
3730             Some(uty) => {
3731                 for e in args.iter() {
3732                     check_expr_coercable_to_type(fcx, &**e, uty);
3733                 }
3734                 uty
3735             }
3736             None => {
3737                 let t: Ty = fcx.infcx().next_ty_var();
3738                 for e in args.iter() {
3739                     check_expr_has_type(fcx, &**e, t);
3740                 }
3741                 t
3742             }
3743         };
3744         let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3745         fcx.write_ty(id, typ);
3746       }
3747       ast::ExprRepeat(ref element, ref count_expr) => {
3748         check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3749         let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3750
3751         let uty = match expected {
3752             ExpectHasType(uty) => {
3753                 match uty.sty {
3754                     ty::ty_vec(ty, _) => Some(ty),
3755                     _ => None
3756                 }
3757             }
3758             _ => None
3759         };
3760
3761         let (element_ty, t) = match uty {
3762             Some(uty) => {
3763                 check_expr_coercable_to_type(fcx, &**element, uty);
3764                 (uty, uty)
3765             }
3766             None => {
3767                 let t: Ty = fcx.infcx().next_ty_var();
3768                 check_expr_has_type(fcx, &**element, t);
3769                 (fcx.expr_ty(&**element), t)
3770             }
3771         };
3772
3773         if count > 1 {
3774             // For [foo, ..n] where n > 1, `foo` must have
3775             // Copy type:
3776             fcx.require_type_meets(
3777                 t,
3778                 expr.span,
3779                 traits::RepeatVec,
3780                 ty::BoundCopy);
3781         }
3782
3783         if ty::type_is_error(element_ty) {
3784             fcx.write_error(id);
3785         } else {
3786             let t = ty::mk_vec(tcx, t, Some(count));
3787             fcx.write_ty(id, t);
3788         }
3789       }
3790       ast::ExprTup(ref elts) => {
3791         let flds = expected.only_has_type(fcx).and_then(|ty| {
3792             match ty.sty {
3793                 ty::ty_tup(ref flds) => Some(&flds[]),
3794                 _ => None
3795             }
3796         });
3797         let mut err_field = false;
3798
3799         let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3800             let t = match flds {
3801                 Some(ref fs) if i < fs.len() => {
3802                     let ety = fs[i];
3803                     check_expr_coercable_to_type(fcx, &**e, ety);
3804                     ety
3805                 }
3806                 _ => {
3807                     check_expr_with_expectation(fcx, &**e, NoExpectation);
3808                     fcx.expr_ty(&**e)
3809                 }
3810             };
3811             err_field = err_field || ty::type_is_error(t);
3812             t
3813         }).collect();
3814         if err_field {
3815             fcx.write_error(id);
3816         } else {
3817             let typ = ty::mk_tup(tcx, elt_ts);
3818             fcx.write_ty(id, typ);
3819         }
3820       }
3821       ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3822         // Resolve the path.
3823         let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3824         let struct_id = match def {
3825             Some(def::DefVariant(enum_id, variant_id, true)) => {
3826                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3827                                           variant_id, &fields[]);
3828                 enum_id
3829             }
3830             Some(def::DefTrait(def_id)) => {
3831                 span_err!(tcx.sess, path.span, E0159,
3832                     "use of trait `{}` as a struct constructor",
3833                     pprust::path_to_string(path));
3834                 check_struct_fields_on_error(fcx,
3835                                              id,
3836                                              &fields[],
3837                                              base_expr);
3838                 def_id
3839             },
3840             Some(def) => {
3841                 // Verify that this was actually a struct.
3842                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3843                 match typ.ty.sty {
3844                     ty::ty_struct(struct_did, _) => {
3845                         check_struct_constructor(fcx,
3846                                                  id,
3847                                                  expr.span,
3848                                                  struct_did,
3849                                                  &fields[],
3850                                                  base_expr.as_ref().map(|e| &**e));
3851                     }
3852                     _ => {
3853                         span_err!(tcx.sess, path.span, E0071,
3854                             "`{}` does not name a structure",
3855                             pprust::path_to_string(path));
3856                         check_struct_fields_on_error(fcx,
3857                                                      id,
3858                                                      &fields[],
3859                                                      base_expr);
3860                     }
3861                 }
3862
3863                 def.def_id()
3864             }
3865             _ => {
3866                 tcx.sess.span_bug(path.span,
3867                                   "structure constructor wasn't resolved")
3868             }
3869         };
3870
3871         // Turn the path into a type and verify that that type unifies with
3872         // the resulting structure type. This is needed to handle type
3873         // parameters correctly.
3874         let actual_structure_type = fcx.expr_ty(&*expr);
3875         if !ty::type_is_error(actual_structure_type) {
3876             let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3877             match fcx.mk_subty(false,
3878                                infer::Misc(path.span),
3879                                actual_structure_type,
3880                                type_and_substs.ty) {
3881                 Ok(()) => {}
3882                 Err(type_error) => {
3883                     let type_error_description =
3884                         ty::type_err_to_str(tcx, &type_error);
3885                     fcx.tcx()
3886                        .sess
3887                        .span_err(path.span,
3888                                  &format!("structure constructor specifies a \
3889                                          structure of type `{}`, but this \
3890                                          structure has type `{}`: {}",
3891                                          fcx.infcx()
3892                                             .ty_to_string(type_and_substs.ty),
3893                                          fcx.infcx()
3894                                             .ty_to_string(
3895                                                 actual_structure_type),
3896                                          type_error_description)[]);
3897                     ty::note_and_explain_type_err(tcx, &type_error);
3898                 }
3899             }
3900         }
3901
3902         fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3903       }
3904       ast::ExprField(ref base, ref field) => {
3905         check_field(fcx, expr, lvalue_pref, &**base, field);
3906       }
3907       ast::ExprTupField(ref base, idx) => {
3908         check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3909       }
3910       ast::ExprIndex(ref base, ref idx) => {
3911           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3912           let base_t = fcx.expr_ty(&**base);
3913           if ty::type_is_error(base_t) {
3914               fcx.write_ty(id, base_t);
3915           } else {
3916               check_expr(fcx, &**idx);
3917               let idx_t = fcx.expr_ty(&**idx);
3918               if ty::type_is_error(idx_t) {
3919                   fcx.write_ty(id, idx_t);
3920               } else {
3921                   let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3922
3923                   let result =
3924                       autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3925                           try_index_step(fcx,
3926                                          MethodCall::expr(expr.id),
3927                                          expr,
3928                                          &**base,
3929                                          adj_ty,
3930                                          adj,
3931                                          lvalue_pref,
3932                                          idx_t)
3933                       });
3934
3935                   match result {
3936                       Some((index_ty, element_ty)) => {
3937                           // FIXME: we've already checked idx above, we should
3938                           // probably just demand subtype or something here.
3939                           check_expr_has_type(fcx, &**idx, index_ty);
3940                           fcx.write_ty(id, element_ty);
3941                       }
3942                       _ => {
3943                           check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3944                           fcx.type_error_message(
3945                               expr.span,
3946                               |actual| {
3947                                   format!("cannot index a value of type `{}`",
3948                                           actual)
3949                               },
3950                               base_t,
3951                               None);
3952                           fcx.write_ty(id, fcx.tcx().types.err);
3953                       }
3954                   }
3955               }
3956           }
3957        }
3958        ast::ExprRange(ref start, ref end) => {
3959           let t_start = start.as_ref().map(|e| {
3960             check_expr(fcx, &**e);
3961             fcx.expr_ty(&**e)
3962           });
3963           let t_end = end.as_ref().map(|e| {
3964             check_expr(fcx, &**e);
3965             fcx.expr_ty(&**e)
3966           });
3967
3968           let idx_type = match (t_start, t_end) {
3969               (Some(ty), None) | (None, Some(ty)) => {
3970                   Some(ty)
3971               }
3972               (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3973                                                ty::type_is_error(t_end)) => {
3974                   Some(fcx.tcx().types.err)
3975               }
3976               (Some(t_start), Some(t_end)) => {
3977                   Some(infer::common_supertype(fcx.infcx(),
3978                                                infer::RangeExpression(expr.span),
3979                                                true,
3980                                                t_start,
3981                                                t_end))
3982               }
3983               _ => None
3984           };
3985
3986           // Note that we don't check the type of start/end satisfy any
3987           // bounds because right now the range structs do not have any. If we add
3988           // some bounds, then we'll need to check `t_start` against them here.
3989
3990           let range_type = match idx_type {
3991             Some(idx_type) if ty::type_is_error(idx_type) => {
3992                 fcx.tcx().types.err
3993             }
3994             Some(idx_type) => {
3995                 // Find the did from the appropriate lang item.
3996                 let did = match (start, end) {
3997                     (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3998                     (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3999                     (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4000                     (&None, &None) => {
4001                         tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4002                     }
4003                 };
4004
4005                 if let Some(did) = did {
4006                     let polytype = ty::lookup_item_type(tcx, did);
4007                     let substs = Substs::new_type(vec![idx_type], vec![]);
4008                     let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4009                     fcx.add_obligations_for_parameters(
4010                         traits::ObligationCause::new(expr.span,
4011                                                      fcx.body_id,
4012                                                      traits::ItemObligation(did)),
4013                         &bounds);
4014
4015                     ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4016                 } else {
4017                     tcx.sess.span_err(expr.span, "No lang item for range syntax");
4018                     fcx.tcx().types.err
4019                 }
4020             }
4021             None => {
4022                 // Neither start nor end => FullRange
4023                 if let Some(did) = tcx.lang_items.full_range_struct() {
4024                     let substs = Substs::new_type(vec![], vec![]);
4025                     ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4026                 } else {
4027                     tcx.sess.span_err(expr.span, "No lang item for range syntax");
4028                     fcx.tcx().types.err
4029                 }
4030             }
4031           };
4032
4033           fcx.write_ty(id, range_type);
4034        }
4035
4036     }
4037
4038     debug!("type of expr({}) {} is...", expr.id,
4039            syntax::print::pprust::expr_to_string(expr));
4040     debug!("... {}, expected is {}",
4041            ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4042            expected.repr(tcx));
4043
4044     unifier();
4045 }
4046
4047 fn constrain_path_type_parameters(fcx: &FnCtxt,
4048                                   expr: &ast::Expr)
4049 {
4050     fcx.opt_node_ty_substs(expr.id, |item_substs| {
4051         fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4052     });
4053 }
4054
4055 impl<'tcx> Expectation<'tcx> {
4056     /// Provide an expectation for an rvalue expression given an *optional*
4057     /// hint, which is not required for type safety (the resulting type might
4058     /// be checked higher up, as is the case with `&expr` and `box expr`), but
4059     /// is useful in determining the concrete type.
4060     ///
4061     /// The primary use case is where the expected type is a fat pointer,
4062     /// like `&[int]`. For example, consider the following statement:
4063     ///
4064     ///    let x: &[int] = &[1, 2, 3];
4065     ///
4066     /// In this case, the expected type for the `&[1, 2, 3]` expression is
4067     /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4068     /// expectation `ExpectHasType([int])`, that would be too strong --
4069     /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4070     /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4071     /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4072     /// which still is useful, because it informs integer literals and the like.
4073     /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4074     /// for examples of where this comes up,.
4075     fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4076         match ty.sty {
4077             ty::ty_vec(_, None) | ty::ty_trait(..) => {
4078                 ExpectRvalueLikeUnsized(ty)
4079             }
4080             _ => ExpectHasType(ty)
4081         }
4082     }
4083
4084     // Resolves `expected` by a single level if it is a variable. If
4085     // there is no expected type or resolution is not possible (e.g.,
4086     // no constraints yet present), just returns `None`.
4087     fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4088         match self {
4089             NoExpectation => {
4090                 NoExpectation
4091             }
4092             ExpectCastableToType(t) => {
4093                 ExpectCastableToType(
4094                     fcx.infcx().resolve_type_vars_if_possible(&t))
4095             }
4096             ExpectHasType(t) => {
4097                 ExpectHasType(
4098                     fcx.infcx().resolve_type_vars_if_possible(&t))
4099             }
4100             ExpectRvalueLikeUnsized(t) => {
4101                 ExpectRvalueLikeUnsized(
4102                     fcx.infcx().resolve_type_vars_if_possible(&t))
4103             }
4104         }
4105     }
4106
4107     fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4108         match self.resolve(fcx) {
4109             NoExpectation => None,
4110             ExpectCastableToType(ty) |
4111             ExpectHasType(ty) |
4112             ExpectRvalueLikeUnsized(ty) => Some(ty),
4113         }
4114     }
4115
4116     fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4117         match self.resolve(fcx) {
4118             ExpectHasType(ty) => Some(ty),
4119             _ => None
4120         }
4121     }
4122 }
4123
4124 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4125     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4126         match *self {
4127             NoExpectation => format!("NoExpectation"),
4128             ExpectHasType(t) => format!("ExpectHasType({})",
4129                                         t.repr(tcx)),
4130             ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4131                                                t.repr(tcx)),
4132             ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4133                                                   t.repr(tcx)),
4134         }
4135     }
4136 }
4137
4138 pub fn check_decl_initializer(fcx: &FnCtxt,
4139                               nid: ast::NodeId,
4140                               init: &ast::Expr)
4141 {
4142     let local_ty = fcx.local_ty(init.span, nid);
4143     check_expr_coercable_to_type(fcx, init, local_ty)
4144 }
4145
4146 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
4147     let tcx = fcx.ccx.tcx;
4148
4149     let t = fcx.local_ty(local.span, local.id);
4150     fcx.write_ty(local.id, t);
4151
4152     if let Some(ref init) = local.init {
4153         check_decl_initializer(fcx, local.id, &**init);
4154         let init_ty = fcx.expr_ty(&**init);
4155         if ty::type_is_error(init_ty) {
4156             fcx.write_ty(local.id, init_ty);
4157         }
4158     }
4159
4160     let pcx = pat_ctxt {
4161         fcx: fcx,
4162         map: pat_id_map(&tcx.def_map, &*local.pat),
4163     };
4164     _match::check_pat(&pcx, &*local.pat, t);
4165     let pat_ty = fcx.node_ty(local.pat.id);
4166     if ty::type_is_error(pat_ty) {
4167         fcx.write_ty(local.id, pat_ty);
4168     }
4169 }
4170
4171 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
4172     let node_id;
4173     let mut saw_bot = false;
4174     let mut saw_err = false;
4175     match stmt.node {
4176       ast::StmtDecl(ref decl, id) => {
4177         node_id = id;
4178         match decl.node {
4179           ast::DeclLocal(ref l) => {
4180               check_decl_local(fcx, &**l);
4181               let l_t = fcx.node_ty(l.id);
4182               saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4183               saw_err = saw_err || ty::type_is_error(l_t);
4184           }
4185           ast::DeclItem(_) => {/* ignore for now */ }
4186         }
4187       }
4188       ast::StmtExpr(ref expr, id) => {
4189         node_id = id;
4190         // Check with expected type of ()
4191         check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4192         let expr_ty = fcx.expr_ty(&**expr);
4193         saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4194         saw_err = saw_err || ty::type_is_error(expr_ty);
4195       }
4196       ast::StmtSemi(ref expr, id) => {
4197         node_id = id;
4198         check_expr(fcx, &**expr);
4199         let expr_ty = fcx.expr_ty(&**expr);
4200         saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4201         saw_err |= ty::type_is_error(expr_ty);
4202       }
4203       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4204     }
4205     if saw_bot {
4206         fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4207     }
4208     else if saw_err {
4209         fcx.write_error(node_id);
4210     }
4211     else {
4212         fcx.write_nil(node_id)
4213     }
4214 }
4215
4216 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
4217     check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4218     let blkty = fcx.node_ty(blk.id);
4219     if ty::type_is_error(blkty) {
4220         fcx.write_error(blk.id);
4221     } else {
4222         let nilty = ty::mk_nil(fcx.tcx());
4223         demand::suptype(fcx, blk.span, nilty, blkty);
4224     }
4225 }
4226
4227 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4228                                        blk: &ast::Block,
4229                                        expected: Expectation<'tcx>) {
4230     let prev = {
4231         let mut fcx_ps = fcx.ps.borrow_mut();
4232         let unsafety_state = fcx_ps.recurse(blk);
4233         replace(&mut *fcx_ps, unsafety_state)
4234     };
4235
4236     let mut warned = false;
4237     let mut any_diverges = false;
4238     let mut any_err = false;
4239     for s in blk.stmts.iter() {
4240         check_stmt(fcx, &**s);
4241         let s_id = ast_util::stmt_id(&**s);
4242         let s_ty = fcx.node_ty(s_id);
4243         if any_diverges && !warned && match s.node {
4244             ast::StmtDecl(ref decl, _) => {
4245                 match decl.node {
4246                     ast::DeclLocal(_) => true,
4247                     _ => false,
4248                 }
4249             }
4250             ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4251             _ => false
4252         } {
4253             fcx.ccx
4254                 .tcx
4255                 .sess
4256                 .add_lint(lint::builtin::UNREACHABLE_CODE,
4257                           s_id,
4258                           s.span,
4259                           "unreachable statement".to_string());
4260             warned = true;
4261         }
4262         any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4263         any_err = any_err || ty::type_is_error(s_ty);
4264     }
4265     match blk.expr {
4266         None => if any_err {
4267             fcx.write_error(blk.id);
4268         } else if any_diverges {
4269             fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4270         } else {
4271             fcx.write_nil(blk.id);
4272         },
4273         Some(ref e) => {
4274             if any_diverges && !warned {
4275                 fcx.ccx
4276                     .tcx
4277                     .sess
4278                     .add_lint(lint::builtin::UNREACHABLE_CODE,
4279                               e.id,
4280                               e.span,
4281                               "unreachable expression".to_string());
4282             }
4283             let ety = match expected {
4284                 ExpectHasType(ety) => {
4285                     check_expr_coercable_to_type(fcx, &**e, ety);
4286                     ety
4287                 }
4288                 _ => {
4289                     check_expr_with_expectation(fcx, &**e, expected);
4290                     fcx.expr_ty(&**e)
4291                 }
4292             };
4293
4294             if any_err {
4295                 fcx.write_error(blk.id);
4296             } else if any_diverges {
4297                 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4298             } else {
4299                 fcx.write_ty(blk.id, ety);
4300             }
4301         }
4302     };
4303
4304     *fcx.ps.borrow_mut() = prev;
4305 }
4306
4307 /// Checks a constant appearing in a type. At the moment this is just the
4308 /// length expression in a fixed-length vector, but someday it might be
4309 /// extended to type-level numeric literals.
4310 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4311                                 expr: &ast::Expr,
4312                                 expected_type: Ty<'tcx>) {
4313     let inh = static_inherited_fields(ccx);
4314     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4315     check_const_with_ty(&fcx, expr.span, expr, expected_type);
4316 }
4317
4318 fn check_const(ccx: &CrateCtxt,
4319                sp: Span,
4320                e: &ast::Expr,
4321                id: ast::NodeId) {
4322     let inh = static_inherited_fields(ccx);
4323     let rty = ty::node_id_to_type(ccx.tcx, id);
4324     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4325     let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4326     check_const_with_ty(&fcx, sp, e, declty);
4327 }
4328
4329 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4330                                  _: Span,
4331                                  e: &ast::Expr,
4332                                  declty: Ty<'tcx>) {
4333     // Gather locals in statics (because of block expressions).
4334     // This is technically unnecessary because locals in static items are forbidden,
4335     // but prevents type checking from blowing up before const checking can properly
4336     // emit a error.
4337     GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4338
4339     check_expr_with_hint(fcx, e, declty);
4340     demand::coerce(fcx, e.span, declty, e);
4341     vtable::select_all_fcx_obligations_or_error(fcx);
4342     regionck::regionck_expr(fcx, e);
4343     writeback::resolve_type_vars_in_expr(fcx, e);
4344 }
4345
4346 /// Checks whether a type can be represented in memory. In particular, it
4347 /// identifies types that contain themselves without indirection through a
4348 /// pointer, which would mean their size is unbounded. This is different from
4349 /// the question of whether a type can be instantiated. See the definition of
4350 /// `check_instantiable`.
4351 pub fn check_representable(tcx: &ty::ctxt,
4352                            sp: Span,
4353                            item_id: ast::NodeId,
4354                            designation: &str) -> bool {
4355     let rty = ty::node_id_to_type(tcx, item_id);
4356
4357     // Check that it is possible to represent this type. This call identifies
4358     // (1) types that contain themselves and (2) types that contain a different
4359     // recursive type. It is only necessary to throw an error on those that
4360     // contain themselves. For case 2, there must be an inner type that will be
4361     // caught by case 1.
4362     match ty::is_type_representable(tcx, sp, rty) {
4363       ty::SelfRecursive => {
4364         span_err!(tcx.sess, sp, E0072,
4365             "illegal recursive {} type; \
4366              wrap the inner value in a box to make it representable",
4367             designation);
4368         return false
4369       }
4370       ty::Representable | ty::ContainsRecursive => (),
4371     }
4372     return true
4373 }
4374
4375 /// Checks whether a type can be created without an instance of itself.
4376 /// This is similar but different from the question of whether a type
4377 /// can be represented.  For example, the following type:
4378 ///
4379 ///     enum foo { None, Some(foo) }
4380 ///
4381 /// is instantiable but is not representable.  Similarly, the type
4382 ///
4383 ///     enum foo { Some(@foo) }
4384 ///
4385 /// is representable, but not instantiable.
4386 pub fn check_instantiable(tcx: &ty::ctxt,
4387                           sp: Span,
4388                           item_id: ast::NodeId)
4389                           -> bool {
4390     let item_ty = ty::node_id_to_type(tcx, item_id);
4391     if !ty::is_instantiable(tcx, item_ty) {
4392         span_err!(tcx.sess, sp, E0073,
4393             "this type cannot be instantiated without an \
4394              instance of itself");
4395         span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4396             ppaux::ty_to_string(tcx, item_ty));
4397         false
4398     } else {
4399         true
4400     }
4401 }
4402
4403 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4404     let t = ty::node_id_to_type(tcx, id);
4405     if ty::type_needs_subst(t) {
4406         span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4407         return;
4408     }
4409     match t.sty {
4410         ty::ty_struct(did, substs) => {
4411             let fields = ty::lookup_struct_fields(tcx, did);
4412             if fields.is_empty() {
4413                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4414                 return;
4415             }
4416             let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4417             if !fields.iter().all(
4418                          |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4419                 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4420                 return;
4421             }
4422             if !ty::type_is_machine(e) {
4423                 span_err!(tcx.sess, sp, E0077,
4424                     "SIMD vector element type should be machine type");
4425                 return;
4426             }
4427         }
4428         _ => ()
4429     }
4430 }
4431
4432 pub fn check_enum_variants(ccx: &CrateCtxt,
4433                            sp: Span,
4434                            vs: &[P<ast::Variant>],
4435                            id: ast::NodeId) {
4436
4437     fn disr_in_range(ccx: &CrateCtxt,
4438                      ty: attr::IntType,
4439                      disr: ty::Disr) -> bool {
4440         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4441             match ty {
4442                 ast::TyU8 => disr as u8 as Disr == disr,
4443                 ast::TyU16 => disr as u16 as Disr == disr,
4444                 ast::TyU32 => disr as u32 as Disr == disr,
4445                 ast::TyU64 => disr as u64 as Disr == disr,
4446                 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4447             }
4448         }
4449         fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4450             match ty {
4451                 ast::TyI8 => disr as i8 as Disr == disr,
4452                 ast::TyI16 => disr as i16 as Disr == disr,
4453                 ast::TyI32 => disr as i32 as Disr == disr,
4454                 ast::TyI64 => disr as i64 as Disr == disr,
4455                 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4456             }
4457         }
4458         match ty {
4459             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4460             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4461         }
4462     }
4463
4464     fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4465                           vs: &[P<ast::Variant>],
4466                           id: ast::NodeId,
4467                           hint: attr::ReprAttr)
4468                           -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4469
4470         let rty = ty::node_id_to_type(ccx.tcx, id);
4471         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4472         let mut disr_vals: Vec<ty::Disr> = Vec::new();
4473         let mut prev_disr_val: Option<ty::Disr> = None;
4474
4475         for v in vs.iter() {
4476
4477             // If the discriminant value is specified explicitly in the enum check whether the
4478             // initialization expression is valid, otherwise use the last value plus one.
4479             let mut current_disr_val = match prev_disr_val {
4480                 Some(prev_disr_val) => prev_disr_val + 1,
4481                 None => ty::INITIAL_DISCRIMINANT_VALUE
4482             };
4483
4484             match v.node.disr_expr {
4485                 Some(ref e) => {
4486                     debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4487
4488                     let inh = static_inherited_fields(ccx);
4489                     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4490                     let declty = match hint {
4491                         attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4492                         attr::ReprInt(_, attr::SignedInt(ity)) => {
4493                             ty::mk_mach_int(fcx.tcx(), ity)
4494                         }
4495                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4496                             ty::mk_mach_uint(fcx.tcx(), ity)
4497                         },
4498                     };
4499                     check_const_with_ty(&fcx, e.span, &**e, declty);
4500                     // check_expr (from check_const pass) doesn't guarantee
4501                     // that the expression is in a form that eval_const_expr can
4502                     // handle, so we may still get an internal compiler error
4503
4504                     match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4505                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4506                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4507                         Ok(_) => {
4508                             span_err!(ccx.tcx.sess, e.span, E0079,
4509                                 "expected signed integer constant");
4510                         }
4511                         Err(ref err) => {
4512                             span_err!(ccx.tcx.sess, e.span, E0080,
4513                                 "expected constant: {}", *err);
4514                         }
4515                     }
4516                 },
4517                 None => ()
4518             };
4519
4520             // Check for duplicate discriminant values
4521             match disr_vals.iter().position(|&x| x == current_disr_val) {
4522                 Some(i) => {
4523                     span_err!(ccx.tcx.sess, v.span, E0081,
4524                         "discriminant value `{}` already exists", disr_vals[i]);
4525                     span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4526                         "conflicting discriminant here")
4527                 }
4528                 None => {}
4529             }
4530             // Check for unrepresentable discriminant values
4531             match hint {
4532                 attr::ReprAny | attr::ReprExtern => (),
4533                 attr::ReprInt(sp, ity) => {
4534                     if !disr_in_range(ccx, ity, current_disr_val) {
4535                         span_err!(ccx.tcx.sess, v.span, E0082,
4536                             "discriminant value outside specified type");
4537                         span_note!(ccx.tcx.sess, sp,
4538                             "discriminant type specified here");
4539                     }
4540                 }
4541                 attr::ReprPacked => {
4542                     ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4543                 }
4544             }
4545             disr_vals.push(current_disr_val);
4546
4547             let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4548                                                                      current_disr_val));
4549             prev_disr_val = Some(current_disr_val);
4550
4551             variants.push(variant_info);
4552         }
4553
4554         return variants;
4555     }
4556
4557     let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4558         [].get(0).unwrap_or(&attr::ReprAny);
4559
4560     if hint != attr::ReprAny && vs.len() <= 1 {
4561         if vs.len() == 1 {
4562             span_err!(ccx.tcx.sess, sp, E0083,
4563                 "unsupported representation for univariant enum");
4564         } else {
4565             span_err!(ccx.tcx.sess, sp, E0084,
4566                 "unsupported representation for zero-variant enum");
4567         };
4568     }
4569
4570     let variants = do_check(ccx, vs, id, hint);
4571
4572     // cache so that ty::enum_variants won't repeat this work
4573     ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4574
4575     check_representable(ccx.tcx, sp, id, "enum");
4576
4577     // Check that it is possible to instantiate this enum:
4578     //
4579     // This *sounds* like the same that as representable, but it's
4580     // not.  See def'n of `check_instantiable()` for details.
4581     check_instantiable(ccx.tcx, sp, id);
4582 }
4583
4584 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4585     lookup_def_ccx(fcx.ccx, sp, id)
4586 }
4587
4588 // Returns the type parameter count and the type for the given definition.
4589 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4590                                      sp: Span,
4591                                      defn: def::Def)
4592                                      -> TypeScheme<'tcx> {
4593     match defn {
4594       def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4595           let typ = fcx.local_ty(sp, nid);
4596           return no_params(typ);
4597       }
4598       def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4599       def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4600       def::DefStruct(id) | def::DefConst(id) => {
4601         return ty::lookup_item_type(fcx.ccx.tcx, id);
4602       }
4603       def::DefTrait(_) |
4604       def::DefTy(..) |
4605       def::DefAssociatedTy(..) |
4606       def::DefAssociatedPath(..) |
4607       def::DefPrimTy(_) |
4608       def::DefTyParam(..) => {
4609         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4610       }
4611       def::DefMod(..) | def::DefForeignMod(..) => {
4612         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4613       }
4614       def::DefUse(..) => {
4615         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4616       }
4617       def::DefRegion(..) => {
4618         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4619       }
4620       def::DefTyParamBinder(..) => {
4621         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4622       }
4623       def::DefLabel(..) => {
4624         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4625       }
4626       def::DefSelfTy(..) => {
4627         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4628       }
4629     }
4630 }
4631
4632 // Instantiates the given path, which must refer to an item with the given
4633 // number of type parameters and type.
4634 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4635                                   path: &ast::Path,
4636                                   type_scheme: TypeScheme<'tcx>,
4637                                   opt_self_ty: Option<Ty<'tcx>>,
4638                                   def: def::Def,
4639                                   span: Span,
4640                                   node_id: ast::NodeId) {
4641     debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4642            path.repr(fcx.tcx()),
4643            def.repr(fcx.tcx()),
4644            node_id,
4645            type_scheme.repr(fcx.tcx()));
4646
4647     // We need to extract the type parameters supplied by the user in
4648     // the path `path`. Due to the current setup, this is a bit of a
4649     // tricky-process; the problem is that resolve only tells us the
4650     // end-point of the path resolution, and not the intermediate steps.
4651     // Luckily, we can (at least for now) deduce the intermediate steps
4652     // just from the end-point.
4653     //
4654     // There are basically three cases to consider:
4655     //
4656     // 1. Reference to a *type*, such as a struct or enum:
4657     //
4658     //        mod a { struct Foo<T> { ... } }
4659     //
4660     //    Because we don't allow types to be declared within one
4661     //    another, a path that leads to a type will always look like
4662     //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
4663     //    that only the final segment can have type parameters, and
4664     //    they are located in the TypeSpace.
4665     //
4666     //    *Note:* Generally speaking, references to types don't
4667     //    actually pass through this function, but rather the
4668     //    `ast_ty_to_ty` function in `astconv`. However, in the case
4669     //    of struct patterns (and maybe literals) we do invoke
4670     //    `instantiate_path` to get the general type of an instance of
4671     //    a struct. (In these cases, there are actually no type
4672     //    parameters permitted at present, but perhaps we will allow
4673     //    them in the future.)
4674     //
4675     // 1b. Reference to a enum variant or tuple-like struct:
4676     //
4677     //        struct foo<T>(...)
4678     //        enum E<T> { foo(...) }
4679     //
4680     //    In these cases, the parameters are declared in the type
4681     //    space.
4682     //
4683     // 2. Reference to a *fn item*:
4684     //
4685     //        fn foo<T>() { }
4686     //
4687     //    In this case, the path will again always have the form
4688     //    `a::b::foo::<T>` where only the final segment should have
4689     //    type parameters. However, in this case, those parameters are
4690     //    declared on a value, and hence are in the `FnSpace`.
4691     //
4692     // 3. Reference to a *method*:
4693     //
4694     //        impl<A> SomeStruct<A> {
4695     //            fn foo<B>(...)
4696     //        }
4697     //
4698     //    Here we can have a path like
4699     //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4700     //    may appear in two places. The penultimate segment,
4701     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4702     //    final segment, `foo::<B>` contains parameters in fn space.
4703     //
4704     // The first step then is to categorize the segments appropriately.
4705
4706     assert!(path.segments.len() >= 1);
4707     let mut segment_spaces: Vec<_>;
4708     match def {
4709         // Case 1 and 1b. Reference to a *type* or *enum variant*.
4710         def::DefSelfTy(..) |
4711         def::DefStruct(..) |
4712         def::DefVariant(..) |
4713         def::DefTyParamBinder(..) |
4714         def::DefTy(..) |
4715         def::DefAssociatedTy(..) |
4716         def::DefAssociatedPath(..) |
4717         def::DefTrait(..) |
4718         def::DefPrimTy(..) |
4719         def::DefTyParam(..) => {
4720             // Everything but the final segment should have no
4721             // parameters at all.
4722             segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4723             segment_spaces.push(Some(subst::TypeSpace));
4724         }
4725
4726         // Case 2. Reference to a top-level value.
4727         def::DefFn(..) |
4728         def::DefConst(..) |
4729         def::DefStatic(..) => {
4730             segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4731             segment_spaces.push(Some(subst::FnSpace));
4732         }
4733
4734         // Case 3. Reference to a method.
4735         def::DefStaticMethod(_, providence) |
4736         def::DefMethod(_, _, providence) => {
4737             assert!(path.segments.len() >= 2);
4738
4739             match providence {
4740                 def::FromTrait(trait_did) => {
4741                     callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4742                 }
4743                 def::FromImpl(_) => {}
4744             }
4745
4746             segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4747             segment_spaces.push(Some(subst::TypeSpace));
4748             segment_spaces.push(Some(subst::FnSpace));
4749         }
4750
4751         // Other cases. Various nonsense that really shouldn't show up
4752         // here. If they do, an error will have been reported
4753         // elsewhere. (I hope)
4754         def::DefMod(..) |
4755         def::DefForeignMod(..) |
4756         def::DefLocal(..) |
4757         def::DefUse(..) |
4758         def::DefRegion(..) |
4759         def::DefLabel(..) |
4760         def::DefUpvar(..) => {
4761             segment_spaces = repeat(None).take(path.segments.len()).collect();
4762         }
4763     }
4764     assert_eq!(segment_spaces.len(), path.segments.len());
4765
4766     debug!("segment_spaces={:?}", segment_spaces);
4767
4768     // Next, examine the definition, and determine how many type
4769     // parameters we expect from each space.
4770     let type_defs = &type_scheme.generics.types;
4771     let region_defs = &type_scheme.generics.regions;
4772
4773     // Now that we have categorized what space the parameters for each
4774     // segment belong to, let's sort out the parameters that the user
4775     // provided (if any) into their appropriate spaces. We'll also report
4776     // errors if type parameters are provided in an inappropriate place.
4777     let mut substs = Substs::empty();
4778     for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4779         match *opt_space {
4780             None => {
4781                 report_error_if_segment_contains_type_parameters(fcx, segment);
4782             }
4783
4784             Some(space) => {
4785                 push_explicit_parameters_from_segment_to_substs(fcx,
4786                                                                 space,
4787                                                                 path.span,
4788                                                                 type_defs,
4789                                                                 region_defs,
4790                                                                 segment,
4791                                                                 &mut substs);
4792             }
4793         }
4794     }
4795     if let Some(self_ty) = opt_self_ty {
4796         // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4797         assert_eq!(type_defs.len(subst::SelfSpace), 1);
4798         substs.types.push(subst::SelfSpace, self_ty);
4799     }
4800
4801     // Now we have to compare the types that the user *actually*
4802     // provided against the types that were *expected*. If the user
4803     // did not provide any types, then we want to substitute inference
4804     // variables. If the user provided some types, we may still need
4805     // to add defaults. If the user provided *too many* types, that's
4806     // a problem.
4807     for &space in ParamSpace::all().iter() {
4808         adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4809         assert_eq!(substs.types.len(space), type_defs.len(space));
4810
4811         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4812         assert_eq!(substs.regions().len(space), region_defs.len(space));
4813     }
4814
4815     // The things we are substituting into the type should not contain
4816     // escaping late-bound regions, and nor should the base type scheme.
4817     assert!(!substs.has_regions_escaping_depth(0));
4818     assert!(!type_scheme.has_escaping_regions());
4819
4820     // Add all the obligations that are required, substituting and
4821     // normalized appropriately.
4822     let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4823     fcx.add_obligations_for_parameters(
4824         traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4825         &bounds);
4826
4827     // Substitute the values for the type parameters into the type of
4828     // the referenced item.
4829     let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4830
4831     fcx.write_ty(node_id, ty_substituted);
4832     fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4833     return;
4834
4835     fn report_error_if_segment_contains_type_parameters(
4836         fcx: &FnCtxt,
4837         segment: &ast::PathSegment)
4838     {
4839         for typ in segment.parameters.types().iter() {
4840             span_err!(fcx.tcx().sess, typ.span, E0085,
4841                 "type parameters may not appear here");
4842             break;
4843         }
4844
4845         for lifetime in segment.parameters.lifetimes().iter() {
4846             span_err!(fcx.tcx().sess, lifetime.span, E0086,
4847                 "lifetime parameters may not appear here");
4848             break;
4849         }
4850     }
4851
4852     /// Finds the parameters that the user provided and adds them to `substs`. If too many
4853     /// parameters are provided, then reports an error and clears the output vector.
4854     ///
4855     /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4856     /// use inference variables. This seems less likely to lead to derived errors.
4857     ///
4858     /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4859     /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4860     /// here because we can easily use the precise span of the N+1'th parameter.
4861     fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4862         fcx: &FnCtxt<'a, 'tcx>,
4863         space: subst::ParamSpace,
4864         span: Span,
4865         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4866         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4867         segment: &ast::PathSegment,
4868         substs: &mut Substs<'tcx>)
4869     {
4870         match segment.parameters {
4871             ast::AngleBracketedParameters(ref data) => {
4872                 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4873                     fcx, space, type_defs, region_defs, data, substs);
4874             }
4875
4876             ast::ParenthesizedParameters(ref data) => {
4877                 fcx.tcx().sess.span_err(
4878                     span,
4879                     "parenthesized parameters may only be used with a trait");
4880                 push_explicit_parenthesized_parameters_from_segment_to_substs(
4881                     fcx, space, span, type_defs, data, substs);
4882             }
4883         }
4884     }
4885
4886     fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4887         fcx: &FnCtxt<'a, 'tcx>,
4888         space: subst::ParamSpace,
4889         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4890         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4891         data: &ast::AngleBracketedParameterData,
4892         substs: &mut Substs<'tcx>)
4893     {
4894         {
4895             let type_count = type_defs.len(space);
4896             assert_eq!(substs.types.len(space), 0);
4897             for (i, typ) in data.types.iter().enumerate() {
4898                 let t = fcx.to_ty(&**typ);
4899                 if i < type_count {
4900                     substs.types.push(space, t);
4901                 } else if i == type_count {
4902                     span_err!(fcx.tcx().sess, typ.span, E0087,
4903                         "too many type parameters provided: \
4904                          expected at most {} parameter(s), \
4905                          found {} parameter(s)",
4906                          type_count, data.types.len());
4907                     substs.types.truncate(space, 0);
4908                     break;
4909                 }
4910             }
4911         }
4912
4913         if data.bindings.len() > 0 {
4914             span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4915                       "unexpected binding of associated item in expression path \
4916                        (only allowed in type paths)");
4917         }
4918
4919         {
4920             let region_count = region_defs.len(space);
4921             assert_eq!(substs.regions().len(space), 0);
4922             for (i, lifetime) in data.lifetimes.iter().enumerate() {
4923                 let r = ast_region_to_region(fcx.tcx(), lifetime);
4924                 if i < region_count {
4925                     substs.mut_regions().push(space, r);
4926                 } else if i == region_count {
4927                     span_err!(fcx.tcx().sess, lifetime.span, E0088,
4928                         "too many lifetime parameters provided: \
4929                          expected {} parameter(s), found {} parameter(s)",
4930                         region_count,
4931                         data.lifetimes.len());
4932                     substs.mut_regions().truncate(space, 0);
4933                     break;
4934                 }
4935             }
4936         }
4937     }
4938
4939     /// As with
4940     /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4941     /// but intended for `Foo(A,B) -> C` form. This expands to
4942     /// roughly the same thing as `Foo<(A,B),C>`. One important
4943     /// difference has to do with the treatment of anonymous
4944     /// regions, which are translated into bound regions (NYI).
4945     fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4946         fcx: &FnCtxt<'a, 'tcx>,
4947         space: subst::ParamSpace,
4948         span: Span,
4949         type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4950         data: &ast::ParenthesizedParameterData,
4951         substs: &mut Substs<'tcx>)
4952     {
4953         let type_count = type_defs.len(space);
4954         if type_count < 2 {
4955             span_err!(fcx.tcx().sess, span, E0167,
4956                       "parenthesized form always supplies 2 type parameters, \
4957                       but only {} parameter(s) were expected",
4958                       type_count);
4959         }
4960
4961         let input_tys: Vec<Ty> =
4962             data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4963
4964         let tuple_ty =
4965             ty::mk_tup(fcx.tcx(), input_tys);
4966
4967         if type_count >= 1 {
4968             substs.types.push(space, tuple_ty);
4969         }
4970
4971         let output_ty: Option<Ty> =
4972             data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4973
4974         let output_ty =
4975             output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4976
4977         if type_count >= 2 {
4978             substs.types.push(space, output_ty);
4979         }
4980     }
4981
4982     fn adjust_type_parameters<'a, 'tcx>(
4983         fcx: &FnCtxt<'a, 'tcx>,
4984         span: Span,
4985         space: ParamSpace,
4986         defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4987         substs: &mut Substs<'tcx>)
4988     {
4989         let provided_len = substs.types.len(space);
4990         let desired = defs.get_slice(space);
4991         let required_len = desired.iter()
4992                               .take_while(|d| d.default.is_none())
4993                               .count();
4994
4995         debug!("adjust_type_parameters(space={:?}, \
4996                provided_len={}, \
4997                desired_len={}, \
4998                required_len={})",
4999                space,
5000                provided_len,
5001                desired.len(),
5002                required_len);
5003
5004         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5005         assert!(provided_len <= desired.len());
5006
5007         // Nothing specified at all: supply inference variables for
5008         // everything.
5009         if provided_len == 0 {
5010             substs.types.replace(space,
5011                                  fcx.infcx().next_ty_vars(desired.len()));
5012             return;
5013         }
5014
5015         // Too few parameters specified: report an error and use Err
5016         // for everything.
5017         if provided_len < required_len {
5018             let qualifier =
5019                 if desired.len() != required_len { "at least " } else { "" };
5020             span_err!(fcx.tcx().sess, span, E0089,
5021                 "too few type parameters provided: expected {}{} parameter(s) \
5022                 , found {} parameter(s)",
5023                 qualifier, required_len, provided_len);
5024             substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5025             return;
5026         }
5027
5028         // Otherwise, add in any optional parameters that the user
5029         // omitted. The case of *too many* parameters is handled
5030         // already by
5031         // push_explicit_parameters_from_segment_to_substs(). Note
5032         // that the *default* type are expressed in terms of all prior
5033         // parameters, so we have to substitute as we go with the
5034         // partial substitution that we have built up.
5035         for i in range(provided_len, desired.len()) {
5036             let default = desired[i].default.unwrap();
5037             let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5038             substs.types.push(space, default);
5039         }
5040         assert_eq!(substs.types.len(space), desired.len());
5041
5042         debug!("Final substs: {}", substs.repr(fcx.tcx()));
5043     }
5044
5045     fn adjust_region_parameters(
5046         fcx: &FnCtxt,
5047         span: Span,
5048         space: ParamSpace,
5049         defs: &VecPerParamSpace<ty::RegionParameterDef>,
5050         substs: &mut Substs)
5051     {
5052         let provided_len = substs.mut_regions().len(space);
5053         let desired = defs.get_slice(space);
5054
5055         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5056         assert!(provided_len <= desired.len());
5057
5058         // If nothing was provided, just use inference variables.
5059         if provided_len == 0 {
5060             substs.mut_regions().replace(
5061                 space,
5062                 fcx.infcx().region_vars_for_defs(span, desired));
5063             return;
5064         }
5065
5066         // If just the right number were provided, everybody is happy.
5067         if provided_len == desired.len() {
5068             return;
5069         }
5070
5071         // Otherwise, too few were provided. Report an error and then
5072         // use inference variables.
5073         span_err!(fcx.tcx().sess, span, E0090,
5074             "too few lifetime parameters provided: expected {} parameter(s), \
5075              found {} parameter(s)",
5076             desired.len(), provided_len);
5077
5078         substs.mut_regions().replace(
5079             space,
5080             fcx.infcx().region_vars_for_defs(span, desired));
5081     }
5082 }
5083
5084 // Resolves `typ` by a single level if `typ` is a type variable.  If no
5085 // resolution is possible, then an error is reported.
5086 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5087                                             mut ty: Ty<'tcx>) -> Ty<'tcx> {
5088     // If `ty` is a type variable, see whether we already know what it is.
5089     ty = fcx.infcx().shallow_resolve(ty);
5090
5091     // If not, try resolve pending fcx obligations. Those can shed light.
5092     //
5093     // FIXME(#18391) -- This current strategy can lead to bad performance in
5094     // extreme cases.  We probably ought to smarter in general about
5095     // only resolving when we need help and only resolving obligations
5096     // will actually help.
5097     if ty::type_is_ty_var(ty) {
5098         vtable::select_fcx_obligations_where_possible(fcx);
5099         ty = fcx.infcx().shallow_resolve(ty);
5100     }
5101
5102     // If not, error.
5103     if ty::type_is_ty_var(ty) {
5104         fcx.type_error_message(sp, |_actual| {
5105             "the type of this value must be known in this \
5106              context".to_string()
5107         }, ty, None);
5108         demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5109         ty = fcx.tcx().types.err;
5110     }
5111
5112     ty
5113 }
5114
5115 // Returns true if b contains a break that can exit from b
5116 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5117     // First: is there an unlabeled break immediately
5118     // inside the loop?
5119     (loop_query(&*b, |e| {
5120         match *e {
5121             ast::ExprBreak(_) => true,
5122             _ => false
5123         }
5124     })) ||
5125    // Second: is there a labeled break with label
5126    // <id> nested anywhere inside the loop?
5127     (block_query(b, |e| {
5128         match e.node {
5129             ast::ExprBreak(Some(_)) => {
5130                 match cx.def_map.borrow().get(&e.id) {
5131                     Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5132                     _ => false,
5133                 }
5134             }
5135             _ => false
5136         }}))
5137 }
5138
5139 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5140                                        span: Span,
5141                                        tps: &OwnedSlice<ast::TyParam>,
5142                                        ty: Ty<'tcx>) {
5143     debug!("check_bounds_are_used(n_tps={}, ty={})",
5144            tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5145
5146     // make a vector of booleans initially false, set to true when used
5147     if tps.len() == 0u { return; }
5148     let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5149
5150     ty::walk_ty(ty, |t| {
5151             match t.sty {
5152                 ty::ty_param(ParamTy {idx, ..}) => {
5153                     debug!("Found use of ty param num {}", idx);
5154                     tps_used[idx as uint] = true;
5155                 }
5156                 _ => ()
5157             }
5158         });
5159
5160     for (i, b) in tps_used.iter().enumerate() {
5161         if !*b {
5162             span_err!(ccx.tcx.sess, span, E0091,
5163                 "type parameter `{}` is unused",
5164                 token::get_ident(tps[i].ident));
5165         }
5166     }
5167 }
5168
5169 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5170     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5171         let name = token::intern(format!("P{}", n).as_slice());
5172         ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5173     }
5174
5175     let tcx = ccx.tcx;
5176     let name = token::get_ident(it.ident);
5177     let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5178         let split : Vec<&str> = name.get().split('_').collect();
5179         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5180
5181         //We only care about the operation here
5182         let (n_tps, inputs, output) = match split[1] {
5183             "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5184                                 param(ccx, 0),
5185                                 param(ccx, 0)),
5186                         param(ccx, 0)),
5187             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5188                        param(ccx, 0)),
5189             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5190                         ty::mk_nil(tcx)),
5191
5192             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
5193             "min"  | "umax" | "umin" => {
5194                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5195                  param(ccx, 0))
5196             }
5197             "fence" => {
5198                 (0, Vec::new(), ty::mk_nil(tcx))
5199             }
5200             op => {
5201                 span_err!(tcx.sess, it.span, E0092,
5202                     "unrecognized atomic operation function: `{}`", op);
5203                 return;
5204             }
5205         };
5206         (n_tps, inputs, ty::FnConverging(output))
5207     } else if name.get() == "abort" || name.get() == "unreachable" {
5208         (0, Vec::new(), ty::FnDiverging)
5209     } else {
5210         let (n_tps, inputs, output) = match name.get() {
5211             "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5212             "size_of" |
5213             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5214             "init" => (1u, Vec::new(), param(ccx, 0)),
5215             "uninit" => (1u, Vec::new(), param(ccx, 0)),
5216             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5217             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5218             "move_val_init" => {
5219                 (1u,
5220                  vec!(
5221                     ty::mk_mut_rptr(tcx,
5222                                     tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5223                                                                   ty::BrAnon(0))),
5224                                     param(ccx, 0)),
5225                     param(ccx, 0)
5226                   ),
5227                ty::mk_nil(tcx))
5228             }
5229             "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5230             "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5231
5232             "get_tydesc" => {
5233               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5234                   Ok(t) => t,
5235                   Err(s) => { tcx.sess.span_fatal(it.span, &s[]); }
5236               };
5237               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5238                   ty: tydesc_ty,
5239                   mutbl: ast::MutImmutable
5240               });
5241               (1u, Vec::new(), td_ptr)
5242             }
5243             "type_id" => {
5244                 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5245                 match langid {
5246                     Ok(did) => (1u,
5247                                 Vec::new(),
5248                                 ty::mk_struct(ccx.tcx, did,
5249                                               ccx.tcx.mk_substs(subst::Substs::empty()))),
5250                     Err(msg) => {
5251                         tcx.sess.span_fatal(it.span, &msg[]);
5252                     }
5253                 }
5254             },
5255             "offset" => {
5256               (1,
5257                vec!(
5258                   ty::mk_ptr(tcx, ty::mt {
5259                       ty: param(ccx, 0),
5260                       mutbl: ast::MutImmutable
5261                   }),
5262                   ccx.tcx.types.int
5263                ),
5264                ty::mk_ptr(tcx, ty::mt {
5265                    ty: param(ccx, 0),
5266                    mutbl: ast::MutImmutable
5267                }))
5268             }
5269             "copy_memory" | "copy_nonoverlapping_memory" |
5270             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5271               (1,
5272                vec!(
5273                   ty::mk_ptr(tcx, ty::mt {
5274                       ty: param(ccx, 0),
5275                       mutbl: ast::MutMutable
5276                   }),
5277                   ty::mk_ptr(tcx, ty::mt {
5278                       ty: param(ccx, 0),
5279                       mutbl: ast::MutImmutable
5280                   }),
5281                   tcx.types.uint,
5282                ),
5283                ty::mk_nil(tcx))
5284             }
5285             "set_memory" | "volatile_set_memory" => {
5286               (1,
5287                vec!(
5288                   ty::mk_ptr(tcx, ty::mt {
5289                       ty: param(ccx, 0),
5290                       mutbl: ast::MutMutable
5291                   }),
5292                   tcx.types.u8,
5293                   tcx.types.uint,
5294                ),
5295                ty::mk_nil(tcx))
5296             }
5297             "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5298             "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5299             "powif32" => {
5300                (0,
5301                 vec!( tcx.types.f32, tcx.types.i32 ),
5302                 tcx.types.f32)
5303             }
5304             "powif64" => {
5305                (0,
5306                 vec!( tcx.types.f64, tcx.types.i32 ),
5307                 tcx.types.f64)
5308             }
5309             "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5310             "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5311             "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5312             "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5313             "powf32" => {
5314                (0,
5315                 vec!( tcx.types.f32, tcx.types.f32 ),
5316                 tcx.types.f32)
5317             }
5318             "powf64" => {
5319                (0,
5320                 vec!( tcx.types.f64, tcx.types.f64 ),
5321                 tcx.types.f64)
5322             }
5323             "expf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5324             "expf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5325             "exp2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5326             "exp2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5327             "logf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5328             "logf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5329             "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5330             "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5331             "log2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5332             "log2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5333             "fmaf32" => {
5334                 (0,
5335                  vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5336                  tcx.types.f32)
5337             }
5338             "fmaf64" => {
5339                 (0,
5340                  vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5341                  tcx.types.f64)
5342             }
5343             "fabsf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5344             "fabsf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5345             "copysignf32"  => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5346             "copysignf64"  => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5347             "floorf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5348             "floorf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5349             "ceilf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5350             "ceilf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5351             "truncf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5352             "truncf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5353             "rintf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5354             "rintf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5355             "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5356             "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5357             "roundf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5358             "roundf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5359             "ctpop8"       => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5360             "ctpop16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5361             "ctpop32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5362             "ctpop64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5363             "ctlz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5364             "ctlz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5365             "ctlz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5366             "ctlz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5367             "cttz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
5368             "cttz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5369             "cttz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5370             "cttz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5371             "bswap16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5372             "bswap32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5373             "bswap64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5374
5375             "volatile_load" =>
5376                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5377             "volatile_store" =>
5378                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5379
5380             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5381                 (0, vec!(tcx.types.i8, tcx.types.i8),
5382                 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5383
5384             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5385                 (0, vec!(tcx.types.i16, tcx.types.i16),
5386                 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5387
5388             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5389                 (0, vec!(tcx.types.i32, tcx.types.i32),
5390                 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5391
5392             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5393                 (0, vec!(tcx.types.i64, tcx.types.i64),
5394                 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5395
5396             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5397                 (0, vec!(tcx.types.u8, tcx.types.u8),
5398                 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5399
5400             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5401                 (0, vec!(tcx.types.u16, tcx.types.u16),
5402                 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5403
5404             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5405                 (0, vec!(tcx.types.u32, tcx.types.u32),
5406                 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5407
5408             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
5409                 (0, vec!(tcx.types.u64, tcx.types.u64),
5410                 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5411
5412             "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5413
5414             "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5415
5416             ref other => {
5417                 span_err!(tcx.sess, it.span, E0093,
5418                     "unrecognized intrinsic function: `{}`", *other);
5419                 return;
5420             }
5421         };
5422         (n_tps, inputs, ty::FnConverging(output))
5423     };
5424     let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5425         unsafety: ast::Unsafety::Unsafe,
5426         abi: abi::RustIntrinsic,
5427         sig: ty::Binder(FnSig {
5428             inputs: inputs,
5429             output: output,
5430             variadic: false,
5431         }),
5432     }));
5433     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5434     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5435     if i_n_tps != n_tps {
5436         span_err!(tcx.sess, it.span, E0094,
5437             "intrinsic has wrong number of type \
5438              parameters: found {}, expected {}",
5439              i_n_tps, n_tps);
5440     } else {
5441         require_same_types(tcx,
5442                            None,
5443                            false,
5444                            it.span,
5445                            i_ty.ty,
5446                            fty,
5447                            || {
5448                 format!("intrinsic has wrong type: expected `{}`",
5449                         ppaux::ty_to_string(ccx.tcx, fty))
5450             });
5451     }
5452 }