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