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