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