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