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