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