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