]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/mod.rs
8d67c04f687bf9a81290080d6cff8485f488f07c
[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         if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3873             match unop {
3874                 ast::UnBox => {
3875                     oprnd_t = ty::mk_box(tcx, oprnd_t)
3876                 }
3877                 ast::UnUniq => {
3878                     oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3879                 }
3880                 ast::UnDeref => {
3881                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3882                     oprnd_t = match ty::deref(oprnd_t, true) {
3883                         Some(mt) => mt.ty,
3884                         None => match try_overloaded_deref(fcx, expr.span,
3885                                                            Some(MethodCall::expr(expr.id)),
3886                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
3887                             Some(mt) => mt.ty,
3888                             None => {
3889                                 let is_newtype = match ty::get(oprnd_t).sty {
3890                                     ty::ty_struct(did, ref substs) => {
3891                                         let fields = ty::struct_fields(fcx.tcx(), did, substs);
3892                                         fields.len() == 1
3893                                         && fields.get(0).ident ==
3894                                         token::special_idents::unnamed_field
3895                                     }
3896                                     _ => false
3897                                 };
3898                                 if is_newtype {
3899                                     // This is an obsolete struct deref
3900                                     span_err!(tcx.sess, expr.span, E0068,
3901                                         "single-field tuple-structs can \
3902                                          no longer be dereferenced");
3903                                 } else {
3904                                     fcx.type_error_message(expr.span, |actual| {
3905                                         format!("type `{}` cannot be \
3906                                                 dereferenced", actual)
3907                                     }, oprnd_t, None);
3908                                 }
3909                                 ty::mk_err()
3910                             }
3911                         }
3912                     };
3913                 }
3914                 ast::UnNot => {
3915                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3916                                                          oprnd_t);
3917                     if !(ty::type_is_integral(oprnd_t) ||
3918                          ty::get(oprnd_t).sty == ty::ty_bool) {
3919                         oprnd_t = check_user_unop(fcx, "!", "not",
3920                                                   tcx.lang_items.not_trait(),
3921                                                   expr, &**oprnd, oprnd_t);
3922                     }
3923                 }
3924                 ast::UnNeg => {
3925                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3926                                                          oprnd_t);
3927                     if !(ty::type_is_integral(oprnd_t) ||
3928                          ty::type_is_fp(oprnd_t)) {
3929                         oprnd_t = check_user_unop(fcx, "-", "neg",
3930                                                   tcx.lang_items.neg_trait(),
3931                                                   expr, &**oprnd, oprnd_t);
3932                     }
3933                 }
3934             }
3935         }
3936         fcx.write_ty(id, oprnd_t);
3937       }
3938       ast::ExprAddrOf(mutbl, ref oprnd) => {
3939         let expected = expected.only_has_type();
3940         let hint = expected.map(fcx, |sty| {
3941             match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3942                          _ => NoExpectation }
3943         });
3944         let lvalue_pref = match mutbl {
3945             ast::MutMutable => PreferMutLvalue,
3946             ast::MutImmutable => NoPreference
3947         };
3948         check_expr_with_expectation_and_lvalue_pref(fcx,
3949                                                     &**oprnd,
3950                                                     hint,
3951                                                     lvalue_pref);
3952
3953         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3954         let oprnd_t = if ty::type_is_error(tm.ty) {
3955             ty::mk_err()
3956         } else if ty::type_is_bot(tm.ty) {
3957             ty::mk_bot()
3958         }
3959         else {
3960             // Note: at this point, we cannot say what the best lifetime
3961             // is to use for resulting pointer.  We want to use the
3962             // shortest lifetime possible so as to avoid spurious borrowck
3963             // errors.  Moreover, the longest lifetime will depend on the
3964             // precise details of the value whose address is being taken
3965             // (and how long it is valid), which we don't know yet until type
3966             // inference is complete.
3967             //
3968             // Therefore, here we simply generate a region variable.  The
3969             // region inferencer will then select the ultimate value.
3970             // Finally, borrowck is charged with guaranteeing that the
3971             // value whose address was taken can actually be made to live
3972             // as long as it needs to live.
3973             match oprnd.node {
3974                 // String literals are already, implicitly converted to slices.
3975                 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3976                 // Empty slices live in static memory.
3977                 ast::ExprVec(ref elements) if elements.len() == 0 => {
3978                     // Note: we do not assign a lifetime of
3979                     // static. This is because the resulting type
3980                     // `&'static [T]` would require that T outlives
3981                     // `'static`!
3982                     let region = fcx.infcx().next_region_var(
3983                         infer::AddrOfSlice(expr.span));
3984                     ty::mk_rptr(tcx, region, tm)
3985                 }
3986                 _ => {
3987                     let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3988                     ty::mk_rptr(tcx, region, tm)
3989                 }
3990             }
3991         };
3992         fcx.write_ty(id, oprnd_t);
3993       }
3994       ast::ExprPath(ref pth) => {
3995           let defn = lookup_def(fcx, pth.span, id);
3996           let pty = polytype_for_def(fcx, expr.span, defn);
3997           instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3998
3999           // We always require that the type provided as the value for
4000           // a type parameter outlives the moment of instantiation.
4001           constrain_path_type_parameters(fcx, expr);
4002       }
4003       ast::ExprInlineAsm(ref ia) => {
4004           for &(_, ref input) in ia.inputs.iter() {
4005               check_expr(fcx, &**input);
4006           }
4007           for &(_, ref out, _) in ia.outputs.iter() {
4008               check_expr(fcx, &**out);
4009           }
4010           fcx.write_nil(id);
4011       }
4012       ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
4013       ast::ExprBreak(_) => { fcx.write_bot(id); }
4014       ast::ExprAgain(_) => { fcx.write_bot(id); }
4015       ast::ExprRet(ref expr_opt) => {
4016         let ret_ty = fcx.ret_ty;
4017         match *expr_opt {
4018           None => match fcx.mk_eqty(false, infer::Misc(expr.span),
4019                                     ret_ty, ty::mk_nil()) {
4020             Ok(_) => { /* fall through */ }
4021             Err(_) => {
4022                 span_err!(tcx.sess, expr.span, E0069,
4023                     "`return;` in function returning non-nil");
4024             }
4025           },
4026           Some(ref e) => {
4027               check_expr_coercable_to_type(fcx, &**e, ret_ty);
4028           }
4029         }
4030         fcx.write_bot(id);
4031       }
4032       ast::ExprParen(ref a) => {
4033         check_expr_with_expectation_and_lvalue_pref(fcx,
4034                                                     &**a,
4035                                                     expected,
4036                                                     lvalue_pref);
4037         fcx.write_ty(id, fcx.expr_ty(&**a));
4038       }
4039       ast::ExprAssign(ref lhs, ref rhs) => {
4040         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4041
4042         let tcx = fcx.tcx();
4043         if !ty::expr_is_lval(tcx, &**lhs) {
4044             span_err!(tcx.sess, expr.span, E0070,
4045                 "illegal left-hand side expression");
4046         }
4047
4048         let lhs_ty = fcx.expr_ty(&**lhs);
4049         check_expr_has_type(fcx, &**rhs, lhs_ty);
4050         let rhs_ty = fcx.expr_ty(&**rhs);
4051
4052         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4053
4054         if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4055             fcx.write_error(id);
4056         } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
4057             fcx.write_bot(id);
4058         } else {
4059             fcx.write_nil(id);
4060         }
4061       }
4062       ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4063         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4064                         id, expr.span, expected);
4065       }
4066       ast::ExprWhile(ref cond, ref body, _) => {
4067         check_expr_has_type(fcx, &**cond, ty::mk_bool());
4068         check_block_no_value(fcx, &**body);
4069         let cond_ty = fcx.expr_ty(&**cond);
4070         let body_ty = fcx.node_ty(body.id);
4071         if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4072             fcx.write_error(id);
4073         }
4074         else if ty::type_is_bot(cond_ty) {
4075             fcx.write_bot(id);
4076         }
4077         else {
4078             fcx.write_nil(id);
4079         }
4080       }
4081       ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4082         check_expr(fcx, &**head);
4083         let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4084         vtable2::select_fcx_obligations_where_possible(fcx);
4085
4086         let pcx = pat_ctxt {
4087             fcx: fcx,
4088             map: pat_id_map(&tcx.def_map, &**pat),
4089         };
4090         _match::check_pat(&pcx, &**pat, typ);
4091
4092         check_block_no_value(fcx, &**block);
4093         fcx.write_nil(id);
4094       }
4095       ast::ExprLoop(ref body, _) => {
4096         check_block_no_value(fcx, &**body);
4097         if !may_break(tcx, expr.id, &**body) {
4098             fcx.write_bot(id);
4099         } else {
4100             fcx.write_nil(id);
4101         }
4102       }
4103       ast::ExprMatch(ref discrim, ref arms) => {
4104         _match::check_match(fcx, expr, &**discrim, arms.as_slice());
4105       }
4106       ast::ExprFnBlock(_, ref decl, ref body) => {
4107         let region = astconv::opt_ast_region_to_region(fcx,
4108                                                        fcx.infcx(),
4109                                                        expr.span,
4110                                                        &None);
4111         check_expr_fn(fcx,
4112                       expr,
4113                       ty::RegionTraitStore(region, ast::MutMutable),
4114                       &**decl,
4115                       &**body,
4116                       expected);
4117       }
4118       ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
4119         check_unboxed_closure(fcx,
4120                               expr,
4121                               kind,
4122                               &**decl,
4123                               &**body);
4124       }
4125       ast::ExprProc(ref decl, ref body) => {
4126         check_expr_fn(fcx,
4127                       expr,
4128                       ty::UniqTraitStore,
4129                       &**decl,
4130                       &**body,
4131                       expected);
4132       }
4133       ast::ExprBlock(ref b) => {
4134         check_block_with_expected(fcx, &**b, expected);
4135         fcx.write_ty(id, fcx.node_ty(b.id));
4136       }
4137       ast::ExprCall(ref f, ref args) => {
4138           // Index expressions need to be handled separately, to inform them
4139           // that they appear in call position.
4140           check_expr(fcx, &**f);
4141           let f_ty = fcx.expr_ty(&**f);
4142
4143           if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
4144               check_call(fcx, expr, &**f, args.as_slice());
4145               let (args_bot, args_err) = args.iter().fold((false, false),
4146                  |(rest_bot, rest_err), a| {
4147                      // is this not working?
4148                      let a_ty = fcx.expr_ty(&**a);
4149                      (rest_bot || ty::type_is_bot(a_ty),
4150                       rest_err || ty::type_is_error(a_ty))});
4151               if ty::type_is_error(f_ty) || args_err {
4152                   fcx.write_error(id);
4153               }
4154               else if ty::type_is_bot(f_ty) || args_bot {
4155                   fcx.write_bot(id);
4156               }
4157           }
4158       }
4159       ast::ExprMethodCall(ident, ref tps, ref args) => {
4160         check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
4161         let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4162         let (args_bot, args_err) = arg_tys.fold((false, false),
4163              |(rest_bot, rest_err), a| {
4164               (rest_bot || ty::type_is_bot(a),
4165                rest_err || ty::type_is_error(a))});
4166         if args_err {
4167             fcx.write_error(id);
4168         } else if args_bot {
4169             fcx.write_bot(id);
4170         }
4171       }
4172       ast::ExprCast(ref e, ref t) => {
4173         match t.node {
4174             ast::TyFixedLengthVec(_, ref count_expr) => {
4175                 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
4176             }
4177             _ => {}
4178         }
4179         check_cast(fcx, expr, &**e, &**t);
4180       }
4181       ast::ExprVec(ref args) => {
4182         let uty = match expected {
4183             ExpectHasType(uty) => {
4184                 match ty::get(uty).sty {
4185                         ty::ty_vec(ty, _) => Some(ty),
4186                         _ => None
4187                 }
4188             }
4189             _ => None
4190         };
4191
4192         let typ = match uty {
4193             Some(uty) => {
4194                 for e in args.iter() {
4195                     check_expr_coercable_to_type(fcx, &**e, uty);
4196                 }
4197                 uty
4198             }
4199             None => {
4200                 let t: ty::t = fcx.infcx().next_ty_var();
4201                 for e in args.iter() {
4202                     check_expr_has_type(fcx, &**e, t);
4203                 }
4204                 t
4205             }
4206         };
4207         let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4208         fcx.write_ty(id, typ);
4209       }
4210       ast::ExprRepeat(ref element, ref count_expr) => {
4211         check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
4212         let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4213
4214         let uty = match expected {
4215             ExpectHasType(uty) => {
4216                 match ty::get(uty).sty {
4217                         ty::ty_vec(ty, _) => Some(ty),
4218                         _ => None
4219                 }
4220             }
4221             _ => None
4222         };
4223
4224         let (element_ty, t) = match uty {
4225             Some(uty) => {
4226                 check_expr_coercable_to_type(fcx, &**element, uty);
4227                 (uty, uty)
4228             }
4229             None => {
4230                 let t: ty::t = fcx.infcx().next_ty_var();
4231                 check_expr_has_type(fcx, &**element, t);
4232                 (fcx.expr_ty(&**element), t)
4233             }
4234         };
4235
4236         if count > 1 {
4237             // For [foo, ..n] where n > 1, `foo` must have
4238             // Copy type:
4239             fcx.require_type_meets(
4240                 t,
4241                 expr.span,
4242                 traits::RepeatVec,
4243                 ty::BoundCopy);
4244         }
4245
4246         if ty::type_is_error(element_ty) {
4247             fcx.write_error(id);
4248         } else if ty::type_is_bot(element_ty) {
4249             fcx.write_bot(id);
4250         } else {
4251             let t = ty::mk_vec(tcx, t, Some(count));
4252             fcx.write_ty(id, t);
4253         }
4254       }
4255       ast::ExprTup(ref elts) => {
4256         let expected = expected.only_has_type();
4257         let flds = expected.map_to_option(fcx, |sty| {
4258             match *sty {
4259                 ty::ty_tup(ref flds) => Some((*flds).clone()),
4260                 _ => None
4261             }
4262         });
4263         let mut bot_field = false;
4264         let mut err_field = false;
4265
4266         let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4267             let t = match flds {
4268                 Some(ref fs) if i < fs.len() => {
4269                     let ety = *fs.get(i);
4270                     check_expr_coercable_to_type(fcx, &**e, ety);
4271                     ety
4272                 }
4273                 _ => {
4274                     check_expr_with_expectation(fcx, &**e, NoExpectation);
4275                     fcx.expr_ty(&**e)
4276                 }
4277             };
4278             err_field = err_field || ty::type_is_error(t);
4279             bot_field = bot_field || ty::type_is_bot(t);
4280             t
4281         }).collect();
4282         if bot_field {
4283             fcx.write_bot(id);
4284         } else if err_field {
4285             fcx.write_error(id);
4286         } else {
4287             let typ = ty::mk_tup(tcx, elt_ts);
4288             fcx.write_ty(id, typ);
4289         }
4290       }
4291       ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4292         // Resolve the path.
4293         let def = tcx.def_map.borrow().find(&id).map(|i| *i);
4294         let struct_id = match def {
4295             Some(def::DefVariant(enum_id, variant_id, _)) => {
4296                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4297                                           variant_id, fields.as_slice());
4298                 enum_id
4299             }
4300             Some(def::DefTrait(def_id)) => {
4301                 span_err!(tcx.sess, path.span, E0159,
4302                     "use of trait `{}` as a struct constructor",
4303                     pprust::path_to_string(path));
4304                 check_struct_fields_on_error(fcx,
4305                                              id,
4306                                              fields.as_slice(),
4307                                              base_expr);
4308                 def_id
4309             },
4310             Some(def) => {
4311                 // Verify that this was actually a struct.
4312                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4313                 match ty::get(typ.ty).sty {
4314                     ty::ty_struct(struct_did, _) => {
4315                         check_struct_constructor(fcx,
4316                                                  id,
4317                                                  expr.span,
4318                                                  struct_did,
4319                                                  fields.as_slice(),
4320                                                  base_expr.as_ref().map(|e| &**e));
4321                     }
4322                     _ => {
4323                         span_err!(tcx.sess, path.span, E0071,
4324                             "`{}` does not name a structure",
4325                             pprust::path_to_string(path));
4326                         check_struct_fields_on_error(fcx,
4327                                                      id,
4328                                                      fields.as_slice(),
4329                                                      base_expr);
4330                     }
4331                 }
4332
4333                 def.def_id()
4334             }
4335             _ => {
4336                 tcx.sess.span_bug(path.span,
4337                                   "structure constructor wasn't resolved")
4338             }
4339         };
4340
4341         // Turn the path into a type and verify that that type unifies with
4342         // the resulting structure type. This is needed to handle type
4343         // parameters correctly.
4344         let actual_structure_type = fcx.expr_ty(&*expr);
4345         if !ty::type_is_error(actual_structure_type) {
4346             let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4347                                                                   fcx.infcx(),
4348                                                                   struct_id,
4349                                                                   path);
4350             match fcx.mk_subty(false,
4351                                infer::Misc(path.span),
4352                                actual_structure_type,
4353                                type_and_substs.ty) {
4354                 Ok(()) => {}
4355                 Err(type_error) => {
4356                     let type_error_description =
4357                         ty::type_err_to_str(tcx, &type_error);
4358                     fcx.tcx()
4359                        .sess
4360                        .span_err(path.span,
4361                                  format!("structure constructor specifies a \
4362                                          structure of type `{}`, but this \
4363                                          structure has type `{}`: {}",
4364                                          fcx.infcx()
4365                                             .ty_to_string(type_and_substs.ty),
4366                                          fcx.infcx()
4367                                             .ty_to_string(
4368                                                 actual_structure_type),
4369                                          type_error_description).as_slice());
4370                     ty::note_and_explain_type_err(tcx, &type_error);
4371                 }
4372             }
4373         }
4374
4375         fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4376       }
4377       ast::ExprField(ref base, ref field, ref tys) => {
4378         check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
4379       }
4380       ast::ExprTupField(ref base, idx, ref tys) => {
4381         check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
4382       }
4383       ast::ExprIndex(ref base, ref idx) => {
4384           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4385           check_expr(fcx, &**idx);
4386           let raw_base_t = fcx.expr_ty(&**base);
4387           let idx_t = fcx.expr_ty(&**idx);
4388           if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
4389               fcx.write_ty(id, raw_base_t);
4390           } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
4391               fcx.write_ty(id, idx_t);
4392           } else {
4393               let (_, autoderefs, field_ty) =
4394                 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
4395                           lvalue_pref, |base_t, _| ty::index(base_t));
4396               match field_ty {
4397                   Some(ty) => {
4398                       check_expr_has_type(fcx, &**idx, ty::mk_uint());
4399                       fcx.write_ty(id, ty);
4400                       fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
4401                   }
4402                   None => {
4403                       // This is an overloaded method.
4404                       let base_t = structurally_resolved_type(fcx,
4405                                                               expr.span,
4406                                                               raw_base_t);
4407                       let method_call = MethodCall::expr(expr.id);
4408                       match try_overloaded_index(fcx,
4409                                                  Some(method_call),
4410                                                  expr,
4411                                                  &**base,
4412                                                  base_t,
4413                                                  idx,
4414                                                  lvalue_pref) {
4415                           Some(mt) => fcx.write_ty(id, mt.ty),
4416                           None => {
4417                                 fcx.type_error_message(expr.span,
4418                                                        |actual| {
4419                                                         format!("cannot \
4420                                                                  index a \
4421                                                                  value of \
4422                                                                  type `{}`",
4423                                                                 actual)
4424                                                        },
4425                                                        base_t,
4426                                                        None);
4427                                 fcx.write_ty(id, ty::mk_err())
4428                           }
4429                       }
4430                   }
4431               }
4432           }
4433        }
4434     }
4435
4436     debug!("type of expr({}) {} is...", expr.id,
4437            syntax::print::pprust::expr_to_string(expr));
4438     debug!("... {}, expected is {}",
4439            ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4440            expected.repr(tcx));
4441
4442     unifier();
4443 }
4444
4445 fn constrain_path_type_parameters(fcx: &FnCtxt,
4446                                   expr: &ast::Expr)
4447 {
4448     fcx.opt_node_ty_substs(expr.id, |item_substs| {
4449         for &ty in item_substs.substs.types.iter() {
4450             let default_bound = ty::ReScope(expr.id);
4451             let origin = infer::RelateDefaultParamBound(expr.span, ty);
4452             fcx.register_region_obligation(origin, ty, default_bound);
4453         }
4454     });
4455 }
4456
4457 impl Expectation {
4458     fn only_has_type(self) -> Expectation {
4459         match self {
4460             NoExpectation | ExpectCastableToType(..) => NoExpectation,
4461             ExpectHasType(t) => ExpectHasType(t)
4462         }
4463     }
4464
4465     // Resolves `expected` by a single level if it is a variable. If
4466     // there is no expected type or resolution is not possible (e.g.,
4467     // no constraints yet present), just returns `None`.
4468     fn resolve(self, fcx: &FnCtxt) -> Expectation {
4469         match self {
4470             NoExpectation => {
4471                 NoExpectation
4472             }
4473             ExpectCastableToType(t) => {
4474                 ExpectCastableToType(
4475                     fcx.infcx().resolve_type_vars_if_possible(t))
4476             }
4477             ExpectHasType(t) => {
4478                 ExpectHasType(
4479                     fcx.infcx().resolve_type_vars_if_possible(t))
4480             }
4481         }
4482     }
4483
4484     fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
4485         match self.resolve(fcx) {
4486             NoExpectation => NoExpectation,
4487             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4488         }
4489     }
4490
4491     fn map_to_option<O>(self,
4492                         fcx: &FnCtxt,
4493                         unpack: |&ty::sty| -> Option<O>)
4494                         -> Option<O>
4495     {
4496         match self.resolve(fcx) {
4497             NoExpectation => None,
4498             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4499         }
4500     }
4501 }
4502
4503 impl Repr for Expectation {
4504     fn repr(&self, tcx: &ty::ctxt) -> String {
4505         match *self {
4506             NoExpectation => format!("NoExpectation"),
4507             ExpectHasType(t) => format!("ExpectHasType({})",
4508                                         t.repr(tcx)),
4509             ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4510                                                t.repr(tcx)),
4511         }
4512     }
4513 }
4514
4515 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
4516     if !type_is_uint(fcx, sp, t) {
4517         fcx.type_error_message(sp, |actual| {
4518             format!("mismatched types: expected `uint` type, found `{}`",
4519                     actual)
4520         }, t, None);
4521     }
4522 }
4523
4524 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
4525     if !type_is_integral(fcx, sp, t) {
4526         fcx.type_error_message(sp, |actual| {
4527             format!("mismatched types: expected integral type, found `{}`",
4528                     actual)
4529         }, t, None);
4530     }
4531 }
4532
4533 pub fn check_decl_initializer(fcx: &FnCtxt,
4534                               nid: ast::NodeId,
4535                               init: &ast::Expr)
4536                             {
4537     let local_ty = fcx.local_ty(init.span, nid);
4538     check_expr_coercable_to_type(fcx, init, local_ty)
4539 }
4540
4541 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
4542     let tcx = fcx.ccx.tcx;
4543
4544     let t = fcx.local_ty(local.span, local.id);
4545     fcx.write_ty(local.id, t);
4546
4547     match local.init {
4548         Some(ref init) => {
4549             check_decl_initializer(fcx, local.id, &**init);
4550             let init_ty = fcx.expr_ty(&**init);
4551             if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
4552                 fcx.write_ty(local.id, init_ty);
4553             }
4554         }
4555         _ => {}
4556     }
4557
4558     let pcx = pat_ctxt {
4559         fcx: fcx,
4560         map: pat_id_map(&tcx.def_map, &*local.pat),
4561     };
4562     _match::check_pat(&pcx, &*local.pat, t);
4563     let pat_ty = fcx.node_ty(local.pat.id);
4564     if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
4565         fcx.write_ty(local.id, pat_ty);
4566     }
4567 }
4568
4569 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
4570     let node_id;
4571     let mut saw_bot = false;
4572     let mut saw_err = false;
4573     match stmt.node {
4574       ast::StmtDecl(ref decl, id) => {
4575         node_id = id;
4576         match decl.node {
4577           ast::DeclLocal(ref l) => {
4578               check_decl_local(fcx, &**l);
4579               let l_t = fcx.node_ty(l.id);
4580               saw_bot = saw_bot || ty::type_is_bot(l_t);
4581               saw_err = saw_err || ty::type_is_error(l_t);
4582           }
4583           ast::DeclItem(_) => {/* ignore for now */ }
4584         }
4585       }
4586       ast::StmtExpr(ref expr, id) => {
4587         node_id = id;
4588         // Check with expected type of ()
4589         check_expr_has_type(fcx, &**expr, ty::mk_nil());
4590         let expr_ty = fcx.expr_ty(&**expr);
4591         saw_bot = saw_bot || ty::type_is_bot(expr_ty);
4592         saw_err = saw_err || ty::type_is_error(expr_ty);
4593       }
4594       ast::StmtSemi(ref expr, id) => {
4595         node_id = id;
4596         check_expr(fcx, &**expr);
4597         let expr_ty = fcx.expr_ty(&**expr);
4598         saw_bot |= ty::type_is_bot(expr_ty);
4599         saw_err |= ty::type_is_error(expr_ty);
4600       }
4601       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4602     }
4603     if saw_bot {
4604         fcx.write_bot(node_id);
4605     }
4606     else if saw_err {
4607         fcx.write_error(node_id);
4608     }
4609     else {
4610         fcx.write_nil(node_id)
4611     }
4612 }
4613
4614 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
4615     check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
4616     let blkty = fcx.node_ty(blk.id);
4617     if ty::type_is_error(blkty) {
4618         fcx.write_error(blk.id);
4619     }
4620     else if ty::type_is_bot(blkty) {
4621         fcx.write_bot(blk.id);
4622     }
4623     else {
4624         let nilty = ty::mk_nil();
4625         demand::suptype(fcx, blk.span, nilty, blkty);
4626     }
4627 }
4628
4629 fn check_block_with_expected(fcx: &FnCtxt,
4630                              blk: &ast::Block,
4631                              expected: Expectation) {
4632     let prev = {
4633         let mut fcx_ps = fcx.ps.borrow_mut();
4634         let fn_style_state = fcx_ps.recurse(blk);
4635         replace(&mut *fcx_ps, fn_style_state)
4636     };
4637
4638     let mut warned = false;
4639     let mut last_was_bot = false;
4640     let mut any_bot = false;
4641     let mut any_err = false;
4642     for s in blk.stmts.iter() {
4643         check_stmt(fcx, &**s);
4644         let s_id = ast_util::stmt_id(&**s);
4645         let s_ty = fcx.node_ty(s_id);
4646         if last_was_bot && !warned && match s.node {
4647             ast::StmtDecl(ref decl, _) => {
4648                 match decl.node {
4649                     ast::DeclLocal(_) => true,
4650                     _ => false,
4651                 }
4652             }
4653             ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4654             _ => false
4655         } {
4656             fcx.ccx
4657                 .tcx
4658                 .sess
4659                 .add_lint(lint::builtin::UNREACHABLE_CODE,
4660                           s_id,
4661                           s.span,
4662                           "unreachable statement".to_string());
4663             warned = true;
4664         }
4665         if ty::type_is_bot(s_ty) {
4666             last_was_bot = true;
4667         }
4668         any_bot = any_bot || ty::type_is_bot(s_ty);
4669         any_err = any_err || ty::type_is_error(s_ty);
4670     }
4671     match blk.expr {
4672         None => if any_err {
4673             fcx.write_error(blk.id);
4674         } else if any_bot {
4675             fcx.write_bot(blk.id);
4676         } else {
4677             fcx.write_nil(blk.id);
4678         },
4679         Some(ref e) => {
4680             if any_bot && !warned {
4681                 fcx.ccx
4682                     .tcx
4683                     .sess
4684                     .add_lint(lint::builtin::UNREACHABLE_CODE,
4685                               e.id,
4686                               e.span,
4687                               "unreachable expression".to_string());
4688             }
4689             let ety = match expected {
4690                 ExpectHasType(ety) => {
4691                     check_expr_coercable_to_type(fcx, &**e, ety);
4692                     ety
4693                 }
4694                 _ => {
4695                     check_expr_with_expectation(fcx, &**e, expected);
4696                     fcx.expr_ty(&**e)
4697                 }
4698             };
4699
4700             fcx.write_ty(blk.id, ety);
4701             if any_err {
4702                 fcx.write_error(blk.id);
4703             } else if any_bot {
4704                 fcx.write_bot(blk.id);
4705             }
4706         }
4707     };
4708
4709     *fcx.ps.borrow_mut() = prev;
4710 }
4711
4712 /// Checks a constant appearing in a type. At the moment this is just the
4713 /// length expression in a fixed-length vector, but someday it might be
4714 /// extended to type-level numeric literals.
4715 pub fn check_const_in_type(tcx: &ty::ctxt,
4716                            expr: &ast::Expr,
4717                            expected_type: ty::t) {
4718     // Synthesize a crate context. The trait map is not needed here (though I
4719     // imagine it will be if we have associated statics --pcwalton), so we
4720     // leave it blank.
4721     let ccx = CrateCtxt {
4722         trait_map: NodeMap::new(),
4723         tcx: tcx,
4724     };
4725     let inh = static_inherited_fields(&ccx);
4726     let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
4727     check_const_with_ty(&fcx, expr.span, expr, expected_type);
4728 }
4729
4730 pub fn check_const(ccx: &CrateCtxt,
4731                    sp: Span,
4732                    e: &ast::Expr,
4733                    id: ast::NodeId) {
4734     let inh = static_inherited_fields(ccx);
4735     let rty = ty::node_id_to_type(ccx.tcx, id);
4736     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4737     let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
4738     check_const_with_ty(&fcx, sp, e, declty);
4739 }
4740
4741 pub fn check_const_with_ty(fcx: &FnCtxt,
4742                            _: Span,
4743                            e: &ast::Expr,
4744                            declty: ty::t) {
4745     // Gather locals in statics (because of block expressions).
4746     // This is technically unnecessary because locals in static items are forbidden,
4747     // but prevents type checking from blowing up before const checking can properly
4748     // emit a error.
4749     GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4750
4751     check_expr_with_hint(fcx, e, declty);
4752     demand::coerce(fcx, e.span, declty, e);
4753     vtable2::select_all_fcx_obligations_or_error(fcx);
4754     regionck::regionck_expr(fcx, e);
4755     writeback::resolve_type_vars_in_expr(fcx, e);
4756     vtable2::check_builtin_bound_obligations(fcx);
4757 }
4758
4759 /// Checks whether a type can be represented in memory. In particular, it
4760 /// identifies types that contain themselves without indirection through a
4761 /// pointer, which would mean their size is unbounded. This is different from
4762 /// the question of whether a type can be instantiated. See the definition of
4763 /// `check_instantiable`.
4764 pub fn check_representable(tcx: &ty::ctxt,
4765                            sp: Span,
4766                            item_id: ast::NodeId,
4767                            designation: &str) -> bool {
4768     let rty = ty::node_id_to_type(tcx, item_id);
4769
4770     // Check that it is possible to represent this type. This call identifies
4771     // (1) types that contain themselves and (2) types that contain a different
4772     // recursive type. It is only necessary to throw an error on those that
4773     // contain themselves. For case 2, there must be an inner type that will be
4774     // caught by case 1.
4775     match ty::is_type_representable(tcx, sp, rty) {
4776       ty::SelfRecursive => {
4777         span_err!(tcx.sess, sp, E0072,
4778             "illegal recursive {} type; \
4779              wrap the inner value in a box to make it representable",
4780             designation);
4781         return false
4782       }
4783       ty::Representable | ty::ContainsRecursive => (),
4784     }
4785     return true
4786 }
4787
4788 /// Checks whether a type can be created without an instance of itself.
4789 /// This is similar but different from the question of whether a type
4790 /// can be represented.  For example, the following type:
4791 ///
4792 ///     enum foo { None, Some(foo) }
4793 ///
4794 /// is instantiable but is not representable.  Similarly, the type
4795 ///
4796 ///     enum foo { Some(@foo) }
4797 ///
4798 /// is representable, but not instantiable.
4799 pub fn check_instantiable(tcx: &ty::ctxt,
4800                           sp: Span,
4801                           item_id: ast::NodeId)
4802                           -> bool {
4803     let item_ty = ty::node_id_to_type(tcx, item_id);
4804     if !ty::is_instantiable(tcx, item_ty) {
4805         span_err!(tcx.sess, sp, E0073,
4806             "this type cannot be instantiated without an \
4807              instance of itself; consider using `Option<{}>`",
4808             ppaux::ty_to_string(tcx, item_ty));
4809         false
4810     } else {
4811         true
4812     }
4813 }
4814
4815 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4816     let t = ty::node_id_to_type(tcx, id);
4817     if ty::type_needs_subst(t) {
4818         span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4819         return;
4820     }
4821     match ty::get(t).sty {
4822         ty::ty_struct(did, ref substs) => {
4823             let fields = ty::lookup_struct_fields(tcx, did);
4824             if fields.is_empty() {
4825                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4826                 return;
4827             }
4828             let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
4829             if !fields.iter().all(
4830                          |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4831                 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4832                 return;
4833             }
4834             if !ty::type_is_machine(e) {
4835                 span_err!(tcx.sess, sp, E0077,
4836                     "SIMD vector element type should be machine type");
4837                 return;
4838             }
4839         }
4840         _ => ()
4841     }
4842 }
4843
4844
4845 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4846                                  vs: &[P<ast::Variant>]) {
4847     for v in vs.iter() {
4848         match v.node.kind {
4849             ast::TupleVariantKind(ref args) if args.len() > 0 => {
4850                 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4851                 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4852                 let len = arg_tys.len();
4853                 if len == 0 {
4854                     return;
4855                 }
4856                 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4857                     // Allow the last field in an enum to be unsized.
4858                     // We want to do this so that we can support smart pointers.
4859                     // A struct value with an unsized final field is itself
4860                     // unsized and we must track this in the type system.
4861                     if !ty::type_is_sized(ccx.tcx, *t) {
4862                         span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4863                             "type `{}` is dynamically sized. dynamically sized types may only \
4864                              appear as the final type in a variant",
4865                              ppaux::ty_to_string(ccx.tcx, *t));
4866                     }
4867                 }
4868             },
4869             ast::StructVariantKind(ref struct_def) => {
4870                 check_fields_sized(ccx.tcx, &**struct_def)
4871             }
4872             _ => {}
4873         }
4874     }
4875 }
4876
4877 pub fn check_enum_variants(ccx: &CrateCtxt,
4878                            sp: Span,
4879                            vs: &[P<ast::Variant>],
4880                            id: ast::NodeId) {
4881
4882     fn disr_in_range(ccx: &CrateCtxt,
4883                      ty: attr::IntType,
4884                      disr: ty::Disr) -> bool {
4885         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4886             match ty {
4887                 ast::TyU8 => disr as u8 as Disr == disr,
4888                 ast::TyU16 => disr as u16 as Disr == disr,
4889                 ast::TyU32 => disr as u32 as Disr == disr,
4890                 ast::TyU64 => disr as u64 as Disr == disr,
4891                 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4892             }
4893         }
4894         fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4895             match ty {
4896                 ast::TyI8 => disr as i8 as Disr == disr,
4897                 ast::TyI16 => disr as i16 as Disr == disr,
4898                 ast::TyI32 => disr as i32 as Disr == disr,
4899                 ast::TyI64 => disr as i64 as Disr == disr,
4900                 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4901             }
4902         }
4903         match ty {
4904             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4905             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4906         }
4907     }
4908
4909     fn do_check(ccx: &CrateCtxt,
4910                 vs: &[P<ast::Variant>],
4911                 id: ast::NodeId,
4912                 hint: attr::ReprAttr)
4913                 -> Vec<Rc<ty::VariantInfo>> {
4914
4915         let rty = ty::node_id_to_type(ccx.tcx, id);
4916         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4917         let mut disr_vals: Vec<ty::Disr> = Vec::new();
4918         let mut prev_disr_val: Option<ty::Disr> = None;
4919
4920         for v in vs.iter() {
4921
4922             // If the discriminant value is specified explicitly in the enum check whether the
4923             // initialization expression is valid, otherwise use the last value plus one.
4924             let mut current_disr_val = match prev_disr_val {
4925                 Some(prev_disr_val) => prev_disr_val + 1,
4926                 None => ty::INITIAL_DISCRIMINANT_VALUE
4927             };
4928
4929             match v.node.disr_expr {
4930                 Some(ref e) => {
4931                     debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4932
4933                     let inh = static_inherited_fields(ccx);
4934                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4935                     let declty = match hint {
4936                         attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4937                         attr::ReprInt(_, attr::SignedInt(ity)) => {
4938                             ty::mk_mach_int(ity)
4939                         }
4940                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4941                             ty::mk_mach_uint(ity)
4942                         },
4943                     };
4944                     check_const_with_ty(&fcx, e.span, &**e, declty);
4945                     // check_expr (from check_const pass) doesn't guarantee
4946                     // that the expression is in a form that eval_const_expr can
4947                     // handle, so we may still get an internal compiler error
4948
4949                     match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4950                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4951                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4952                         Ok(_) => {
4953                             span_err!(ccx.tcx.sess, e.span, E0079,
4954                                 "expected signed integer constant");
4955                         }
4956                         Err(ref err) => {
4957                             span_err!(ccx.tcx.sess, e.span, E0080,
4958                                 "expected constant: {}", *err);
4959                         }
4960                     }
4961                 },
4962                 None => ()
4963             };
4964
4965             // Check for duplicate discriminant values
4966             if disr_vals.contains(&current_disr_val) {
4967                 span_err!(ccx.tcx.sess, v.span, E0081,
4968                     "discriminant value already exists");
4969             }
4970             // Check for unrepresentable discriminant values
4971             match hint {
4972                 attr::ReprAny | attr::ReprExtern => (),
4973                 attr::ReprInt(sp, ity) => {
4974                     if !disr_in_range(ccx, ity, current_disr_val) {
4975                         span_err!(ccx.tcx.sess, v.span, E0082,
4976                             "discriminant value outside specified type");
4977                         span_note!(ccx.tcx.sess, sp,
4978                             "discriminant type specified here");
4979                     }
4980                 }
4981                 attr::ReprPacked => {
4982                     ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4983                 }
4984             }
4985             disr_vals.push(current_disr_val);
4986
4987             let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4988                                                                      current_disr_val));
4989             prev_disr_val = Some(current_disr_val);
4990
4991             variants.push(variant_info);
4992         }
4993
4994         return variants;
4995     }
4996
4997     let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4998                     .as_slice().get(0).unwrap_or(&attr::ReprAny);
4999
5000     if hint != attr::ReprAny && vs.len() <= 1 {
5001         if vs.len() == 1 {
5002             span_err!(ccx.tcx.sess, sp, E0083,
5003                 "unsupported representation for univariant enum");
5004         } else {
5005             span_err!(ccx.tcx.sess, sp, E0084,
5006                 "unsupported representation for zero-variant enum");
5007         };
5008     }
5009
5010     let variants = do_check(ccx, vs, id, hint);
5011
5012     // cache so that ty::enum_variants won't repeat this work
5013     ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
5014
5015     check_representable(ccx.tcx, sp, id, "enum");
5016
5017     // Check that it is possible to instantiate this enum:
5018     //
5019     // This *sounds* like the same that as representable, but it's
5020     // not.  See def'n of `check_instantiable()` for details.
5021     check_instantiable(ccx.tcx, sp, id);
5022 }
5023
5024 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
5025     lookup_def_ccx(fcx.ccx, sp, id)
5026 }
5027
5028 // Returns the type parameter count and the type for the given definition.
5029 pub fn polytype_for_def(fcx: &FnCtxt,
5030                         sp: Span,
5031                         defn: def::Def)
5032                         -> Polytype {
5033     match defn {
5034       def::DefArg(nid, _) | def::DefLocal(nid, _) |
5035       def::DefBinding(nid, _) => {
5036           let typ = fcx.local_ty(sp, nid);
5037           return no_params(typ);
5038       }
5039       def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
5040       def::DefStatic(id, _) | def::DefVariant(_, id, _) |
5041       def::DefStruct(id) => {
5042         return ty::lookup_item_type(fcx.ccx.tcx, id);
5043       }
5044       def::DefUpvar(_, inner, _, _) => {
5045         return polytype_for_def(fcx, sp, *inner);
5046       }
5047       def::DefTrait(_) |
5048       def::DefTy(..) |
5049       def::DefAssociatedTy(..) |
5050       def::DefPrimTy(_) |
5051       def::DefTyParam(..)=> {
5052         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
5053       }
5054       def::DefMod(..) | def::DefForeignMod(..) => {
5055         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
5056       }
5057       def::DefUse(..) => {
5058         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
5059       }
5060       def::DefRegion(..) => {
5061         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
5062       }
5063       def::DefTyParamBinder(..) => {
5064         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
5065       }
5066       def::DefLabel(..) => {
5067         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
5068       }
5069       def::DefSelfTy(..) => {
5070         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5071       }
5072       def::DefMethod(..) => {
5073         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found method");
5074       }
5075     }
5076 }
5077
5078 // Instantiates the given path, which must refer to an item with the given
5079 // number of type parameters and type.
5080 pub fn instantiate_path(fcx: &FnCtxt,
5081                         path: &ast::Path,
5082                         polytype: Polytype,
5083                         def: def::Def,
5084                         span: Span,
5085                         node_id: ast::NodeId) {
5086     debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
5087            path.repr(fcx.tcx()),
5088            def.repr(fcx.tcx()),
5089            node_id,
5090            polytype.repr(fcx.tcx()));
5091
5092     // We need to extract the type parameters supplied by the user in
5093     // the path `path`. Due to the current setup, this is a bit of a
5094     // tricky-process; the problem is that resolve only tells us the
5095     // end-point of the path resolution, and not the intermediate steps.
5096     // Luckily, we can (at least for now) deduce the intermediate steps
5097     // just from the end-point.
5098     //
5099     // There are basically three cases to consider:
5100     //
5101     // 1. Reference to a *type*, such as a struct or enum:
5102     //
5103     //        mod a { struct Foo<T> { ... } }
5104     //
5105     //    Because we don't allow types to be declared within one
5106     //    another, a path that leads to a type will always look like
5107     //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
5108     //    that only the final segment can have type parameters, and
5109     //    they are located in the TypeSpace.
5110     //
5111     //    *Note:* Generally speaking, references to types don't
5112     //    actually pass through this function, but rather the
5113     //    `ast_ty_to_ty` function in `astconv`. However, in the case
5114     //    of struct patterns (and maybe literals) we do invoke
5115     //    `instantiate_path` to get the general type of an instance of
5116     //    a struct. (In these cases, there are actually no type
5117     //    parameters permitted at present, but perhaps we will allow
5118     //    them in the future.)
5119     //
5120     // 1b. Reference to a enum variant or tuple-like struct:
5121     //
5122     //        struct foo<T>(...)
5123     //        enum E<T> { foo(...) }
5124     //
5125     //    In these cases, the parameters are declared in the type
5126     //    space.
5127     //
5128     // 2. Reference to a *fn item*:
5129     //
5130     //        fn foo<T>() { }
5131     //
5132     //    In this case, the path will again always have the form
5133     //    `a::b::foo::<T>` where only the final segment should have
5134     //    type parameters. However, in this case, those parameters are
5135     //    declared on a value, and hence are in the `FnSpace`.
5136     //
5137     // 3. Reference to a *method*:
5138     //
5139     //        impl<A> SomeStruct<A> {
5140     //            fn foo<B>(...)
5141     //        }
5142     //
5143     //    Here we can have a path like
5144     //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5145     //    may appear in two places. The penultimate segment,
5146     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5147     //    final segment, `foo::<B>` contains parameters in fn space.
5148     //
5149     // The first step then is to categorize the segments appropriately.
5150
5151     assert!(path.segments.len() >= 1);
5152     let mut segment_spaces;
5153     match def {
5154         // Case 1 and 1b. Reference to a *type* or *enum variant*.
5155         def::DefSelfTy(..) |
5156         def::DefStruct(..) |
5157         def::DefVariant(..) |
5158         def::DefTyParamBinder(..) |
5159         def::DefTy(..) |
5160         def::DefAssociatedTy(..) |
5161         def::DefTrait(..) |
5162         def::DefPrimTy(..) |
5163         def::DefTyParam(..) => {
5164             // Everything but the final segment should have no
5165             // parameters at all.
5166             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5167             segment_spaces.push(Some(subst::TypeSpace));
5168         }
5169
5170         // Case 2. Reference to a top-level value.
5171         def::DefFn(..) |
5172         def::DefStatic(..) => {
5173             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5174             segment_spaces.push(Some(subst::FnSpace));
5175         }
5176
5177         // Case 3. Reference to a method.
5178         def::DefStaticMethod(..) => {
5179             assert!(path.segments.len() >= 2);
5180             segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
5181             segment_spaces.push(Some(subst::TypeSpace));
5182             segment_spaces.push(Some(subst::FnSpace));
5183         }
5184
5185         // Other cases. Various nonsense that really shouldn't show up
5186         // here. If they do, an error will have been reported
5187         // elsewhere. (I hope)
5188         def::DefMod(..) |
5189         def::DefForeignMod(..) |
5190         def::DefArg(..) |
5191         def::DefLocal(..) |
5192         def::DefMethod(..) |
5193         def::DefBinding(..) |
5194         def::DefUse(..) |
5195         def::DefRegion(..) |
5196         def::DefLabel(..) |
5197         def::DefUpvar(..) => {
5198             segment_spaces = Vec::from_elem(path.segments.len(), None);
5199         }
5200     }
5201     assert_eq!(segment_spaces.len(), path.segments.len());
5202
5203     debug!("segment_spaces={}", segment_spaces);
5204
5205     // Next, examine the definition, and determine how many type
5206     // parameters we expect from each space.
5207     let type_defs = &polytype.generics.types;
5208     let region_defs = &polytype.generics.regions;
5209
5210     // Now that we have categorized what space the parameters for each
5211     // segment belong to, let's sort out the parameters that the user
5212     // provided (if any) into their appropriate spaces. We'll also report
5213     // errors if type parameters are provided in an inappropriate place.
5214     let mut substs = Substs::empty();
5215     for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5216         match *opt_space {
5217             None => {
5218                 report_error_if_segment_contains_type_parameters(fcx, segment);
5219             }
5220
5221             Some(space) => {
5222                 push_explicit_parameters_from_segment_to_substs(fcx,
5223                                                                 space,
5224                                                                 type_defs,
5225                                                                 region_defs,
5226                                                                 segment,
5227                                                                 &mut substs);
5228             }
5229         }
5230     }
5231
5232     // Now we have to compare the types that the user *actually*
5233     // provided against the types that were *expected*. If the user
5234     // did not provide any types, then we want to substitute inference
5235     // variables. If the user provided some types, we may still need
5236     // to add defaults. If the user provided *too many* types, that's
5237     // a problem.
5238     for &space in ParamSpace::all().iter() {
5239         adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5240         assert_eq!(substs.types.len(space), type_defs.len(space));
5241
5242         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5243         assert_eq!(substs.regions().len(space), region_defs.len(space));
5244     }
5245
5246     fcx.add_obligations_for_parameters(
5247         traits::ObligationCause::new(span,
5248                                      traits::ItemObligation(def.def_id())),
5249         &substs,
5250         &polytype.generics);
5251
5252     fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
5253         substs: substs,
5254     });
5255
5256     fn report_error_if_segment_contains_type_parameters(
5257         fcx: &FnCtxt,
5258         segment: &ast::PathSegment)
5259     {
5260         for typ in segment.types.iter() {
5261             span_err!(fcx.tcx().sess, typ.span, E0085,
5262                 "type parameters may not appear here");
5263             break;
5264         }
5265
5266         for lifetime in segment.lifetimes.iter() {
5267             span_err!(fcx.tcx().sess, lifetime.span, E0086,
5268                 "lifetime parameters may not appear here");
5269             break;
5270         }
5271     }
5272
5273     fn push_explicit_parameters_from_segment_to_substs(
5274         fcx: &FnCtxt,
5275         space: subst::ParamSpace,
5276         type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
5277         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5278         segment: &ast::PathSegment,
5279         substs: &mut Substs)
5280     {
5281         /*!
5282          * Finds the parameters that the user provided and adds them
5283          * to `substs`. If too many parameters are provided, then
5284          * reports an error and clears the output vector.
5285          *
5286          * We clear the output vector because that will cause the
5287          * `adjust_XXX_parameters()` later to use inference
5288          * variables. This seems less likely to lead to derived
5289          * errors.
5290          *
5291          * Note that we *do not* check for *too few* parameters here.
5292          * Due to the presence of defaults etc that is more
5293          * complicated. I wanted however to do the reporting of *too
5294          * many* parameters here because we can easily use the precise
5295          * span of the N+1'th parameter.
5296          */
5297
5298         {
5299             let type_count = type_defs.len(space);
5300             assert_eq!(substs.types.len(space), 0);
5301             for (i, typ) in segment.types.iter().enumerate() {
5302                 let t = fcx.to_ty(&**typ);
5303                 if i < type_count {
5304                     substs.types.push(space, t);
5305                 } else if i == type_count {
5306                     span_err!(fcx.tcx().sess, typ.span, E0087,
5307                         "too many type parameters provided: \
5308                          expected at most {} parameter(s), \
5309                          found {} parameter(s)",
5310                          type_count, segment.types.len());
5311                     substs.types.truncate(space, 0);
5312                 }
5313             }
5314         }
5315
5316         {
5317             let region_count = region_defs.len(space);
5318             assert_eq!(substs.regions().len(space), 0);
5319             for (i, lifetime) in segment.lifetimes.iter().enumerate() {
5320                 let r = ast_region_to_region(fcx.tcx(), lifetime);
5321                 if i < region_count {
5322                     substs.mut_regions().push(space, r);
5323                 } else if i == region_count {
5324                     span_err!(fcx.tcx().sess, lifetime.span, E0088,
5325                         "too many lifetime parameters provided: \
5326                          expected {} parameter(s), found {} parameter(s)",
5327                         region_count,
5328                         segment.lifetimes.len());
5329                     substs.mut_regions().truncate(space, 0);
5330                 }
5331             }
5332         }
5333     }
5334
5335     fn adjust_type_parameters(
5336         fcx: &FnCtxt,
5337         span: Span,
5338         space: ParamSpace,
5339         defs: &VecPerParamSpace<ty::TypeParameterDef>,
5340         substs: &mut Substs)
5341     {
5342         let provided_len = substs.types.len(space);
5343         let desired = defs.get_slice(space);
5344         let required_len = desired.iter()
5345                               .take_while(|d| d.default.is_none())
5346                               .count();
5347
5348         debug!("adjust_type_parameters(space={}, \
5349                provided_len={}, \
5350                desired_len={}, \
5351                required_len={})",
5352                space,
5353                provided_len,
5354                desired.len(),
5355                required_len);
5356
5357         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5358         assert!(provided_len <= desired.len());
5359
5360         // Nothing specified at all: supply inference variables for
5361         // everything.
5362         if provided_len == 0 {
5363             substs.types.replace(space,
5364                                  fcx.infcx().next_ty_vars(desired.len()));
5365             return;
5366         }
5367
5368         // Too few parameters specified: report an error and use Err
5369         // for everything.
5370         if provided_len < required_len {
5371             let qualifier =
5372                 if desired.len() != required_len { "at least " } else { "" };
5373             span_err!(fcx.tcx().sess, span, E0089,
5374                 "too few type parameters provided: expected {}{} parameter(s) \
5375                 , found {} parameter(s)",
5376                 qualifier, required_len, provided_len);
5377             substs.types.replace(space,
5378                                  Vec::from_elem(desired.len(), ty::mk_err()));
5379             return;
5380         }
5381
5382         // Otherwise, add in any optional parameters that the user
5383         // omitted. The case of *too many* parameters is handled
5384         // already by
5385         // push_explicit_parameters_from_segment_to_substs(). Note
5386         // that the *default* type are expressed in terms of all prior
5387         // parameters, so we have to substitute as we go with the
5388         // partial substitution that we have built up.
5389         for i in range(provided_len, desired.len()) {
5390             let default = desired[i].default.unwrap();
5391             let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5392             substs.types.push(space, default);
5393         }
5394         assert_eq!(substs.types.len(space), desired.len());
5395
5396         debug!("Final substs: {}", substs.repr(fcx.tcx()));
5397     }
5398
5399     fn adjust_region_parameters(
5400         fcx: &FnCtxt,
5401         span: Span,
5402         space: ParamSpace,
5403         defs: &VecPerParamSpace<ty::RegionParameterDef>,
5404         substs: &mut Substs)
5405     {
5406         let provided_len = substs.mut_regions().len(space);
5407         let desired = defs.get_slice(space);
5408
5409         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5410         assert!(provided_len <= desired.len());
5411
5412         // If nothing was provided, just use inference variables.
5413         if provided_len == 0 {
5414             substs.mut_regions().replace(
5415                 space,
5416                 fcx.infcx().region_vars_for_defs(span, desired));
5417             return;
5418         }
5419
5420         // If just the right number were provided, everybody is happy.
5421         if provided_len == desired.len() {
5422             return;
5423         }
5424
5425         // Otherwise, too few were provided. Report an error and then
5426         // use inference variables.
5427         span_err!(fcx.tcx().sess, span, E0090,
5428             "too few lifetime parameters provided: expected {} parameter(s), \
5429              found {} parameter(s)",
5430             desired.len(), provided_len);
5431
5432         substs.mut_regions().replace(
5433             space,
5434             fcx.infcx().region_vars_for_defs(span, desired));
5435     }
5436 }
5437
5438 // Resolves `typ` by a single level if `typ` is a type variable.  If no
5439 // resolution is possible, then an error is reported.
5440 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
5441     match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
5442         Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
5443         _ => {
5444             fcx.type_error_message(sp, |_actual| {
5445                 "the type of this value must be known in this \
5446                  context".to_string()
5447             }, tp, None);
5448             demand::suptype(fcx, sp, ty::mk_err(), tp);
5449             tp
5450         }
5451     }
5452 }
5453
5454 // Returns the one-level-deep structure of the given type.
5455 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
5456                         -> &'a ty::sty {
5457     &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
5458 }
5459
5460 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5461     let typ_s = structurally_resolved_type(fcx, sp, typ);
5462     return ty::type_is_integral(typ_s);
5463 }
5464
5465 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5466     let typ_s = structurally_resolved_type(fcx, sp, typ);
5467     return ty::type_is_uint(typ_s);
5468 }
5469
5470 pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5471     let typ_s = structurally_resolved_type(fcx, sp, typ);
5472     return ty::type_is_scalar(typ_s);
5473 }
5474
5475 pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5476     let typ_s = structurally_resolved_type(fcx, sp, typ);
5477     return ty::type_is_char(typ_s);
5478 }
5479
5480 pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5481     let typ_s = structurally_resolved_type(fcx, sp, typ);
5482     return ty::type_is_bare_fn(typ_s);
5483 }
5484
5485 pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5486     let typ_s = structurally_resolved_type(fcx, sp, typ);
5487     return ty::type_is_floating_point(typ_s);
5488 }
5489
5490 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5491     let typ_s = structurally_resolved_type(fcx, sp, typ);
5492     return ty::type_is_unsafe_ptr(typ_s);
5493 }
5494
5495 pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5496     let typ_s = structurally_resolved_type(fcx, sp, typ);
5497     return ty::type_is_region_ptr(typ_s);
5498 }
5499
5500 pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5501     let typ_s = structurally_resolved_type(fcx, sp, typ);
5502     return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
5503 }
5504
5505 // Returns true if b contains a break that can exit from b
5506 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5507     // First: is there an unlabeled break immediately
5508     // inside the loop?
5509     (loop_query(&*b, |e| {
5510         match *e {
5511             ast::ExprBreak(_) => true,
5512             _ => false
5513         }
5514     })) ||
5515    // Second: is there a labeled break with label
5516    // <id> nested anywhere inside the loop?
5517     (block_query(b, |e| {
5518         match e.node {
5519             ast::ExprBreak(Some(_)) => {
5520                 match cx.def_map.borrow().find(&e.id) {
5521                     Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5522                     _ => false,
5523                 }
5524             }
5525             _ => false
5526         }}))
5527 }
5528
5529 pub fn check_bounds_are_used(ccx: &CrateCtxt,
5530                              span: Span,
5531                              tps: &OwnedSlice<ast::TyParam>,
5532                              ty: ty::t) {
5533     debug!("check_bounds_are_used(n_tps={}, ty={})",
5534            tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5535
5536     // make a vector of booleans initially false, set to true when used
5537     if tps.len() == 0u { return; }
5538     let mut tps_used = Vec::from_elem(tps.len(), false);
5539
5540     ty::walk_ty(ty, |t| {
5541             match ty::get(t).sty {
5542                 ty::ty_param(ParamTy {idx, ..}) => {
5543                     debug!("Found use of ty param num {}", idx);
5544                     *tps_used.get_mut(idx) = true;
5545                 }
5546                 _ => ()
5547             }
5548         });
5549
5550     for (i, b) in tps_used.iter().enumerate() {
5551         if !*b {
5552             span_err!(ccx.tcx.sess, span, E0091,
5553                 "type parameter `{}` is unused",
5554                 token::get_ident(tps.get(i).ident));
5555         }
5556     }
5557 }
5558
5559 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5560     fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
5561         ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5562     }
5563
5564     let tcx = ccx.tcx;
5565     let name = token::get_ident(it.ident);
5566     let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5567         let split : Vec<&str> = name.get().split('_').collect();
5568         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5569
5570         //We only care about the operation here
5571         match *split.get(1) {
5572             "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5573                                 param(ccx, 0),
5574                                 param(ccx, 0)),
5575                         param(ccx, 0)),
5576             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5577                        param(ccx, 0)),
5578             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5579                         ty::mk_nil()),
5580
5581             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
5582             "min"  | "umax" | "umin" => {
5583                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5584                  param(ccx, 0))
5585             }
5586             "fence" => {
5587                 (0, Vec::new(), ty::mk_nil())
5588             }
5589             op => {
5590                 span_err!(tcx.sess, it.span, E0092,
5591                     "unrecognized atomic operation function: `{}`", op);
5592                 return;
5593             }
5594         }
5595
5596     } else {
5597         match name.get() {
5598             "abort" => (0, Vec::new(), ty::mk_bot()),
5599             "breakpoint" => (0, Vec::new(), ty::mk_nil()),
5600             "size_of" |
5601             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5602             "init" => (1u, Vec::new(), param(ccx, 0u)),
5603             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5604             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
5605             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5606             "move_val_init" => {
5607                 (1u,
5608                  vec!(
5609                     ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
5610                     param(ccx, 0u)
5611                   ),
5612                ty::mk_nil())
5613             }
5614             "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5615             "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5616
5617             "get_tydesc" => {
5618               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5619                   Ok(t) => t,
5620                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5621               };
5622               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5623                   ty: tydesc_ty,
5624                   mutbl: ast::MutImmutable
5625               });
5626               (1u, Vec::new(), td_ptr)
5627             }
5628             "type_id" => {
5629                 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5630                 match langid {
5631                     Ok(did) => (1u,
5632                                 Vec::new(),
5633                                 ty::mk_struct(ccx.tcx, did,
5634                                               subst::Substs::empty())),
5635                     Err(msg) => {
5636                         tcx.sess.span_fatal(it.span, msg.as_slice());
5637                     }
5638                 }
5639             },
5640             "visit_tydesc" => {
5641               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5642                   Ok(t) => t,
5643                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5644               };
5645               let region0 = ty::ReLateBound(it.id, ty::BrAnon(0));
5646               let region1 = ty::ReLateBound(it.id, ty::BrAnon(1));
5647               let visitor_object_ty =
5648                     match ty::visitor_object_ty(tcx, region0, region1) {
5649                         Ok((_, vot)) => vot,
5650                         Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5651                     };
5652
5653               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5654                   ty: tydesc_ty,
5655                   mutbl: ast::MutImmutable
5656               });
5657               (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
5658             }
5659             "offset" => {
5660               (1,
5661                vec!(
5662                   ty::mk_ptr(tcx, ty::mt {
5663                       ty: param(ccx, 0),
5664                       mutbl: ast::MutImmutable
5665                   }),
5666                   ty::mk_int()
5667                ),
5668                ty::mk_ptr(tcx, ty::mt {
5669                    ty: param(ccx, 0),
5670                    mutbl: ast::MutImmutable
5671                }))
5672             }
5673             "copy_memory" | "copy_nonoverlapping_memory" |
5674             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5675               (1,
5676                vec!(
5677                   ty::mk_ptr(tcx, ty::mt {
5678                       ty: param(ccx, 0),
5679                       mutbl: ast::MutMutable
5680                   }),
5681                   ty::mk_ptr(tcx, ty::mt {
5682                       ty: param(ccx, 0),
5683                       mutbl: ast::MutImmutable
5684                   }),
5685                   ty::mk_uint()
5686                ),
5687                ty::mk_nil())
5688             }
5689             "set_memory" | "volatile_set_memory" => {
5690               (1,
5691                vec!(
5692                   ty::mk_ptr(tcx, ty::mt {
5693                       ty: param(ccx, 0),
5694                       mutbl: ast::MutMutable
5695                   }),
5696                   ty::mk_u8(),
5697                   ty::mk_uint()
5698                ),
5699                ty::mk_nil())
5700             }
5701             "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5702             "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5703             "powif32" => {
5704                (0,
5705                 vec!( ty::mk_f32(), ty::mk_i32() ),
5706                 ty::mk_f32())
5707             }
5708             "powif64" => {
5709                (0,
5710                 vec!( ty::mk_f64(), ty::mk_i32() ),
5711                 ty::mk_f64())
5712             }
5713             "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5714             "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5715             "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5716             "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5717             "powf32" => {
5718                (0,
5719                 vec!( ty::mk_f32(), ty::mk_f32() ),
5720                 ty::mk_f32())
5721             }
5722             "powf64" => {
5723                (0,
5724                 vec!( ty::mk_f64(), ty::mk_f64() ),
5725                 ty::mk_f64())
5726             }
5727             "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5728             "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5729             "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5730             "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5731             "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5732             "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5733             "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5734             "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5735             "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5736             "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5737             "fmaf32" => {
5738                 (0,
5739                  vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5740                  ty::mk_f32())
5741             }
5742             "fmaf64" => {
5743                 (0,
5744                  vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5745                  ty::mk_f64())
5746             }
5747             "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5748             "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5749             "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5750             "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5751             "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5752             "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5753             "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5754             "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5755             "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5756             "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5757             "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5758             "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5759             "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5760             "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5761             "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5762             "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5763             "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
5764             "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5765             "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5766             "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5767             "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
5768             "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5769             "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5770             "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5771             "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
5772             "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5773             "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5774             "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5775             "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5776             "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5777             "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5778
5779             "volatile_load" =>
5780                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5781             "volatile_store" =>
5782                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
5783
5784             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5785                 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5786                 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5787
5788             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5789                 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5790                 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5791
5792             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5793                 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5794                 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5795
5796             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5797                 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5798                 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5799
5800             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5801                 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5802                 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5803
5804             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5805                 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5806                 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5807
5808             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5809                 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5810                 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5811
5812             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
5813                 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5814                 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5815
5816             "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5817
5818             ref other => {
5819                 span_err!(tcx.sess, it.span, E0093,
5820                     "unrecognized intrinsic function: `{}`", *other);
5821                 return;
5822             }
5823         }
5824     };
5825     let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5826         fn_style: ast::UnsafeFn,
5827         abi: abi::RustIntrinsic,
5828         sig: FnSig {
5829             binder_id: it.id,
5830             inputs: inputs,
5831             output: output,
5832             variadic: false,
5833         }
5834     });
5835     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5836     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5837     if i_n_tps != n_tps {
5838         span_err!(tcx.sess, it.span, E0094,
5839             "intrinsic has wrong number of type \
5840              parameters: found {}, expected {}",
5841              i_n_tps, n_tps);
5842     } else {
5843         require_same_types(tcx,
5844                            None,
5845                            false,
5846                            it.span,
5847                            i_ty.ty,
5848                            fty,
5849                            || {
5850                 format!("intrinsic has wrong type: expected `{}`",
5851                         ppaux::ty_to_string(ccx.tcx, fty))
5852             });
5853     }
5854 }
5855
5856 impl Repr for RegionObligation {
5857     fn repr(&self, tcx: &ty::ctxt) -> String {
5858         format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5859                 self.sub_region.repr(tcx),
5860                 self.sup_type.repr(tcx),
5861                 self.origin.repr(tcx))
5862     }
5863 }