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