]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/mod.rs
librustc (RFC #34): Implement the new `Index` and `IndexMut` traits.
[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::DefStruct(type_def_id)) => {
3370                 check_struct_constructor(fcx, id, expr.span, type_def_id,
3371                                          fields.as_slice(), base_expr);
3372             }
3373             Some(def::DefVariant(enum_id, variant_id, _)) => {
3374                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3375                                           variant_id, fields.as_slice());
3376             }
3377             _ => {
3378                 tcx.sess.span_bug(path.span,
3379                                   "structure constructor does not name a structure type");
3380             }
3381         }
3382       }
3383       ast::ExprField(ref base, ref field, ref tys) => {
3384         check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3385       }
3386       ast::ExprIndex(ref base, ref idx) => {
3387           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3388           check_expr(fcx, &**idx);
3389           let raw_base_t = fcx.expr_ty(&**base);
3390           let idx_t = fcx.expr_ty(&**idx);
3391           if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3392               fcx.write_ty(id, raw_base_t);
3393           } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3394               fcx.write_ty(id, idx_t);
3395           } else {
3396               let (_, autoderefs, field_ty) =
3397                 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3398                           lvalue_pref, |base_t, _| ty::index(base_t));
3399               match field_ty {
3400                   Some(mt) => {
3401                       check_expr_has_type(fcx, &**idx, ty::mk_uint());
3402                       fcx.write_ty(id, mt.ty);
3403                       fcx.write_autoderef_adjustment(base.id, autoderefs);
3404                   }
3405                   None => {
3406                       // This is an overloaded method.
3407                       let base_t = structurally_resolved_type(fcx,
3408                                                               expr.span,
3409                                                               raw_base_t);
3410                       let method_call = MethodCall::expr(expr.id);
3411                       match try_overloaded_index(fcx,
3412                                                  Some(method_call),
3413                                                  expr,
3414                                                  *base,
3415                                                  base_t,
3416                                                  *idx,
3417                                                  lvalue_pref) {
3418                           Some(mt) => fcx.write_ty(id, mt.ty),
3419                           None => {
3420                                 fcx.type_error_message(expr.span,
3421                                                        |actual| {
3422                                                         format!("cannot \
3423                                                                  index a \
3424                                                                  value of \
3425                                                                  type `{}`",
3426                                                                 actual)
3427                                                        },
3428                                                        base_t,
3429                                                        None);
3430                                 fcx.write_ty(id, ty::mk_err())
3431                           }
3432                       }
3433                   }
3434               }
3435           }
3436        }
3437     }
3438
3439     debug!("type of expr({}) {} is...", expr.id,
3440            syntax::print::pprust::expr_to_str(expr));
3441     debug!("... {}, expected is {}",
3442            ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3443            expected.repr(tcx))
3444
3445     unifier();
3446 }
3447
3448 impl Expectation {
3449     fn only_has_type(self) -> Expectation {
3450         match self {
3451             NoExpectation | ExpectCastableToType(..) => NoExpectation,
3452             ExpectHasType(t) => ExpectHasType(t)
3453         }
3454     }
3455
3456     // Resolves `expected` by a single level if it is a variable. If
3457     // there is no expected type or resolution is not possible (e.g.,
3458     // no constraints yet present), just returns `None`.
3459     fn resolve(self, fcx: &FnCtxt) -> Expectation {
3460         match self {
3461             NoExpectation => {
3462                 NoExpectation
3463             }
3464             ExpectCastableToType(t) => {
3465                 ExpectCastableToType(
3466                     fcx.infcx().resolve_type_vars_if_possible(t))
3467             }
3468             ExpectHasType(t) => {
3469                 ExpectHasType(
3470                     fcx.infcx().resolve_type_vars_if_possible(t))
3471             }
3472         }
3473     }
3474
3475     fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3476         match self.resolve(fcx) {
3477             NoExpectation => NoExpectation,
3478             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3479         }
3480     }
3481
3482     fn map_to_option<O>(self,
3483                         fcx: &FnCtxt,
3484                         unpack: |&ty::sty| -> Option<O>)
3485                         -> Option<O>
3486     {
3487         match self.resolve(fcx) {
3488             NoExpectation => None,
3489             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3490         }
3491     }
3492 }
3493
3494 impl Repr for Expectation {
3495     fn repr(&self, tcx: &ty::ctxt) -> String {
3496         match *self {
3497             NoExpectation => format!("NoExpectation"),
3498             ExpectHasType(t) => format!("ExpectHasType({})",
3499                                         t.repr(tcx)),
3500             ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3501                                                t.repr(tcx)),
3502         }
3503     }
3504 }
3505
3506 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3507     if !type_is_uint(fcx, sp, t) {
3508         fcx.type_error_message(sp, |actual| {
3509             format!("mismatched types: expected `uint` type but found `{}`",
3510                     actual)
3511         }, t, None);
3512     }
3513 }
3514
3515 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3516     if !type_is_integral(fcx, sp, t) {
3517         fcx.type_error_message(sp, |actual| {
3518             format!("mismatched types: expected integral type but found `{}`",
3519                     actual)
3520         }, t, None);
3521     }
3522 }
3523
3524 pub fn check_decl_initializer(fcx: &FnCtxt,
3525                               nid: ast::NodeId,
3526                               init: &ast::Expr)
3527                             {
3528     let local_ty = fcx.local_ty(init.span, nid);
3529     check_expr_coercable_to_type(fcx, init, local_ty)
3530 }
3531
3532 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
3533     let tcx = fcx.ccx.tcx;
3534
3535     let t = fcx.local_ty(local.span, local.id);
3536     fcx.write_ty(local.id, t);
3537
3538     match local.init {
3539         Some(ref init) => {
3540             check_decl_initializer(fcx, local.id, &**init);
3541             let init_ty = fcx.expr_ty(&**init);
3542             if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3543                 fcx.write_ty(local.id, init_ty);
3544             }
3545         }
3546         _ => {}
3547     }
3548
3549     let pcx = pat_ctxt {
3550         fcx: fcx,
3551         map: pat_id_map(&tcx.def_map, &*local.pat),
3552     };
3553     _match::check_pat(&pcx, &*local.pat, t);
3554     let pat_ty = fcx.node_ty(local.pat.id);
3555     if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3556         fcx.write_ty(local.id, pat_ty);
3557     }
3558 }
3559
3560 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
3561     let node_id;
3562     let mut saw_bot = false;
3563     let mut saw_err = false;
3564     match stmt.node {
3565       ast::StmtDecl(decl, id) => {
3566         node_id = id;
3567         match decl.node {
3568           ast::DeclLocal(ref l) => {
3569               check_decl_local(fcx, &**l);
3570               let l_t = fcx.node_ty(l.id);
3571               saw_bot = saw_bot || ty::type_is_bot(l_t);
3572               saw_err = saw_err || ty::type_is_error(l_t);
3573           }
3574           ast::DeclItem(_) => {/* ignore for now */ }
3575         }
3576       }
3577       ast::StmtExpr(ref expr, id) => {
3578         node_id = id;
3579         // Check with expected type of ()
3580         check_expr_has_type(fcx, &**expr, ty::mk_nil());
3581         let expr_ty = fcx.expr_ty(&**expr);
3582         saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3583         saw_err = saw_err || ty::type_is_error(expr_ty);
3584       }
3585       ast::StmtSemi(ref expr, id) => {
3586         node_id = id;
3587         check_expr(fcx, &**expr);
3588         let expr_ty = fcx.expr_ty(&**expr);
3589         saw_bot |= ty::type_is_bot(expr_ty);
3590         saw_err |= ty::type_is_error(expr_ty);
3591       }
3592       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3593     }
3594     if saw_bot {
3595         fcx.write_bot(node_id);
3596     }
3597     else if saw_err {
3598         fcx.write_error(node_id);
3599     }
3600     else {
3601         fcx.write_nil(node_id)
3602     }
3603 }
3604
3605 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
3606     check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3607     let blkty = fcx.node_ty(blk.id);
3608     if ty::type_is_error(blkty) {
3609         fcx.write_error(blk.id);
3610     }
3611     else if ty::type_is_bot(blkty) {
3612         fcx.write_bot(blk.id);
3613     }
3614     else {
3615         let nilty = ty::mk_nil();
3616         demand::suptype(fcx, blk.span, nilty, blkty);
3617     }
3618 }
3619
3620 fn check_block_with_expected(fcx: &FnCtxt,
3621                              blk: &ast::Block,
3622                              expected: Expectation) {
3623     let prev = {
3624         let mut fcx_ps = fcx.ps.borrow_mut();
3625         let fn_style_state = fcx_ps.recurse(blk);
3626         replace(&mut *fcx_ps, fn_style_state)
3627     };
3628
3629     fcx.with_region_lb(blk.id, || {
3630         let mut warned = false;
3631         let mut last_was_bot = false;
3632         let mut any_bot = false;
3633         let mut any_err = false;
3634         for s in blk.stmts.iter() {
3635             check_stmt(fcx, &**s);
3636             let s_id = ast_util::stmt_id(&**s);
3637             let s_ty = fcx.node_ty(s_id);
3638             if last_was_bot && !warned && match s.node {
3639                   ast::StmtDecl(decl, _) => {
3640                       match decl.node {
3641                           ast::DeclLocal(_) => true,
3642                           _ => false,
3643                       }
3644                   }
3645                   ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3646                   _ => false
3647                 } {
3648                 fcx.ccx
3649                    .tcx
3650                    .sess
3651                    .add_lint(lint::builtin::UNREACHABLE_CODE,
3652                              s_id,
3653                              s.span,
3654                              "unreachable statement".to_string());
3655                 warned = true;
3656             }
3657             if ty::type_is_bot(s_ty) {
3658                 last_was_bot = true;
3659             }
3660             any_bot = any_bot || ty::type_is_bot(s_ty);
3661             any_err = any_err || ty::type_is_error(s_ty);
3662         }
3663         match blk.expr {
3664             None => if any_err {
3665                 fcx.write_error(blk.id);
3666             }
3667             else if any_bot {
3668                 fcx.write_bot(blk.id);
3669             }
3670             else  {
3671                 fcx.write_nil(blk.id);
3672             },
3673           Some(e) => {
3674             if any_bot && !warned {
3675                 fcx.ccx
3676                    .tcx
3677                    .sess
3678                    .add_lint(lint::builtin::UNREACHABLE_CODE,
3679                              e.id,
3680                              e.span,
3681                              "unreachable expression".to_string());
3682             }
3683             check_expr_with_expectation(fcx, e, expected);
3684               let ety = fcx.expr_ty(e);
3685               fcx.write_ty(blk.id, ety);
3686               if any_err {
3687                   fcx.write_error(blk.id);
3688               }
3689               else if any_bot {
3690                   fcx.write_bot(blk.id);
3691               }
3692           }
3693         };
3694     });
3695
3696     *fcx.ps.borrow_mut() = prev;
3697 }
3698
3699 pub fn check_const(ccx: &CrateCtxt,
3700                    sp: Span,
3701                    e: &ast::Expr,
3702                    id: ast::NodeId) {
3703     let inh = blank_inherited_fields(ccx);
3704     let rty = ty::node_id_to_type(ccx.tcx, id);
3705     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3706     let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3707     check_const_with_ty(&fcx, sp, e, declty);
3708 }
3709
3710 pub fn check_const_with_ty(fcx: &FnCtxt,
3711                            _: Span,
3712                            e: &ast::Expr,
3713                            declty: ty::t) {
3714     // Gather locals in statics (because of block expressions).
3715     // This is technically unnecessary because locals in static items are forbidden,
3716     // but prevents type checking from blowing up before const checking can properly
3717     // emit a error.
3718     GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3719
3720     check_expr(fcx, e);
3721     let cty = fcx.expr_ty(e);
3722     demand::suptype(fcx, e.span, declty, cty);
3723     regionck::regionck_expr(fcx, e);
3724     writeback::resolve_type_vars_in_expr(fcx, e);
3725 }
3726
3727 /// Checks whether a type can be represented in memory. In particular, it
3728 /// identifies types that contain themselves without indirection through a
3729 /// pointer, which would mean their size is unbounded. This is different from
3730 /// the question of whether a type can be instantiated. See the definition of
3731 /// `check_instantiable`.
3732 pub fn check_representable(tcx: &ty::ctxt,
3733                            sp: Span,
3734                            item_id: ast::NodeId,
3735                            designation: &str) -> bool {
3736     let rty = ty::node_id_to_type(tcx, item_id);
3737
3738     // Check that it is possible to represent this type. This call identifies
3739     // (1) types that contain themselves and (2) types that contain a different
3740     // recursive type. It is only necessary to throw an error on those that
3741     // contain themselves. For case 2, there must be an inner type that will be
3742     // caught by case 1.
3743     match ty::is_type_representable(tcx, sp, rty) {
3744       ty::SelfRecursive => {
3745         tcx.sess.span_err(
3746           sp, format!("illegal recursive {} type; \
3747                        wrap the inner value in a box to make it representable",
3748                       designation).as_slice());
3749         return false
3750       }
3751       ty::Representable | ty::ContainsRecursive => (),
3752     }
3753     return true
3754 }
3755
3756 /// Checks whether a type can be created without an instance of itself.
3757 /// This is similar but different from the question of whether a type
3758 /// can be represented.  For example, the following type:
3759 ///
3760 ///     enum foo { None, Some(foo) }
3761 ///
3762 /// is instantiable but is not representable.  Similarly, the type
3763 ///
3764 ///     enum foo { Some(@foo) }
3765 ///
3766 /// is representable, but not instantiable.
3767 pub fn check_instantiable(tcx: &ty::ctxt,
3768                           sp: Span,
3769                           item_id: ast::NodeId)
3770                           -> bool {
3771     let item_ty = ty::node_id_to_type(tcx, item_id);
3772     if !ty::is_instantiable(tcx, item_ty) {
3773         tcx.sess
3774            .span_err(sp,
3775                      format!("this type cannot be instantiated without an \
3776                               instance of itself; consider using \
3777                               `Option<{}>`",
3778                              ppaux::ty_to_str(tcx, item_ty)).as_slice());
3779         false
3780     } else {
3781         true
3782     }
3783 }
3784
3785 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3786     let t = ty::node_id_to_type(tcx, id);
3787     if ty::type_needs_subst(t) {
3788         tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3789         return;
3790     }
3791     match ty::get(t).sty {
3792         ty::ty_struct(did, ref substs) => {
3793             let fields = ty::lookup_struct_fields(tcx, did);
3794             if fields.is_empty() {
3795                 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3796                 return;
3797             }
3798             let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3799             if !fields.iter().all(
3800                          |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3801                 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3802                 return;
3803             }
3804             if !ty::type_is_machine(e) {
3805                 tcx.sess.span_err(sp, "SIMD vector element type should be \
3806                                        machine type");
3807                 return;
3808             }
3809         }
3810         _ => ()
3811     }
3812 }
3813
3814 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3815                                  vs: &[ast::P<ast::Variant>]) {
3816     for &v in vs.iter() {
3817         match v.node.kind {
3818             ast::TupleVariantKind(ref args) if args.len() > 0 => {
3819                 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3820                 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3821                 let len = arg_tys.len();
3822                 if len == 0 {
3823                     return;
3824                 }
3825                 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3826                     // Allow the last field in an enum to be unsized.
3827                     // We want to do this so that we can support smart pointers.
3828                     // A struct value with an unsized final field is itself
3829                     // unsized and we must track this in the type system.
3830                     if !ty::type_is_sized(ccx.tcx, *t) {
3831                         ccx.tcx
3832                            .sess
3833                            .span_err(
3834                                args.get(i).ty.span,
3835                                format!("type `{}` is dynamically sized. \
3836                                         dynamically sized types may only \
3837                                         appear as the final type in a \
3838                                         variant",
3839                                        ppaux::ty_to_str(ccx.tcx,
3840                                                         *t)).as_slice());
3841                     }
3842                 }
3843             },
3844             ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3845             _ => {}
3846         }
3847     }
3848 }
3849
3850 pub fn check_enum_variants(ccx: &CrateCtxt,
3851                            sp: Span,
3852                            vs: &[ast::P<ast::Variant>],
3853                            id: ast::NodeId) {
3854
3855     fn disr_in_range(ccx: &CrateCtxt,
3856                      ty: attr::IntType,
3857                      disr: ty::Disr) -> bool {
3858         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3859             match ty {
3860                 ast::TyU8 => disr as u8 as Disr == disr,
3861                 ast::TyU16 => disr as u16 as Disr == disr,
3862                 ast::TyU32 => disr as u32 as Disr == disr,
3863                 ast::TyU64 => disr as u64 as Disr == disr,
3864                 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3865             }
3866         }
3867         fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3868             match ty {
3869                 ast::TyI8 => disr as i8 as Disr == disr,
3870                 ast::TyI16 => disr as i16 as Disr == disr,
3871                 ast::TyI32 => disr as i32 as Disr == disr,
3872                 ast::TyI64 => disr as i64 as Disr == disr,
3873                 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3874             }
3875         }
3876         match ty {
3877             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3878             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3879         }
3880     }
3881
3882     fn do_check(ccx: &CrateCtxt,
3883                 vs: &[ast::P<ast::Variant>],
3884                 id: ast::NodeId,
3885                 hint: attr::ReprAttr)
3886                 -> Vec<Rc<ty::VariantInfo>> {
3887
3888         let rty = ty::node_id_to_type(ccx.tcx, id);
3889         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3890         let mut disr_vals: Vec<ty::Disr> = Vec::new();
3891         let mut prev_disr_val: Option<ty::Disr> = None;
3892
3893         for &v in vs.iter() {
3894
3895             // If the discriminant value is specified explicitly in the enum check whether the
3896             // initialization expression is valid, otherwise use the last value plus one.
3897             let mut current_disr_val = match prev_disr_val {
3898                 Some(prev_disr_val) => prev_disr_val + 1,
3899                 None => ty::INITIAL_DISCRIMINANT_VALUE
3900             };
3901
3902             match v.node.disr_expr {
3903                 Some(e) => {
3904                     debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3905
3906                     let inh = blank_inherited_fields(ccx);
3907                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3908                     let declty = match hint {
3909                         attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3910                         attr::ReprInt(_, attr::SignedInt(ity)) => {
3911                             ty::mk_mach_int(ity)
3912                         }
3913                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3914                             ty::mk_mach_uint(ity)
3915                         }
3916                     };
3917                     check_const_with_ty(&fcx, e.span, &*e, declty);
3918                     // check_expr (from check_const pass) doesn't guarantee
3919                     // that the expression is in a form that eval_const_expr can
3920                     // handle, so we may still get an internal compiler error
3921
3922                     match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3923                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3924                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3925                         Ok(_) => {
3926                             ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3927                         }
3928                         Err(ref err) => {
3929                             ccx.tcx
3930                                .sess
3931                                .span_err(e.span,
3932                                          format!("expected constant: {}",
3933                                                  *err).as_slice());
3934                         }
3935                     }
3936                 },
3937                 None => ()
3938             };
3939
3940             // Check for duplicate discriminant values
3941             if disr_vals.contains(&current_disr_val) {
3942                 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3943             }
3944             // Check for unrepresentable discriminant values
3945             match hint {
3946                 attr::ReprAny | attr::ReprExtern => (),
3947                 attr::ReprInt(sp, ity) => {
3948                     if !disr_in_range(ccx, ity, current_disr_val) {
3949                         ccx.tcx.sess.span_err(v.span,
3950                                               "discriminant value outside specified type");
3951                         ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3952                     }
3953                 }
3954             }
3955             disr_vals.push(current_disr_val);
3956
3957             let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3958                                                                      current_disr_val));
3959             prev_disr_val = Some(current_disr_val);
3960
3961             variants.push(variant_info);
3962         }
3963
3964         return variants;
3965     }
3966
3967     let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3968     if hint != attr::ReprAny && vs.len() <= 1 {
3969         let msg = if vs.len() == 1 {
3970             "unsupported representation for univariant enum"
3971         } else {
3972             "unsupported representation for zero-variant enum"
3973         };
3974         ccx.tcx.sess.span_err(sp, msg)
3975     }
3976
3977     let variants = do_check(ccx, vs, id, hint);
3978
3979     // cache so that ty::enum_variants won't repeat this work
3980     ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3981
3982     check_representable(ccx.tcx, sp, id, "enum");
3983
3984     // Check that it is possible to instantiate this enum:
3985     //
3986     // This *sounds* like the same that as representable, but it's
3987     // not.  See def'n of `check_instantiable()` for details.
3988     check_instantiable(ccx.tcx, sp, id);
3989 }
3990
3991 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3992     lookup_def_ccx(fcx.ccx, sp, id)
3993 }
3994
3995 // Returns the type parameter count and the type for the given definition.
3996 pub fn polytype_for_def(fcx: &FnCtxt,
3997                         sp: Span,
3998                         defn: def::Def)
3999                         -> Polytype {
4000     match defn {
4001       def::DefArg(nid, _) | def::DefLocal(nid, _) |
4002       def::DefBinding(nid, _) => {
4003           let typ = fcx.local_ty(sp, nid);
4004           return no_params(typ);
4005       }
4006       def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4007       def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4008       def::DefStruct(id) => {
4009         return ty::lookup_item_type(fcx.ccx.tcx, id);
4010       }
4011       def::DefUpvar(_, inner, _, _) => {
4012         return polytype_for_def(fcx, sp, *inner);
4013       }
4014       def::DefTrait(_) |
4015       def::DefTy(_) |
4016       def::DefPrimTy(_) |
4017       def::DefTyParam(..)=> {
4018         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4019       }
4020       def::DefMod(..) | def::DefForeignMod(..) => {
4021         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4022       }
4023       def::DefUse(..) => {
4024         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4025       }
4026       def::DefRegion(..) => {
4027         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4028       }
4029       def::DefTyParamBinder(..) => {
4030         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4031       }
4032       def::DefLabel(..) => {
4033         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4034       }
4035       def::DefSelfTy(..) => {
4036         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4037       }
4038       def::DefMethod(..) => {
4039         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4040       }
4041     }
4042 }
4043
4044 // Instantiates the given path, which must refer to an item with the given
4045 // number of type parameters and type.
4046 pub fn instantiate_path(fcx: &FnCtxt,
4047                         path: &ast::Path,
4048                         polytype: Polytype,
4049                         def: def::Def,
4050                         span: Span,
4051                         node_id: ast::NodeId) {
4052     debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4053            path.repr(fcx.tcx()),
4054            def.repr(fcx.tcx()),
4055            node_id,
4056            polytype.repr(fcx.tcx()));
4057
4058     // We need to extract the type parameters supplied by the user in
4059     // the path `path`. Due to the current setup, this is a bit of a
4060     // tricky-process; the problem is that resolve only tells us the
4061     // end-point of the path resolution, and not the intermediate steps.
4062     // Luckily, we can (at least for now) deduce the intermediate steps
4063     // just from the end-point.
4064     //
4065     // There are basically three cases to consider:
4066     //
4067     // 1. Reference to a *type*, such as a struct or enum:
4068     //
4069     //        mod a { struct Foo<T> { ... } }
4070     //
4071     //    Because we don't allow types to be declared within one
4072     //    another, a path that leads to a type will always look like
4073     //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
4074     //    that only the final segment can have type parameters, and
4075     //    they are located in the TypeSpace.
4076     //
4077     //    *Note:* Generally speaking, references to types don't
4078     //    actually pass through this function, but rather the
4079     //    `ast_ty_to_ty` function in `astconv`. However, in the case
4080     //    of struct patterns (and maybe literals) we do invoke
4081     //    `instantiate_path` to get the general type of an instance of
4082     //    a struct. (In these cases, there are actually no type
4083     //    parameters permitted at present, but perhaps we will allow
4084     //    them in the future.)
4085     //
4086     // 1b. Reference to a enum variant or tuple-like struct:
4087     //
4088     //        struct foo<T>(...)
4089     //        enum E<T> { foo(...) }
4090     //
4091     //    In these cases, the parameters are declared in the type
4092     //    space.
4093     //
4094     // 2. Reference to a *fn item*:
4095     //
4096     //        fn foo<T>() { }
4097     //
4098     //    In this case, the path will again always have the form
4099     //    `a::b::foo::<T>` where only the final segment should have
4100     //    type parameters. However, in this case, those parameters are
4101     //    declared on a value, and hence are in the `FnSpace`.
4102     //
4103     // 3. Reference to a *method*:
4104     //
4105     //        impl<A> SomeStruct<A> {
4106     //            fn foo<B>(...)
4107     //        }
4108     //
4109     //    Here we can have a path like
4110     //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4111     //    may appear in two places. The penultimate segment,
4112     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4113     //    final segment, `foo::<B>` contains parameters in fn space.
4114     //
4115     // The first step then is to categorize the segments appropriately.
4116
4117     assert!(path.segments.len() >= 1);
4118     let mut segment_spaces;
4119     match def {
4120         // Case 1 and 1b. Reference to a *type* or *enum variant*.
4121         def::DefSelfTy(..) |
4122         def::DefStruct(..) |
4123         def::DefVariant(..) |
4124         def::DefTyParamBinder(..) |
4125         def::DefTy(..) |
4126         def::DefTrait(..) |
4127         def::DefPrimTy(..) |
4128         def::DefTyParam(..) => {
4129             // Everything but the final segment should have no
4130             // parameters at all.
4131             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4132             segment_spaces.push(Some(subst::TypeSpace));
4133         }
4134
4135         // Case 2. Reference to a top-level value.
4136         def::DefFn(..) |
4137         def::DefStatic(..) => {
4138             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4139             segment_spaces.push(Some(subst::FnSpace));
4140         }
4141
4142         // Case 3. Reference to a method.
4143         def::DefStaticMethod(..) => {
4144             assert!(path.segments.len() >= 2);
4145             segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4146             segment_spaces.push(Some(subst::TypeSpace));
4147             segment_spaces.push(Some(subst::FnSpace));
4148         }
4149
4150         // Other cases. Various nonsense that really shouldn't show up
4151         // here. If they do, an error will have been reported
4152         // elsewhere. (I hope)
4153         def::DefMod(..) |
4154         def::DefForeignMod(..) |
4155         def::DefArg(..) |
4156         def::DefLocal(..) |
4157         def::DefMethod(..) |
4158         def::DefBinding(..) |
4159         def::DefUse(..) |
4160         def::DefRegion(..) |
4161         def::DefLabel(..) |
4162         def::DefUpvar(..) => {
4163             segment_spaces = Vec::from_elem(path.segments.len(), None);
4164         }
4165     }
4166     assert_eq!(segment_spaces.len(), path.segments.len());
4167
4168     debug!("segment_spaces={}", segment_spaces);
4169
4170     // Next, examine the definition, and determine how many type
4171     // parameters we expect from each space.
4172     let type_defs = &polytype.generics.types;
4173     let region_defs = &polytype.generics.regions;
4174
4175     // Now that we have categorized what space the parameters for each
4176     // segment belong to, let's sort out the parameters that the user
4177     // provided (if any) into their appropriate spaces. We'll also report
4178     // errors if type parameters are provided in an inappropriate place.
4179     let mut substs = Substs::empty();
4180     for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4181         match *opt_space {
4182             None => {
4183                 report_error_if_segment_contains_type_parameters(fcx, segment);
4184             }
4185
4186             Some(space) => {
4187                 push_explicit_parameters_from_segment_to_substs(fcx,
4188                                                                 space,
4189                                                                 type_defs,
4190                                                                 region_defs,
4191                                                                 segment,
4192                                                                 &mut substs);
4193             }
4194         }
4195     }
4196
4197     // Now we have to compare the types that the user *actually*
4198     // provided against the types that were *expected*. If the user
4199     // did not provide any types, then we want to substitute inference
4200     // variables. If the user provided some types, we may still need
4201     // to add defaults. If the user provided *too many* types, that's
4202     // a problem.
4203     for &space in ParamSpace::all().iter() {
4204         adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4205         assert_eq!(substs.types.len(space), type_defs.len(space));
4206
4207         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4208         assert_eq!(substs.regions().len(space), region_defs.len(space));
4209     }
4210
4211     fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4212         substs: substs,
4213     });
4214
4215     fn report_error_if_segment_contains_type_parameters(
4216         fcx: &FnCtxt,
4217         segment: &ast::PathSegment)
4218     {
4219         for typ in segment.types.iter() {
4220             fcx.tcx().sess.span_err(
4221                 typ.span,
4222                 "type parameters may not appear here");
4223             break;
4224         }
4225
4226         for lifetime in segment.lifetimes.iter() {
4227             fcx.tcx().sess.span_err(
4228                 lifetime.span,
4229                 "lifetime parameters may not appear here");
4230             break;
4231         }
4232     }
4233
4234     fn push_explicit_parameters_from_segment_to_substs(
4235         fcx: &FnCtxt,
4236         space: subst::ParamSpace,
4237         type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4238         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4239         segment: &ast::PathSegment,
4240         substs: &mut Substs)
4241     {
4242         /*!
4243          * Finds the parameters that the user provided and adds them
4244          * to `substs`. If too many parameters are provided, then
4245          * reports an error and clears the output vector.
4246          *
4247          * We clear the output vector because that will cause the
4248          * `adjust_XXX_parameters()` later to use inference
4249          * variables. This seems less likely to lead to derived
4250          * errors.
4251          *
4252          * Note that we *do not* check for *too few* parameters here.
4253          * Due to the presence of defaults etc that is more
4254          * complicated. I wanted however to do the reporting of *too
4255          * many* parameters here because we can easily use the precise
4256          * span of the N+1'th parameter.
4257          */
4258
4259         {
4260             let type_count = type_defs.len(space);
4261             assert_eq!(substs.types.len(space), 0);
4262             for (i, &typ) in segment.types.iter().enumerate() {
4263                 let t = fcx.to_ty(&*typ);
4264                 if i < type_count {
4265                     substs.types.push(space, t);
4266                 } else if i == type_count {
4267                     fcx.tcx().sess.span_err(
4268                         typ.span,
4269                         format!(
4270                             "too many type parameters provided: \
4271                              expected at most {} parameter(s) \
4272                              but found {} parameter(s)",
4273                             type_count,
4274                             segment.types.len()).as_slice());
4275                     substs.types.truncate(space, 0);
4276                 }
4277             }
4278         }
4279
4280         {
4281             let region_count = region_defs.len(space);
4282             assert_eq!(substs.regions().len(space), 0);
4283             for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4284                 let r = ast_region_to_region(fcx.tcx(), lifetime);
4285                 if i < region_count {
4286                     substs.mut_regions().push(space, r);
4287                 } else if i == region_count {
4288                     fcx.tcx().sess.span_err(
4289                         lifetime.span,
4290                         format!(
4291                             "too many lifetime parameters provided: \
4292                              expected {} parameter(s) but found {} parameter(s)",
4293                             region_count,
4294                             segment.lifetimes.len()).as_slice());
4295                     substs.mut_regions().truncate(space, 0);
4296                 }
4297             }
4298         }
4299     }
4300
4301     fn adjust_type_parameters(
4302         fcx: &FnCtxt,
4303         span: Span,
4304         space: ParamSpace,
4305         defs: &VecPerParamSpace<ty::TypeParameterDef>,
4306         substs: &mut Substs)
4307     {
4308         let provided_len = substs.types.len(space);
4309         let desired = defs.get_slice(space);
4310         let required_len = desired.iter()
4311                               .take_while(|d| d.default.is_none())
4312                               .count();
4313
4314         debug!("adjust_type_parameters(space={}, \
4315                provided_len={}, \
4316                desired_len={}, \
4317                required_len={})",
4318                space,
4319                provided_len,
4320                desired.len(),
4321                required_len);
4322
4323         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4324         assert!(provided_len <= desired.len());
4325
4326         // Nothing specified at all: supply inference variables for
4327         // everything.
4328         if provided_len == 0 {
4329             substs.types.replace(space,
4330                                  fcx.infcx().next_ty_vars(desired.len()));
4331             return;
4332         }
4333
4334         // Too few parameters specified: report an error and use Err
4335         // for everything.
4336         if provided_len < required_len {
4337             let qualifier =
4338                 if desired.len() != required_len { "at least " } else { "" };
4339             fcx.tcx().sess.span_err(
4340                 span,
4341                 format!("too few type parameters provided: \
4342                              expected {}{} parameter(s) \
4343                              but found {} parameter(s)",
4344                             qualifier,
4345                             required_len,
4346                             provided_len).as_slice());
4347             substs.types.replace(space,
4348                                  Vec::from_elem(desired.len(), ty::mk_err()));
4349             return;
4350         }
4351
4352         // Otherwise, add in any optional parameters that the user
4353         // omitted. The case of *too many* parameters is handled
4354         // already by
4355         // push_explicit_parameters_from_segment_to_substs(). Note
4356         // that the *default* type are expressed in terms of all prior
4357         // parameters, so we have to substitute as we go with the
4358         // partial substitution that we have built up.
4359         for i in range(provided_len, desired.len()) {
4360             let default = desired[i].default.unwrap();
4361             let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4362             substs.types.push(space, default);
4363         }
4364         assert_eq!(substs.types.len(space), desired.len());
4365
4366         debug!("Final substs: {}", substs.repr(fcx.tcx()));
4367     }
4368
4369     fn adjust_region_parameters(
4370         fcx: &FnCtxt,
4371         span: Span,
4372         space: ParamSpace,
4373         defs: &VecPerParamSpace<ty::RegionParameterDef>,
4374         substs: &mut Substs)
4375     {
4376         let provided_len = substs.mut_regions().len(space);
4377         let desired = defs.get_slice(space);
4378
4379         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4380         assert!(provided_len <= desired.len());
4381
4382         // If nothing was provided, just use inference variables.
4383         if provided_len == 0 {
4384             substs.mut_regions().replace(
4385                 space,
4386                 fcx.infcx().region_vars_for_defs(span, desired));
4387             return;
4388         }
4389
4390         // If just the right number were provided, everybody is happy.
4391         if provided_len == desired.len() {
4392             return;
4393         }
4394
4395         // Otherwise, too few were provided. Report an error and then
4396         // use inference variables.
4397         fcx.tcx().sess.span_err(
4398             span,
4399             format!(
4400                 "too few lifetime parameters provided: \
4401                          expected {} parameter(s) \
4402                          but found {} parameter(s)",
4403                 desired.len(),
4404                 provided_len).as_slice());
4405
4406         substs.mut_regions().replace(
4407             space,
4408             fcx.infcx().region_vars_for_defs(span, desired));
4409     }
4410 }
4411
4412 // Resolves `typ` by a single level if `typ` is a type variable.  If no
4413 // resolution is possible, then an error is reported.
4414 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4415     match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4416         Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4417         _ => {
4418             fcx.type_error_message(sp, |_actual| {
4419                 "the type of this value must be known in this \
4420                  context".to_string()
4421             }, tp, None);
4422             demand::suptype(fcx, sp, ty::mk_err(), tp);
4423             tp
4424         }
4425     }
4426 }
4427
4428 // Returns the one-level-deep structure of the given type.
4429 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4430                         -> &'a ty::sty {
4431     &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4432 }
4433
4434 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4435     let typ_s = structurally_resolved_type(fcx, sp, typ);
4436     return ty::type_is_integral(typ_s);
4437 }
4438
4439 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4440     let typ_s = structurally_resolved_type(fcx, sp, typ);
4441     return ty::type_is_uint(typ_s);
4442 }
4443
4444 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4445                              e: &ast::Expr,
4446                              v: ast::ExprVstore,
4447                              mk_inner: || -> ty::mt)
4448                              -> ty::t {
4449     match v {
4450         ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4451         ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4452             match e.node {
4453                 ast::ExprLit(..) => {
4454                     // string literals and *empty slices* live in static memory
4455                     ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4456                 }
4457                 ast::ExprVec(ref elements) if elements.len() == 0 => {
4458                     // string literals and *empty slices* live in static memory
4459                     ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4460                 }
4461                 ast::ExprRepeat(..) |
4462                 ast::ExprVec(..) => {
4463                     // vector literals are temporaries on the stack
4464                     match fcx.tcx().region_maps.temporary_scope(e.id) {
4465                         Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4466                         None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4467                     }
4468                 }
4469                 _ => {
4470                     fcx.ccx.tcx.sess.span_bug(e.span,
4471                                               "vstore with unexpected \
4472                                                contents")
4473                 }
4474             }
4475         }
4476     }
4477 }
4478
4479 // Returns true if b contains a break that can exit from b
4480 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4481     // First: is there an unlabeled break immediately
4482     // inside the loop?
4483     (loop_query(&*b, |e| {
4484         match *e {
4485             ast::ExprBreak(_) => true,
4486             _ => false
4487         }
4488     })) ||
4489    // Second: is there a labeled break with label
4490    // <id> nested anywhere inside the loop?
4491     (block_query(b, |e| {
4492         match e.node {
4493             ast::ExprBreak(Some(_)) => {
4494                 match cx.def_map.borrow().find(&e.id) {
4495                     Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4496                     _ => false,
4497                 }
4498             }
4499             _ => false
4500         }}))
4501 }
4502
4503 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4504                              span: Span,
4505                              tps: &OwnedSlice<ast::TyParam>,
4506                              ty: ty::t) {
4507     debug!("check_bounds_are_used(n_tps={}, ty={})",
4508            tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4509
4510     // make a vector of booleans initially false, set to true when used
4511     if tps.len() == 0u { return; }
4512     let mut tps_used = Vec::from_elem(tps.len(), false);
4513
4514     ty::walk_ty(ty, |t| {
4515             match ty::get(t).sty {
4516                 ty::ty_param(ParamTy {idx, ..}) => {
4517                     debug!("Found use of ty param num {}", idx);
4518                     *tps_used.get_mut(idx) = true;
4519                 }
4520                 _ => ()
4521             }
4522         });
4523
4524     for (i, b) in tps_used.iter().enumerate() {
4525         if !*b {
4526             ccx.tcx.sess.span_err(
4527                 span,
4528                 format!("type parameter `{}` is unused",
4529                         token::get_ident(tps.get(i).ident)).as_slice());
4530         }
4531     }
4532 }
4533
4534 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4535     fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4536         ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4537     }
4538
4539     let tcx = ccx.tcx;
4540     let name = token::get_ident(it.ident);
4541     let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4542         let split : Vec<&str> = name.get().split('_').collect();
4543         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4544
4545         //We only care about the operation here
4546         match *split.get(1) {
4547             "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4548                                 param(ccx, 0),
4549                                 param(ccx, 0)),
4550                         param(ccx, 0)),
4551             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4552                        param(ccx, 0)),
4553             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4554                         ty::mk_nil()),
4555
4556             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
4557             "min"  | "umax" | "umin" => {
4558                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4559                  param(ccx, 0))
4560             }
4561             "fence" => {
4562                 (0, Vec::new(), ty::mk_nil())
4563             }
4564             op => {
4565                 tcx.sess.span_err(it.span,
4566                                   format!("unrecognized atomic operation \
4567                                            function: `{}`",
4568                                           op).as_slice());
4569                 return;
4570             }
4571         }
4572
4573     } else {
4574         match name.get() {
4575             "abort" => (0, Vec::new(), ty::mk_bot()),
4576             "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4577             "size_of" |
4578             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4579             "init" => (1u, Vec::new(), param(ccx, 0u)),
4580             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4581             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4582             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4583             "move_val_init" => {
4584                 (1u,
4585                  vec!(
4586                     ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4587                     param(ccx, 0u)
4588                   ),
4589                ty::mk_nil())
4590             }
4591             "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4592             "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4593
4594             "get_tydesc" => {
4595               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4596                   Ok(t) => t,
4597                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4598               };
4599               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4600                   ty: tydesc_ty,
4601                   mutbl: ast::MutImmutable
4602               });
4603               (1u, Vec::new(), td_ptr)
4604             }
4605             "type_id" => {
4606                 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4607                 match langid {
4608                     Ok(did) => (1u,
4609                                 Vec::new(),
4610                                 ty::mk_struct(ccx.tcx, did,
4611                                               subst::Substs::empty())),
4612                     Err(msg) => {
4613                         tcx.sess.span_fatal(it.span, msg.as_slice());
4614                     }
4615                 }
4616             },
4617             "visit_tydesc" => {
4618               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4619                   Ok(t) => t,
4620                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4621               };
4622               let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4623               let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4624                   Ok((_, vot)) => vot,
4625                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4626               };
4627
4628               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4629                   ty: tydesc_ty,
4630                   mutbl: ast::MutImmutable
4631               });
4632               (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4633             }
4634             "offset" => {
4635               (1,
4636                vec!(
4637                   ty::mk_ptr(tcx, ty::mt {
4638                       ty: param(ccx, 0),
4639                       mutbl: ast::MutImmutable
4640                   }),
4641                   ty::mk_int()
4642                ),
4643                ty::mk_ptr(tcx, ty::mt {
4644                    ty: param(ccx, 0),
4645                    mutbl: ast::MutImmutable
4646                }))
4647             }
4648             "copy_memory" | "copy_nonoverlapping_memory" |
4649             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4650               (1,
4651                vec!(
4652                   ty::mk_ptr(tcx, ty::mt {
4653                       ty: param(ccx, 0),
4654                       mutbl: ast::MutMutable
4655                   }),
4656                   ty::mk_ptr(tcx, ty::mt {
4657                       ty: param(ccx, 0),
4658                       mutbl: ast::MutImmutable
4659                   }),
4660                   ty::mk_uint()
4661                ),
4662                ty::mk_nil())
4663             }
4664             "set_memory" | "volatile_set_memory" => {
4665               (1,
4666                vec!(
4667                   ty::mk_ptr(tcx, ty::mt {
4668                       ty: param(ccx, 0),
4669                       mutbl: ast::MutMutable
4670                   }),
4671                   ty::mk_u8(),
4672                   ty::mk_uint()
4673                ),
4674                ty::mk_nil())
4675             }
4676             "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4677             "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4678             "powif32" => {
4679                (0,
4680                 vec!( ty::mk_f32(), ty::mk_i32() ),
4681                 ty::mk_f32())
4682             }
4683             "powif64" => {
4684                (0,
4685                 vec!( ty::mk_f64(), ty::mk_i32() ),
4686                 ty::mk_f64())
4687             }
4688             "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4689             "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4690             "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4691             "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4692             "powf32" => {
4693                (0,
4694                 vec!( ty::mk_f32(), ty::mk_f32() ),
4695                 ty::mk_f32())
4696             }
4697             "powf64" => {
4698                (0,
4699                 vec!( ty::mk_f64(), ty::mk_f64() ),
4700                 ty::mk_f64())
4701             }
4702             "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4703             "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4704             "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4705             "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4706             "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4707             "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4708             "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4709             "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4710             "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4711             "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4712             "fmaf32" => {
4713                 (0,
4714                  vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4715                  ty::mk_f32())
4716             }
4717             "fmaf64" => {
4718                 (0,
4719                  vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4720                  ty::mk_f64())
4721             }
4722             "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4723             "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4724             "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4725             "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4726             "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4727             "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4728             "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4729             "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4730             "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4731             "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4732             "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4733             "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4734             "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4735             "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4736             "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4737             "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4738             "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4739             "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4740             "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4741             "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4742             "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4743             "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4744             "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4745             "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4746             "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4747             "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4748             "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4749             "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4750             "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4751             "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4752             "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4753
4754             "volatile_load" =>
4755                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4756             "volatile_store" =>
4757                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4758
4759             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4760                 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4761                 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4762
4763             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4764                 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4765                 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4766
4767             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4768                 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4769                 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4770
4771             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4772                 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4773                 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4774
4775             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4776                 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4777                 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4778
4779             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4780                 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4781                 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4782
4783             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4784                 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4785                 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4786
4787             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
4788                 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4789                 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4790
4791             ref other => {
4792                 tcx.sess.span_err(it.span,
4793                                   format!("unrecognized intrinsic function: `{}`",
4794                                           *other).as_slice());
4795                 return;
4796             }
4797         }
4798     };
4799     let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4800         fn_style: ast::UnsafeFn,
4801         abi: abi::RustIntrinsic,
4802         sig: FnSig {
4803             binder_id: it.id,
4804             inputs: inputs,
4805             output: output,
4806             variadic: false,
4807         }
4808     });
4809     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4810     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4811     if i_n_tps != n_tps {
4812         tcx.sess.span_err(it.span,
4813                           format!("intrinsic has wrong number of type \
4814                                    parameters: found {}, expected {}",
4815                                   i_n_tps,
4816                                   n_tps).as_slice());
4817     } else {
4818         require_same_types(tcx,
4819                            None,
4820                            false,
4821                            it.span,
4822                            i_ty.ty,
4823                            fty,
4824                            || {
4825                 format!("intrinsic has wrong type: expected `{}`",
4826                         ppaux::ty_to_str(ccx.tcx, fty))
4827             });
4828     }
4829 }