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