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