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