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