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