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