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