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