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