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