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