]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/mod.rs
auto merge of #15589 : Denommus/rust/master, r=alexcrichton
[rust.git] / src / librustc / middle / typeck / check / mod.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*
12
13 # check.rs
14
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function).  Inference is used to supply types wherever they are
18 unknown.
19
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
22
23 - gather: creates type variables to represent the type of each local
24   variable and pattern binding.
25
26 - main: the main pass does the lion's share of the work: it
27   determines the types of all expressions, resolves
28   methods, checks for most invalid conditions, and so forth.  In
29   some cases, where a type is unknown, it may create a type or region
30   variable and use that as the type of an expression.
31
32   In the process of checking, various constraints will be placed on
33   these type variables through the subtyping relationships requested
34   through the `demand` module.  The `typeck::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
80 use middle::const_eval;
81 use middle::def;
82 use middle::pat_util::pat_id_map;
83 use middle::pat_util;
84 use middle::subst;
85 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
86 use middle::ty::{FnSig, VariantInfo};
87 use middle::ty::{Polytype};
88 use middle::ty::{ParamTy, Disr, ExprTyProvider};
89 use middle::ty;
90 use middle::ty_fold::TypeFolder;
91 use middle::typeck::astconv::AstConv;
92 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
93 use middle::typeck::astconv;
94 use middle::typeck::check::_match::pat_ctxt;
95 use middle::typeck::check::method::{AutoderefReceiver};
96 use middle::typeck::check::method::{AutoderefReceiverFlag};
97 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
98 use middle::typeck::check::method::{DontAutoderefReceiver};
99 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
100 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
101 use middle::typeck::check::regionmanip::relate_free_regions;
102 use middle::typeck::check::vtable::VtableContext;
103 use middle::typeck::CrateCtxt;
104 use middle::typeck::infer::{resolve_type, force_tvar};
105 use middle::typeck::infer;
106 use middle::typeck::rscope::RegionScope;
107 use middle::typeck::{lookup_def_ccx};
108 use middle::typeck::no_params;
109 use middle::typeck::{require_same_types, vtable_map};
110 use middle::typeck::{MethodCall, MethodMap};
111 use middle::typeck::{TypeAndSubsts};
112 use middle::lang_items::TypeIdLangItem;
113 use lint;
114 use util::common::{block_query, indenter, loop_query};
115 use util::ppaux;
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
118
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
122 use std::rc::Rc;
123 use std::gc::Gc;
124 use syntax::abi;
125 use syntax::ast::{Provided, Required};
126 use syntax::ast;
127 use syntax::ast_map;
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
130 use syntax::attr;
131 use syntax::codemap::Span;
132 use syntax::codemap;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
136 use syntax::visit;
137 use syntax::visit::Visitor;
138 use syntax;
139
140 pub mod _match;
141 pub mod vtable;
142 pub mod writeback;
143 pub mod regionmanip;
144 pub mod regionck;
145 pub mod demand;
146 pub mod method;
147
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function.  For example:
150 ///
151 ///     fn foo() {
152 ///         bar(proc() { ... })
153 ///     }
154 ///
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159     infcx: infer::InferCtxt<'a>,
160     locals: RefCell<NodeMap<ty::t>>,
161     param_env: ty::ParameterEnvironment,
162
163     // Temporary tables:
164     node_types: RefCell<NodeMap<ty::t>>,
165     item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166     adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167     method_map: MethodMap,
168     vtable_map: vtable_map,
169     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
170 }
171
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
174 enum Expectation {
175     /// We know nothing about what type this expression should have.
176     NoExpectation,
177
178     /// This expression should have the type given (or some subtype)
179     ExpectHasType(ty::t),
180
181     /// This expression will be cast to the `ty::t`
182     ExpectCastableToType(ty::t),
183 }
184
185 #[deriving(Clone)]
186 pub struct FnStyleState {
187     pub def: ast::NodeId,
188     pub fn_style: ast::FnStyle,
189     from_fn: bool
190 }
191
192 impl FnStyleState {
193     pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194         FnStyleState { def: def, fn_style: fn_style, from_fn: true }
195     }
196
197     pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
198         match self.fn_style {
199             // If this unsafe, then if the outer function was already marked as
200             // unsafe we shouldn't attribute the unsafe'ness to the block. This
201             // way the block can be warned about instead of ignoring this
202             // extraneous block (functions are never warned about).
203             ast::UnsafeFn if self.from_fn => *self,
204
205             fn_style => {
206                 let (fn_style, def) = match blk.rules {
207                     ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208                     ast::DefaultBlock => (fn_style, self.def),
209                 };
210                 FnStyleState{ def: def,
211                              fn_style: fn_style,
212                              from_fn: false }
213             }
214         }
215     }
216 }
217
218 /// Whether `check_binop` is part of an assignment or not.
219 /// Used to know whether we allow user overloads and to print
220 /// better messages on error.
221 #[deriving(PartialEq)]
222 enum IsBinopAssignment{
223     SimpleBinop,
224     BinopAssignment,
225 }
226
227 #[deriving(Clone)]
228 pub struct FnCtxt<'a> {
229     // This flag is set to true if, during the writeback phase, we encounter
230     // a type error in this function.
231     writeback_errors: Cell<bool>,
232
233     // Number of errors that had been reported when we started
234     // checking this function. On exit, if we find that *more* errors
235     // have been reported, we will skip regionck and other work that
236     // expects the types within the function to be consistent.
237     err_count_on_creation: uint,
238
239     ret_ty: ty::t,
240     ps: RefCell<FnStyleState>,
241
242     // Sometimes we generate region pointers where the precise region
243     // to use is not known. For example, an expression like `&x.f`
244     // where `x` is of type `@T`: in this case, we will be rooting
245     // `x` onto the stack frame, and we could choose to root it until
246     // the end of (almost) any enclosing block or expression.  We
247     // want to pick the narrowest block that encompasses all uses.
248     //
249     // What we do in such cases is to generate a region variable with
250     // `region_lb` as a lower bound.  The regionck pass then adds
251     // other constraints based on how the variable is used and region
252     // inference selects the ultimate value.  Finally, borrowck is
253     // charged with guaranteeing that the value whose address was taken
254     // can actually be made to live as long as it needs to live.
255     region_lb: Cell<ast::NodeId>,
256
257     inh: &'a Inherited<'a>,
258
259     ccx: &'a CrateCtxt<'a>,
260 }
261
262 impl<'a> Inherited<'a> {
263     fn new(tcx: &'a ty::ctxt,
264            param_env: ty::ParameterEnvironment)
265            -> Inherited<'a> {
266         Inherited {
267             infcx: infer::new_infer_ctxt(tcx),
268             locals: RefCell::new(NodeMap::new()),
269             param_env: param_env,
270             node_types: RefCell::new(NodeMap::new()),
271             item_substs: RefCell::new(NodeMap::new()),
272             adjustments: RefCell::new(NodeMap::new()),
273             method_map: RefCell::new(FnvHashMap::new()),
274             vtable_map: RefCell::new(FnvHashMap::new()),
275             upvar_borrow_map: RefCell::new(HashMap::new()),
276         }
277     }
278 }
279
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282                      inh: &'a Inherited<'a>,
283                      rty: ty::t,
284                      region_bnd: ast::NodeId)
285                      -> FnCtxt<'a> {
286     FnCtxt {
287         writeback_errors: Cell::new(false),
288         err_count_on_creation: ccx.tcx.sess.err_count(),
289         ret_ty: rty,
290         ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291         region_lb: Cell::new(region_bnd),
292         inh: inh,
293         ccx: ccx
294     }
295 }
296
297 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
298     // It's kind of a kludge to manufacture a fake function context
299     // and statement context, but we might as well do write the code only once
300     let param_env = ty::ParameterEnvironment {
301         free_substs: subst::Substs::empty(),
302         bounds: subst::VecPerParamSpace::empty()
303     };
304     Inherited::new(ccx.tcx, param_env)
305 }
306
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308     fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
309         self.expr_ty(ex)
310     }
311
312     fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
313         self.ccx.tcx
314     }
315 }
316
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
318
319 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
320     fn visit_item(&mut self, i: &ast::Item, _: ()) {
321         check_item(self.ccx, i);
322         visit::walk_item(self, i, ());
323     }
324 }
325
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
327
328 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329     fn visit_item(&mut self, i: &ast::Item, _: ()) {
330         check_item_sized(self.ccx, i);
331         visit::walk_item(self, i, ());
332     }
333 }
334
335 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336     let mut visit = CheckItemTypesVisitor { ccx: ccx };
337     visit::walk_crate(&mut visit, krate, ());
338
339     ccx.tcx.sess.abort_if_errors();
340
341     let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342     visit::walk_crate(&mut visit, krate, ());
343 }
344
345 fn check_bare_fn(ccx: &CrateCtxt,
346                  decl: &ast::FnDecl,
347                  body: &ast::Block,
348                  id: ast::NodeId,
349                  fty: ty::t,
350                  param_env: ty::ParameterEnvironment) {
351     // Compute the fty from point of view of inside fn
352     // (replace any type-scheme with a type)
353     let fty = fty.subst(ccx.tcx, &param_env.free_substs);
354
355     match ty::get(fty).sty {
356         ty::ty_bare_fn(ref fn_ty) => {
357             let inh = Inherited::new(ccx.tcx, param_env);
358             let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
359                                decl, id, body, &inh);
360
361             vtable::resolve_in_block(&fcx, body);
362             regionck::regionck_fn(&fcx, body);
363             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
364         }
365         _ => ccx.tcx.sess.impossible_case(body.span,
366                                  "check_bare_fn: function type expected")
367     }
368 }
369
370 struct GatherLocalsVisitor<'a> {
371     fcx: &'a FnCtxt<'a>
372 }
373
374 impl<'a> GatherLocalsVisitor<'a> {
375     fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
376             match ty_opt {
377                 None => {
378                     // infer the variable's type
379                     let var_id = self.fcx.infcx().next_ty_var_id();
380                     let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
381                     self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
382                 }
383                 Some(typ) => {
384                     // take type that the user specified
385                     self.fcx.inh.locals.borrow_mut().insert(nid, typ);
386                 }
387             }
388     }
389 }
390
391 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392     // Add explicitly-declared locals.
393     fn visit_local(&mut self, local: &ast::Local, _: ()) {
394         let o_ty = match local.ty.node {
395             ast::TyInfer => None,
396             _ => Some(self.fcx.to_ty(&*local.ty))
397         };
398         self.assign(local.id, o_ty);
399         debug!("Local variable {} is assigned type {}",
400                self.fcx.pat_to_string(&*local.pat),
401                self.fcx.infcx().ty_to_string(
402                    self.fcx.inh.locals.borrow().get_copy(&local.id)));
403         visit::walk_local(self, local, ());
404     }
405
406     // Add pattern bindings.
407     fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
408             match p.node {
409               ast::PatIdent(_, ref path1, _)
410                   if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
411                 self.assign(p.id, None);
412                 debug!("Pattern binding {} is assigned to {}",
413                        token::get_ident(path1.node),
414                        self.fcx.infcx().ty_to_string(
415                            self.fcx.inh.locals.borrow().get_copy(&p.id)));
416               }
417               _ => {}
418             }
419             visit::walk_pat(self, p, ());
420
421     }
422
423     fn visit_block(&mut self, b: &ast::Block, _: ()) {
424         // non-obvious: the `blk` variable maps to region lb, so
425         // we have to keep this up-to-date.  This
426         // is... unfortunate.  It'd be nice to not need this.
427         self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
428     }
429
430     // Don't descend into fns and items
431     fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
432                 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
433     fn visit_item(&mut self, _: &ast::Item, _: ()) { }
434
435 }
436
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438                 fn_style: ast::FnStyle,
439                 fn_sig: &ty::FnSig,
440                 decl: &ast::FnDecl,
441                 id: ast::NodeId,
442                 body: &ast::Block,
443                 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
444 {
445     /*!
446      * Helper used by check_bare_fn and check_expr_fn.  Does the
447      * grungy work of checking a function body and returns the
448      * function context used for that purpose, since in the case of a
449      * fn item there is still a bit more to do.
450      *
451      * - ...
452      * - inherited: other fields inherited from the enclosing fn (if any)
453      */
454
455     let tcx = ccx.tcx;
456     let err_count_on_creation = tcx.sess.err_count();
457
458     // First, we have to replace any bound regions in the fn type with free ones.
459     // The free region references will be bound the node_id of the body block.
460     let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
461         ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
462     });
463
464     relate_free_regions(tcx, &fn_sig);
465
466     let arg_tys = fn_sig.inputs.as_slice();
467     let ret_ty = fn_sig.output;
468
469     debug!("check_fn(arg_tys={}, ret_ty={})",
470            arg_tys.repr(tcx),
471            ret_ty.repr(tcx));
472
473     // Create the function context.  This is either derived from scratch or,
474     // in the case of function expressions, based on the outer context.
475     let fcx = FnCtxt {
476         writeback_errors: Cell::new(false),
477         err_count_on_creation: err_count_on_creation,
478         ret_ty: ret_ty,
479         ps: RefCell::new(FnStyleState::function(fn_style, id)),
480         region_lb: Cell::new(body.id),
481         inh: inherited,
482         ccx: ccx
483     };
484
485     {
486
487         let mut visit = GatherLocalsVisitor { fcx: &fcx, };
488         // Add formal parameters.
489         for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
490             // Create type variables for each argument.
491             pat_util::pat_bindings(&tcx.def_map,
492                                    &*input.pat,
493                                    |_bm, pat_id, _sp, _path| {
494                                        visit.assign(pat_id, None);
495                                    });
496
497             // Check the pattern.
498             let pcx = pat_ctxt {
499                 fcx: &fcx,
500                 map: pat_id_map(&tcx.def_map, &*input.pat),
501             };
502             _match::check_pat(&pcx, &*input.pat, *arg_ty);
503         }
504
505         visit.visit_block(body, ());
506     }
507
508     check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
509
510     // We unify the tail expr's type with the
511     // function result type, if there is a tail expr.
512     match body.expr {
513         Some(ref tail_expr) => {
514             // Special case: we print a special error if there appears
515             // to be do-block/for-loop confusion
516             demand::suptype_with_fn(&fcx, tail_expr.span, false,
517                 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
518                 |sp, e, a, s| {
519                     fcx.report_mismatched_return_types(sp, e, a, s);
520                 });
521         }
522         None => {}
523     }
524
525     for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526         fcx.write_ty(input.id, *arg);
527     }
528
529     fcx
530 }
531
532 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
533     assert!(field.id.krate == ast::LOCAL_CRATE);
534     let item = match tcx.map.find(struct_id.node) {
535         Some(ast_map::NodeItem(item)) => item,
536         None => fail!("node not in ast map: {}", struct_id.node),
537         _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
538     };
539
540     match item.node {
541         ast::ItemStruct(struct_def, _) => {
542             match struct_def.fields.iter().find(|f| match f.node.kind {
543                 ast::NamedField(ident, _) => ident.name == field.name,
544                 _ => false,
545             }) {
546                 Some(f) => f.span,
547                 None => {
548                     tcx.sess
549                        .bug(format!("Could not find field {}",
550                                     token::get_name(field.name)).as_slice())
551                 }
552             }
553         },
554         _ => tcx.sess.bug("Field found outside of a struct?"),
555     }
556 }
557
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
560                              id: ast::DefId) {
561     let struct_fields = tcx.struct_fields.borrow();
562     let fields = struct_fields.get(&id);
563
564     let superstructs = tcx.superstructs.borrow();
565     let super_struct = superstructs.get(&id);
566     match *super_struct {
567         Some(parent_id) => {
568             let super_fields = ty::lookup_struct_fields(tcx, parent_id);
569             for f in fields.iter() {
570                 match super_fields.iter().find(|sf| f.name == sf.name) {
571                     Some(prev_field) => {
572                         tcx.sess.span_err(span_for_field(tcx, f, id),
573                             format!("field `{}` hides field declared in \
574                                      super-struct",
575                                     token::get_name(f.name)).as_slice());
576                         tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
577                             "previously declared here");
578                     },
579                     None => {}
580                 }
581             }
582         },
583         None => {}
584     }
585 }
586
587 fn check_fields_sized(tcx: &ty::ctxt,
588                       struct_def: &ast::StructDef) {
589     let len = struct_def.fields.len();
590     if len == 0 {
591         return;
592     }
593     for f in struct_def.fields.slice_to(len - 1).iter() {
594         let t = ty::node_id_to_type(tcx, f.node.id);
595         if !ty::type_is_sized(tcx, t) {
596             match f.node.kind {
597                 ast::NamedField(ident, _) => {
598                     tcx.sess.span_err(
599                         f.span,
600                         format!("type `{}` is dynamically sized. \
601                                  dynamically sized types may only \
602                                  appear as the type of the final \
603                                  field in a struct",
604                                  token::get_ident(ident)).as_slice());
605                 }
606                 ast::UnnamedField(_) => {
607                     tcx.sess.span_err(f.span, "dynamically sized type in field");
608                 }
609             }
610         }
611     }
612 }
613
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
615     let tcx = ccx.tcx;
616
617     check_representable(tcx, span, id, "struct");
618     check_instantiable(tcx, span, id);
619
620     // Check there are no overlapping fields in super-structs
621     check_for_field_shadowing(tcx, local_def(id));
622
623     if ty::lookup_simd(tcx, local_def(id)) {
624         check_simd(tcx, span, id);
625     }
626 }
627
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629     debug!("check_item(it.id={}, it.ident={})",
630            it.id,
631            ty::item_path_str(ccx.tcx, local_def(it.id)));
632     let _indenter = indenter();
633
634     match it.node {
635         ast::ItemEnum(ref enum_definition, _) => {
636             check_enum_variants_sized(ccx,
637                                       enum_definition.variants.as_slice());
638         }
639         ast::ItemStruct(..) => {
640             check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
641         }
642         _ => {}
643     }
644 }
645
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647     debug!("check_item(it.id={}, it.ident={})",
648            it.id,
649            ty::item_path_str(ccx.tcx, local_def(it.id)));
650     let _indenter = indenter();
651
652     match it.node {
653       ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654       ast::ItemEnum(ref enum_definition, _) => {
655         check_enum_variants(ccx,
656                             it.span,
657                             enum_definition.variants.as_slice(),
658                             it.id);
659       }
660       ast::ItemFn(ref decl, _, _, _, ref body) => {
661         let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
662
663         let param_env = ty::construct_parameter_environment(ccx.tcx,
664                                                             &fn_pty.generics,
665                                                             body.id);
666
667         check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
668       }
669       ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
671
672         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
673         for m in ms.iter() {
674             check_method_body(ccx, &impl_pty.generics, &**m);
675         }
676
677         match *opt_trait_ref {
678             Some(ref ast_trait_ref) => {
679                 let impl_trait_ref =
680                     ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681                 check_impl_methods_against_trait(ccx,
682                                              it.span,
683                                              ast_trait_ref,
684                                              &*impl_trait_ref,
685                                              ms.as_slice());
686                 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
687             }
688             None => { }
689         }
690
691       }
692       ast::ItemTrait(_, _, _, ref trait_methods) => {
693         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
694         for trait_method in (*trait_methods).iter() {
695             match *trait_method {
696                 Required(..) => {
697                     // Nothing to do, since required methods don't have
698                     // bodies to check.
699                 }
700                 Provided(m) => {
701                     check_method_body(ccx, &trait_def.generics, &*m);
702                 }
703             }
704         }
705       }
706       ast::ItemStruct(..) => {
707         check_struct(ccx, it.id, it.span);
708       }
709       ast::ItemTy(ref t, ref generics) => {
710         let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
711         check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
712       }
713       ast::ItemForeignMod(ref m) => {
714         if m.abi == abi::RustIntrinsic {
715             for item in m.items.iter() {
716                 check_intrinsic_type(ccx, &**item);
717             }
718         } else {
719             for item in m.items.iter() {
720                 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
721                 if !pty.generics.types.is_empty() {
722                     ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
723                 }
724
725                 match item.node {
726                     ast::ForeignItemFn(ref fn_decl, _) => {
727                         if fn_decl.variadic && m.abi != abi::C {
728                             ccx.tcx.sess.span_err(
729                                 item.span, "variadic function must have C calling convention");
730                         }
731                     }
732                     _ => {}
733                 }
734             }
735         }
736       }
737       _ => {/* nothing to do */ }
738     }
739 }
740
741 fn check_method_body(ccx: &CrateCtxt,
742                      item_generics: &ty::Generics,
743                      method: &ast::Method) {
744     /*!
745      * Type checks a method body.
746      *
747      * # Parameters
748      * - `item_generics`: generics defined on the impl/trait that contains
749      *   the method
750      * - `self_bound`: bound for the `Self` type parameter, if any
751      * - `method`: the method definition
752      */
753
754     debug!("check_method_body(item_generics={}, method.id={})",
755             item_generics.repr(ccx.tcx),
756             method.id);
757     let method_def_id = local_def(method.id);
758     let method_ty = ty::method(ccx.tcx, method_def_id);
759     let method_generics = &method_ty.generics;
760
761     let param_env = ty::construct_parameter_environment(ccx.tcx,
762                                                         method_generics,
763                                                         method.body.id);
764
765     let fty = ty::node_id_to_type(ccx.tcx, method.id);
766
767     check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
768 }
769
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
771                                     impl_span: Span,
772                                     ast_trait_ref: &ast::TraitRef,
773                                     impl_trait_ref: &ty::TraitRef,
774                                     impl_methods: &[Gc<ast::Method>]) {
775     // Locate trait methods
776     let tcx = ccx.tcx;
777     let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
778
779     // Check existing impl methods to see if they are both present in trait
780     // and compatible with trait signature
781     for impl_method in impl_methods.iter() {
782         let impl_method_def_id = local_def(impl_method.id);
783         let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
784
785         // If this is an impl of a trait method, find the corresponding
786         // method definition in the trait.
787         let opt_trait_method_ty =
788             trait_methods.iter().
789             find(|tm| tm.ident.name == impl_method_ty.ident.name);
790         match opt_trait_method_ty {
791             Some(trait_method_ty) => {
792                 compare_impl_method(ccx.tcx,
793                                     &*impl_method_ty,
794                                     impl_method.span,
795                                     impl_method.body.id,
796                                     &**trait_method_ty,
797                                     &impl_trait_ref.substs);
798             }
799             None => {
800                 // This is span_bug as it should have already been caught in resolve.
801                 tcx.sess.span_bug(
802                     impl_method.span,
803                     format!(
804                         "method `{}` is not a member of trait `{}`",
805                         token::get_ident(impl_method_ty.ident),
806                         pprust::path_to_string(&ast_trait_ref.path)).as_slice());
807             }
808         }
809     }
810
811     // Check for missing methods from trait
812     let provided_methods = ty::provided_trait_methods(tcx,
813                                                       impl_trait_ref.def_id);
814     let mut missing_methods = Vec::new();
815     for trait_method in trait_methods.iter() {
816         let is_implemented =
817             impl_methods.iter().any(
818                 |m| m.ident.name == trait_method.ident.name);
819         let is_provided =
820             provided_methods.iter().any(
821                 |m| m.ident.name == trait_method.ident.name);
822         if !is_implemented && !is_provided {
823             missing_methods.push(
824                 format!("`{}`", token::get_ident(trait_method.ident)));
825         }
826     }
827
828     if !missing_methods.is_empty() {
829         tcx.sess.span_err(
830             impl_span,
831             format!("not all trait methods implemented, missing: {}",
832                     missing_methods.connect(", ")).as_slice());
833     }
834 }
835
836 /**
837  * Checks that a method from an impl/class conforms to the signature of
838  * the same method as declared in the trait.
839  *
840  * # Parameters
841  *
842  * - impl_generics: the generics declared on the impl itself (not the method!)
843  * - impl_m: type of the method we are checking
844  * - impl_m_span: span to use for reporting errors
845  * - impl_m_body_id: id of the method body
846  * - trait_m: the method in the trait
847  * - trait_to_impl_substs: the substitutions used on the type of the trait
848  */
849 fn compare_impl_method(tcx: &ty::ctxt,
850                        impl_m: &ty::Method,
851                        impl_m_span: Span,
852                        impl_m_body_id: ast::NodeId,
853                        trait_m: &ty::Method,
854                        trait_to_impl_substs: &subst::Substs) {
855     debug!("compare_impl_method()");
856     let infcx = infer::new_infer_ctxt(tcx);
857
858     // Try to give more informative error messages about self typing
859     // mismatches.  Note that any mismatch will also be detected
860     // below, where we construct a canonical function type that
861     // includes the self parameter as a normal parameter.  It's just
862     // that the error messages you get out of this code are a bit more
863     // inscrutable, particularly for cases where one method has no
864     // self.
865     match (&trait_m.explicit_self, &impl_m.explicit_self) {
866         (&ast::SelfStatic, &ast::SelfStatic) => {}
867         (&ast::SelfStatic, _) => {
868             tcx.sess.span_err(
869                 impl_m_span,
870                 format!("method `{}` has a `{}` declaration in the impl, \
871                         but not in the trait",
872                         token::get_ident(trait_m.ident),
873                         pprust::explicit_self_to_string(
874                             impl_m.explicit_self)).as_slice());
875             return;
876         }
877         (_, &ast::SelfStatic) => {
878             tcx.sess.span_err(
879                 impl_m_span,
880                 format!("method `{}` has a `{}` declaration in the trait, \
881                         but not in the impl",
882                         token::get_ident(trait_m.ident),
883                         pprust::explicit_self_to_string(
884                             trait_m.explicit_self)).as_slice());
885             return;
886         }
887         _ => {
888             // Let the type checker catch other errors below
889         }
890     }
891
892     let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
893     let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
894     if num_impl_m_type_params != num_trait_m_type_params {
895         tcx.sess.span_err(
896             impl_m_span,
897             format!("method `{}` has {} type parameter{} \
898                      but its trait declaration has {} type parameter{}",
899                     token::get_ident(trait_m.ident),
900                     num_impl_m_type_params,
901                     if num_impl_m_type_params == 1 {""} else {"s"},
902                     num_trait_m_type_params,
903                     if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
904         return;
905     }
906
907     if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
908         tcx.sess.span_err(
909             impl_m_span,
910             format!("method `{}` has {} parameter{} \
911                      but the declaration in trait `{}` has {}",
912                  token::get_ident(trait_m.ident),
913                  impl_m.fty.sig.inputs.len(),
914                  if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
915                  ty::item_path_str(tcx, trait_m.def_id),
916                  trait_m.fty.sig.inputs.len()).as_slice());
917         return;
918     }
919
920     let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
921         .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
922
923     // This code is best explained by example. Consider a trait:
924     //
925     //     trait Trait<T> {
926     //          fn method<'a,M>(t: T, m: &'a M) -> Self;
927     //     }
928     //
929     // And an impl:
930     //
931     //     impl<'i, U> Trait<&'i U> for Foo {
932     //          fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
933     //     }
934     //
935     // We wish to decide if those two method types are compatible.
936     //
937     // We start out with trait_to_impl_substs, that maps the trait type
938     // parameters to impl type parameters:
939     //
940     //     trait_to_impl_substs = {T => &'i U, Self => Foo}
941     //
942     // We create a mapping `dummy_substs` that maps from the impl type
943     // parameters to fresh types and regions. For type parameters,
944     // this is the identity transform, but we could as well use any
945     // skolemized types. For regions, we convert from bound to free
946     // regions (Note: but only early-bound regions, i.e., those
947     // declared on the impl or used in type parameter bounds).
948     //
949     //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
950     //
951     // Now we can apply skol_substs to the type of the impl method
952     // to yield a new function type in terms of our fresh, skolemized
953     // types:
954     //
955     //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
956     //
957     // We now want to extract and substitute the type of the *trait*
958     // method and compare it. To do so, we must create a compound
959     // substitution by combining trait_to_impl_substs and
960     // impl_to_skol_substs, and also adding a mapping for the method
961     // type parameters. We extend the mapping to also include
962     // the method parameters.
963     //
964     //     trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
965     //
966     // Applying this to the trait method type yields:
967     //
968     //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
969     //
970     // This type is also the same but the name of the bound region ('a
971     // vs 'b).  However, the normal subtyping rules on fn types handle
972     // this kind of equivalency just fine.
973
974     // Create mapping from impl to skolemized.
975     let skol_tps =
976         impl_m.generics.types.map(
977             |d| ty::mk_param_from_def(tcx, d));
978     let skol_regions =
979         impl_m.generics.regions.map(
980             |l| ty::free_region_from_def(impl_m_body_id, l));
981     let impl_to_skol_substs =
982         subst::Substs::new(skol_tps.clone(), skol_regions.clone());
983
984     // Compute skolemized form of impl method ty.
985     let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
986     let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
987
988     // Compute skolemized form of trait method ty.
989     let trait_to_skol_substs =
990         trait_to_impl_substs
991         .subst(tcx, &impl_to_skol_substs)
992         .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
993                      Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
994     let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
995     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
996
997     // Check bounds.
998     for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
999         // Check that the impl does not require any builtin-bounds
1000         // that the trait does not guarantee:
1001         let extra_bounds =
1002             impl_param_def.bounds.builtin_bounds -
1003             trait_param_def.bounds.builtin_bounds;
1004         if !extra_bounds.is_empty() {
1005            tcx.sess.span_err(
1006                impl_m_span,
1007                format!("in method `{}`, \
1008                        type parameter {} requires `{}`, \
1009                        which is not required by \
1010                        the corresponding type parameter \
1011                        in the trait declaration",
1012                        token::get_ident(trait_m.ident),
1013                        i,
1014                        extra_bounds.user_string(tcx)).as_slice());
1015            return;
1016         }
1017
1018         // Check that the trait bounds of the trait imply the bounds of its
1019         // implementation.
1020         //
1021         // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1022         // traits, but I doubt that'll be wanted often, so meh.
1023         for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1024             let impl_trait_bound =
1025                 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1026
1027             let mut ok = false;
1028             for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1029                 let trait_bound =
1030                     trait_bound.subst(tcx, &trait_to_skol_substs);
1031                 let infcx = infer::new_infer_ctxt(tcx);
1032                 match infer::mk_sub_trait_refs(&infcx,
1033                                                true,
1034                                                infer::Misc(impl_m_span),
1035                                                trait_bound,
1036                                                impl_trait_bound.clone()) {
1037                     Ok(_) => {
1038                         ok = true;
1039                         break
1040                     }
1041                     Err(_) => continue,
1042                 }
1043             }
1044
1045             if !ok {
1046                 tcx.sess.span_err(impl_m_span,
1047                                   format!("in method `{}`, type parameter {} \
1048                                            requires bound `{}`, which is not \
1049                                            required by the corresponding \
1050                                            type parameter in the trait \
1051                                            declaration",
1052                                           token::get_ident(trait_m.ident),
1053                                           i,
1054                                           ppaux::trait_ref_to_string(
1055                                               tcx,
1056                                               &*impl_trait_bound)).as_slice())
1057             }
1058         }
1059     }
1060
1061     // Check the impl method type IM is a subtype of the trait method
1062     // type TM. To see why this makes sense, think of a vtable. The
1063     // expected type of the function pointers in the vtable is the
1064     // type TM of the trait method.  The actual type will be the type
1065     // IM of the impl method. Because we know that IM <: TM, that
1066     // means that anywhere a TM is expected, a IM will do instead. In
1067     // other words, anyone expecting to call a method with the type
1068     // from the trait, can safely call a method with the type from the
1069     // impl instead.
1070     match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1071                           impl_fty, trait_fty) {
1072         Ok(()) => {}
1073         Err(ref terr) => {
1074             tcx.sess.span_err(
1075                 impl_m_span,
1076                 format!("method `{}` has an incompatible type for trait: {}",
1077                         token::get_ident(trait_m.ident),
1078                         ty::type_err_to_str(tcx, terr)).as_slice());
1079             ty::note_and_explain_type_err(tcx, terr);
1080         }
1081     }
1082 }
1083
1084 fn check_cast(fcx: &FnCtxt,
1085               e: &ast::Expr,
1086               t: &ast::Ty,
1087               id: ast::NodeId,
1088               span: Span) {
1089     // Find the type of `e`. Supply hints based on the type we are casting to,
1090     // if appropriate.
1091     let t_1 = fcx.to_ty(t);
1092     let t_1 = structurally_resolved_type(fcx, span, t_1);
1093
1094     if ty::type_is_scalar(t_1) {
1095         // Supply the type as a hint so as to influence integer
1096         // literals and other things that might care.
1097         check_expr_with_hint(fcx, e, t_1)
1098     } else {
1099         check_expr(fcx, e)
1100     }
1101
1102     let t_e = fcx.expr_ty(e);
1103
1104     debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1105     debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1106
1107     if ty::type_is_error(t_e) {
1108         fcx.write_error(id);
1109         return
1110     }
1111     if ty::type_is_bot(t_e) {
1112         fcx.write_bot(id);
1113         return
1114     }
1115
1116     if ty::type_is_trait(t_1) {
1117         // This will be looked up later on.
1118         fcx.write_ty(id, t_1);
1119         return
1120     }
1121
1122     let t_1 = structurally_resolved_type(fcx, span, t_1);
1123     let t_e = structurally_resolved_type(fcx, span, t_e);
1124
1125     if ty::type_is_nil(t_e) {
1126         fcx.type_error_message(span, |actual| {
1127             format!("cast from nil: `{}` as `{}`",
1128                     actual,
1129                     fcx.infcx().ty_to_string(t_1))
1130         }, t_e, None);
1131     } else if ty::type_is_nil(t_1) {
1132         fcx.type_error_message(span, |actual| {
1133             format!("cast to nil: `{}` as `{}`",
1134                     actual,
1135                     fcx.infcx().ty_to_string(t_1))
1136         }, t_e, None);
1137     }
1138
1139     let t_1_is_scalar = ty::type_is_scalar(t_1);
1140     let t_1_is_char = ty::type_is_char(t_1);
1141     let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1142     let t_1_is_float = ty::type_is_floating_point(t_1);
1143
1144     // casts to scalars other than `char` and `bare fn` are trivial
1145     let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1146     if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1147         if t_1_is_float {
1148             fcx.type_error_message(span, |actual| {
1149                 format!("illegal cast; cast through an \
1150                          integer first: `{}` as `{}`",
1151                         actual,
1152                         fcx.infcx().ty_to_string(t_1))
1153             }, t_e, None);
1154         }
1155         // casts from C-like enums are allowed
1156     } else if t_1_is_char {
1157         let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1158         if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1159             fcx.type_error_message(span, |actual| {
1160                 format!("only `u8` can be cast as \
1161                          `char`, not `{}`", actual)
1162             }, t_e, None);
1163         }
1164     } else if ty::get(t_1).sty == ty::ty_bool {
1165         fcx.tcx()
1166            .sess
1167            .span_err(span,
1168                      "cannot cast as `bool`, compare with zero instead");
1169     } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1170         fn types_compatible(fcx: &FnCtxt, sp: Span,
1171                             t1: ty::t, t2: ty::t) -> bool {
1172             if !ty::type_is_vec(t1) {
1173                 // If the type being casted from is not a vector, this special
1174                 // case does not apply.
1175                 return false
1176             }
1177             if ty::type_needs_infer(t2) {
1178                 // This prevents this special case from going off when casting
1179                 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1180                 // #14893.)
1181                 return false
1182             }
1183
1184             let el = ty::sequence_element_type(fcx.tcx(), t1);
1185             infer::mk_eqty(fcx.infcx(),
1186                            false,
1187                            infer::Misc(sp),
1188                            el,
1189                            t2).is_ok()
1190         }
1191
1192         // Due to the limitations of LLVM global constants,
1193         // region pointers end up pointing at copies of
1194         // vector elements instead of the original values.
1195         // To allow unsafe pointers to work correctly, we
1196         // need to special-case obtaining an unsafe pointer
1197         // from a region pointer to a vector.
1198
1199         /* this cast is only allowed from &[T] to *T or
1200         &T to *T. */
1201         match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1202             (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1203              &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1204             if types_compatible(fcx, e.span, mt1, mt2) => {
1205                 /* this case is allowed */
1206             }
1207             _ => {
1208                 demand::coerce(fcx, e.span, t_1, &*e);
1209             }
1210         }
1211     } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1212         /*
1213         If more type combinations should be supported than are
1214         supported here, then file an enhancement issue and
1215         record the issue number in this comment.
1216         */
1217         fcx.type_error_message(span, |actual| {
1218             format!("non-scalar cast: `{}` as `{}`",
1219                     actual,
1220                     fcx.infcx().ty_to_string(t_1))
1221         }, t_e, None);
1222     } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1223         fcx.type_error_message(span, |actual| {
1224             format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1225                      integer first",
1226                     actual,
1227                     fcx.infcx().ty_to_string(t_1))
1228         }, t_e, None);
1229     }
1230
1231     fcx.write_ty(id, t_1);
1232 }
1233
1234 impl<'a> AstConv for FnCtxt<'a> {
1235     fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1236
1237     fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1238         ty::lookup_item_type(self.tcx(), id)
1239     }
1240
1241     fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1242         ty::lookup_trait_def(self.tcx(), id)
1243     }
1244
1245     fn ty_infer(&self, _span: Span) -> ty::t {
1246         self.infcx().next_ty_var()
1247     }
1248 }
1249
1250 impl<'a> FnCtxt<'a> {
1251     pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1252         &self.inh.infcx
1253     }
1254
1255     pub fn err_count_since_creation(&self) -> uint {
1256         self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1257     }
1258
1259     pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1260         VtableContext {
1261             infcx: self.infcx(),
1262             param_env: &self.inh.param_env
1263         }
1264     }
1265 }
1266
1267 impl<'a> RegionScope for infer::InferCtxt<'a> {
1268     fn anon_regions(&self, span: Span, count: uint)
1269                     -> Result<Vec<ty::Region> , ()> {
1270         Ok(Vec::from_fn(count, |_| {
1271             self.next_region_var(infer::MiscVariable(span))
1272         }))
1273     }
1274 }
1275
1276 impl<'a> FnCtxt<'a> {
1277     pub fn tag(&self) -> String {
1278         format!("{}", self as *const FnCtxt)
1279     }
1280
1281     pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1282         match self.inh.locals.borrow().find(&nid) {
1283             Some(&t) => t,
1284             None => {
1285                 self.tcx().sess.span_bug(
1286                     span,
1287                     format!("no type for local variable {:?}",
1288                             nid).as_slice());
1289             }
1290         }
1291     }
1292
1293     #[inline]
1294     pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1295         debug!("write_ty({}, {}) in fcx {}",
1296                node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1297         self.inh.node_types.borrow_mut().insert(node_id, ty);
1298     }
1299
1300     pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1301         if !substs.substs.is_noop() {
1302             debug!("write_substs({}, {}) in fcx {}",
1303                    node_id,
1304                    substs.repr(self.tcx()),
1305                    self.tag());
1306
1307             self.inh.item_substs.borrow_mut().insert(node_id, substs);
1308         }
1309     }
1310
1311     pub fn write_ty_substs(&self,
1312                            node_id: ast::NodeId,
1313                            ty: ty::t,
1314                            substs: ty::ItemSubsts) {
1315         let ty = ty.subst(self.tcx(), &substs.substs);
1316         self.write_ty(node_id, ty);
1317         self.write_substs(node_id, substs);
1318     }
1319
1320     pub fn write_autoderef_adjustment(&self,
1321                                       node_id: ast::NodeId,
1322                                       derefs: uint) {
1323         if derefs == 0 { return; }
1324         self.write_adjustment(
1325             node_id,
1326             ty::AutoDerefRef(ty::AutoDerefRef {
1327                 autoderefs: derefs,
1328                 autoref: None })
1329         );
1330     }
1331
1332     pub fn write_adjustment(&self,
1333                             node_id: ast::NodeId,
1334                             adj: ty::AutoAdjustment) {
1335         debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1336         self.inh.adjustments.borrow_mut().insert(node_id, adj);
1337     }
1338
1339     pub fn write_nil(&self, node_id: ast::NodeId) {
1340         self.write_ty(node_id, ty::mk_nil());
1341     }
1342     pub fn write_bot(&self, node_id: ast::NodeId) {
1343         self.write_ty(node_id, ty::mk_bot());
1344     }
1345     pub fn write_error(&self, node_id: ast::NodeId) {
1346         self.write_ty(node_id, ty::mk_err());
1347     }
1348
1349     pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1350         ast_ty_to_ty(self, self.infcx(), ast_t)
1351     }
1352
1353     pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1354         pat.repr(self.tcx())
1355     }
1356
1357     pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1358         match self.inh.node_types.borrow().find(&ex.id) {
1359             Some(&t) => t,
1360             None => {
1361                 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1362                                             self.tag()).as_slice());
1363             }
1364         }
1365     }
1366
1367     pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1368         match self.inh.node_types.borrow().find(&id) {
1369             Some(&t) => t,
1370             None => {
1371                 self.tcx().sess.bug(
1372                     format!("no type for node {}: {} in fcx {}",
1373                             id, self.tcx().map.node_to_string(id),
1374                             self.tag()).as_slice());
1375             }
1376         }
1377     }
1378
1379     pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1380         match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1381             Some(method) => method.substs.clone(),
1382             None => {
1383                 self.tcx().sess.bug(
1384                     format!("no method entry for node {}: {} in fcx {}",
1385                             id, self.tcx().map.node_to_string(id),
1386                             self.tag()).as_slice());
1387             }
1388         }
1389     }
1390
1391     pub fn opt_node_ty_substs(&self,
1392                               id: ast::NodeId,
1393                               f: |&ty::ItemSubsts|) {
1394         match self.inh.item_substs.borrow().find(&id) {
1395             Some(s) => { f(s) }
1396             None => { }
1397         }
1398     }
1399
1400     pub fn mk_subty(&self,
1401                     a_is_expected: bool,
1402                     origin: infer::TypeOrigin,
1403                     sub: ty::t,
1404                     sup: ty::t)
1405                     -> Result<(), ty::type_err> {
1406         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1407     }
1408
1409     pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1410                         -> Result<(), ty::type_err> {
1411         infer::can_mk_subty(self.infcx(), sub, sup)
1412     }
1413
1414     pub fn mk_assignty(&self,
1415                        expr: &ast::Expr,
1416                        sub: ty::t,
1417                        sup: ty::t)
1418                        -> Result<(), ty::type_err> {
1419         match infer::mk_coercety(self.infcx(),
1420                                  false,
1421                                  infer::ExprAssignable(expr.span),
1422                                  sub,
1423                                  sup) {
1424             Ok(None) => Ok(()),
1425             Err(ref e) => Err((*e)),
1426             Ok(Some(adjustment)) => {
1427                 self.write_adjustment(expr.id, adjustment);
1428                 Ok(())
1429             }
1430         }
1431     }
1432
1433     pub fn mk_eqty(&self,
1434                    a_is_expected: bool,
1435                    origin: infer::TypeOrigin,
1436                    sub: ty::t,
1437                    sup: ty::t)
1438                    -> Result<(), ty::type_err> {
1439         infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1440     }
1441
1442     pub fn mk_subr(&self,
1443                    a_is_expected: bool,
1444                    origin: infer::SubregionOrigin,
1445                    sub: ty::Region,
1446                    sup: ty::Region) {
1447         infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1448     }
1449
1450     pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1451         let old_region_lb = self.region_lb.get();
1452         self.region_lb.set(lb);
1453         let v = f();
1454         self.region_lb.set(old_region_lb);
1455         v
1456     }
1457
1458     pub fn type_error_message(&self,
1459                               sp: Span,
1460                               mk_msg: |String| -> String,
1461                               actual_ty: ty::t,
1462                               err: Option<&ty::type_err>) {
1463         self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1464     }
1465
1466     pub fn report_mismatched_return_types(&self,
1467                                           sp: Span,
1468                                           e: ty::t,
1469                                           a: ty::t,
1470                                           err: &ty::type_err) {
1471         // Derived error
1472         if ty::type_is_error(e) || ty::type_is_error(a) {
1473             return;
1474         }
1475         self.infcx().report_mismatched_types(sp, e, a, err)
1476     }
1477
1478     pub fn report_mismatched_types(&self,
1479                                    sp: Span,
1480                                    e: ty::t,
1481                                    a: ty::t,
1482                                    err: &ty::type_err) {
1483         self.infcx().report_mismatched_types(sp, e, a, err)
1484     }
1485 }
1486
1487 pub enum LvaluePreference {
1488     PreferMutLvalue,
1489     NoPreference
1490 }
1491
1492 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1493                     expr_id: Option<ast::NodeId>,
1494                     mut lvalue_pref: LvaluePreference,
1495                     should_stop: |ty::t, uint| -> Option<T>)
1496                     -> (ty::t, uint, Option<T>) {
1497     /*!
1498      * Executes an autoderef loop for the type `t`. At each step, invokes
1499      * `should_stop` to decide whether to terminate the loop. Returns
1500      * the final type and number of derefs that it performed.
1501      *
1502      * Note: this method does not modify the adjustments table. The caller is
1503      * responsible for inserting an AutoAdjustment record into the `fcx`
1504      * using one of the suitable methods.
1505      */
1506
1507     let mut t = base_ty;
1508     for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1509         let resolved_t = structurally_resolved_type(fcx, sp, t);
1510
1511         match should_stop(resolved_t, autoderefs) {
1512             Some(x) => return (resolved_t, autoderefs, Some(x)),
1513             None => {}
1514         }
1515
1516         // Otherwise, deref if type is derefable:
1517         let mt = match ty::deref(resolved_t, false) {
1518             Some(mt) => Some(mt),
1519             None => {
1520                 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1521                 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1522             }
1523         };
1524         match mt {
1525             Some(mt) => {
1526                 t = mt.ty;
1527                 if mt.mutbl == ast::MutImmutable {
1528                     lvalue_pref = NoPreference;
1529                 }
1530             }
1531             None => return (resolved_t, autoderefs, None)
1532         }
1533     }
1534
1535     // We've reached the recursion limit, error gracefully.
1536     fcx.tcx().sess.span_err(sp,
1537         format!("reached the recursion limit while auto-dereferencing {}",
1538                 base_ty.repr(fcx.tcx())).as_slice());
1539     (ty::mk_err(), 0, None)
1540 }
1541
1542 /// Attempts to resolve a call expression as an overloaded call.
1543 fn try_overloaded_call(fcx: &FnCtxt,
1544                        call_expression: &ast::Expr,
1545                        callee: Gc<ast::Expr>,
1546                        callee_type: ty::t,
1547                        args: &[Gc<ast::Expr>])
1548                        -> bool {
1549     // Try `FnOnce`, then `FnMut`, then `Fn`.
1550     for &(maybe_function_trait, method_name) in [
1551         (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1552         (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1553         (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1554     ].iter() {
1555         let function_trait = match maybe_function_trait {
1556             None => continue,
1557             Some(function_trait) => function_trait,
1558         };
1559         let method_callee = match method::lookup_in_trait(
1560                 fcx,
1561                 call_expression.span,
1562                 Some(&*callee),
1563                 method_name,
1564                 function_trait,
1565                 callee_type,
1566                 [],
1567                 DontAutoderefReceiver,
1568                 IgnoreStaticMethods) {
1569             None => continue,
1570             Some(method_callee) => method_callee,
1571         };
1572         let method_call = MethodCall::expr(call_expression.id);
1573         let output_type = check_method_argument_types(fcx,
1574                                                       call_expression.span,
1575                                                       method_callee.ty,
1576                                                       call_expression,
1577                                                       args,
1578                                                       DontDerefArgs,
1579                                                       TupleArguments);
1580         fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1581         write_call(fcx, call_expression, output_type);
1582
1583         if !fcx.tcx().sess.features.overloaded_calls.get() {
1584             fcx.tcx().sess.span_err(call_expression.span,
1585                                     "overloaded calls are experimental");
1586             fcx.tcx().sess.span_note(call_expression.span,
1587                                      "add `#[feature(overloaded_calls)]` to \
1588                                       the crate attributes to enable");
1589         }
1590
1591         return true
1592     }
1593
1594     false
1595 }
1596
1597 fn try_overloaded_deref(fcx: &FnCtxt,
1598                         span: Span,
1599                         method_call: Option<MethodCall>,
1600                         base_expr: Option<&ast::Expr>,
1601                         base_ty: ty::t,
1602                         lvalue_pref: LvaluePreference)
1603                         -> Option<ty::mt> {
1604     // Try DerefMut first, if preferred.
1605     let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1606         (PreferMutLvalue, Some(trait_did)) => {
1607             method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1608                                     token::intern("deref_mut"), trait_did,
1609                                     base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1610         }
1611         _ => None
1612     };
1613
1614     // Otherwise, fall back to Deref.
1615     let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1616         (None, Some(trait_did)) => {
1617             method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1618                                     token::intern("deref"), trait_did,
1619                                     base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1620         }
1621         (method, _) => method
1622     };
1623
1624     match method {
1625         Some(method) => {
1626             let ref_ty = ty::ty_fn_ret(method.ty);
1627             match method_call {
1628                 Some(method_call) => {
1629                     fcx.inh.method_map.borrow_mut().insert(method_call, method);
1630                 }
1631                 None => {}
1632             }
1633             ty::deref(ref_ty, true)
1634         }
1635         None => None
1636     }
1637 }
1638
1639 fn try_overloaded_index(fcx: &FnCtxt,
1640                         method_call: Option<MethodCall>,
1641                         expr: &ast::Expr,
1642                         base_expr: Gc<ast::Expr>,
1643                         base_ty: ty::t,
1644                         index_expr: Gc<ast::Expr>,
1645                         lvalue_pref: LvaluePreference)
1646                         -> Option<ty::mt> {
1647     // Try `IndexMut` first, if preferred.
1648     let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1649         (PreferMutLvalue, Some(trait_did)) => {
1650             method::lookup_in_trait(fcx,
1651                                     expr.span,
1652                                     Some(&*base_expr),
1653                                     token::intern("index_mut"),
1654                                     trait_did,
1655                                     base_ty,
1656                                     [],
1657                                     DontAutoderefReceiver,
1658                                     IgnoreStaticMethods)
1659         }
1660         _ => None,
1661     };
1662
1663     // Otherwise, fall back to `Index`.
1664     let method = match (method, fcx.tcx().lang_items.index_trait()) {
1665         (None, Some(trait_did)) => {
1666             method::lookup_in_trait(fcx,
1667                                     expr.span,
1668                                     Some(&*base_expr),
1669                                     token::intern("index"),
1670                                     trait_did,
1671                                     base_ty,
1672                                     [],
1673                                     DontAutoderefReceiver,
1674                                     IgnoreStaticMethods)
1675         }
1676         (method, _) => method,
1677     };
1678
1679     // Regardless of whether the lookup succeeds, check the method arguments
1680     // so that we have *some* type for each argument.
1681     let method_type = match method {
1682         Some(ref method) => method.ty,
1683         None => ty::mk_err()
1684     };
1685     check_method_argument_types(fcx,
1686                                 expr.span,
1687                                 method_type,
1688                                 expr,
1689                                 [base_expr, index_expr],
1690                                 DoDerefArgs,
1691                                 DontTupleArguments);
1692
1693     match method {
1694         Some(method) => {
1695             let ref_ty = ty::ty_fn_ret(method.ty);
1696             match method_call {
1697                 Some(method_call) => {
1698                     fcx.inh.method_map.borrow_mut().insert(method_call,
1699                                                            method);
1700                 }
1701                 None => {}
1702             }
1703             ty::deref(ref_ty, true)
1704         }
1705         None => None,
1706     }
1707 }
1708
1709 fn check_method_argument_types(fcx: &FnCtxt,
1710                                sp: Span,
1711                                method_fn_ty: ty::t,
1712                                callee_expr: &ast::Expr,
1713                                args: &[Gc<ast::Expr>],
1714                                deref_args: DerefArgs,
1715                                tuple_arguments: TupleArgumentsFlag)
1716                                -> ty::t {
1717     // HACK(eddyb) ignore provided self (it has special typeck rules).
1718     let args = if tuple_arguments == DontTupleArguments {
1719         args.slice_from(1)
1720     } else {
1721         args
1722     };
1723     if ty::type_is_error(method_fn_ty) {
1724         let err_inputs = err_args(args.len());
1725         check_argument_types(fcx,
1726                              sp,
1727                              err_inputs.as_slice(),
1728                              callee_expr,
1729                              args,
1730                              deref_args,
1731                              false,
1732                              tuple_arguments);
1733         method_fn_ty
1734     } else {
1735         match ty::get(method_fn_ty).sty {
1736             ty::ty_bare_fn(ref fty) => {
1737                 // HACK(eddyb) ignore self in the definition (see above).
1738                 check_argument_types(fcx,
1739                                      sp,
1740                                      fty.sig.inputs.slice_from(1),
1741                                      callee_expr,
1742                                      args,
1743                                      deref_args,
1744                                      fty.sig.variadic,
1745                                      tuple_arguments);
1746                 fty.sig.output
1747             }
1748             _ => {
1749                 fcx.tcx().sess.span_bug(callee_expr.span,
1750                                         "method without bare fn type");
1751             }
1752         }
1753     }
1754 }
1755
1756 fn check_argument_types(fcx: &FnCtxt,
1757                         sp: Span,
1758                         fn_inputs: &[ty::t],
1759                         callee_expr: &ast::Expr,
1760                         args: &[Gc<ast::Expr>],
1761                         deref_args: DerefArgs,
1762                         variadic: bool,
1763                         tuple_arguments: TupleArgumentsFlag) {
1764     /*!
1765      *
1766      * Generic function that factors out common logic from
1767      * function calls, method calls and overloaded operators.
1768      */
1769
1770     let tcx = fcx.ccx.tcx;
1771
1772     // Grab the argument types, supplying fresh type variables
1773     // if the wrong number of arguments were supplied
1774     let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1775         args.len()
1776     } else {
1777         1
1778     };
1779
1780     let expected_arg_count = fn_inputs.len();
1781     let formal_tys = if tuple_arguments == TupleArguments {
1782         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1783         match ty::get(tuple_type).sty {
1784             ty::ty_tup(ref arg_types) => {
1785                 if arg_types.len() != args.len() {
1786                     let msg = format!(
1787                         "this function takes {} parameter{} \
1788                          but {} parameter{} supplied",
1789                          arg_types.len(),
1790                          if arg_types.len() == 1 {""} else {"s"},
1791                          args.len(),
1792                          if args.len() == 1 {" was"} else {"s were"});
1793                     tcx.sess.span_err(sp, msg.as_slice());
1794                     err_args(args.len())
1795                 } else {
1796                     (*arg_types).clone()
1797                 }
1798             }
1799             ty::ty_nil => {
1800                 if args.len() != 0 {
1801                     let msg = format!(
1802                         "this function takes 0 parameters \
1803                          but {} parameter{} supplied",
1804                          args.len(),
1805                          if args.len() == 1 {" was"} else {"s were"});
1806                     tcx.sess.span_err(sp, msg.as_slice());
1807                 }
1808                 Vec::new()
1809             }
1810             _ => {
1811                 tcx.sess
1812                    .span_err(sp,
1813                              "cannot use call notation; the first type \
1814                               parameter for the function trait is neither a \
1815                               tuple nor unit");
1816                 err_args(supplied_arg_count)
1817             }
1818         }
1819     } else if expected_arg_count == supplied_arg_count {
1820         fn_inputs.iter().map(|a| *a).collect()
1821     } else if variadic {
1822         if supplied_arg_count >= expected_arg_count {
1823             fn_inputs.iter().map(|a| *a).collect()
1824         } else {
1825             let msg = format!(
1826                 "this function takes at least {} parameter{} \
1827                  but {} parameter{} supplied",
1828                  expected_arg_count,
1829                  if expected_arg_count == 1 {""} else {"s"},
1830                  supplied_arg_count,
1831                  if supplied_arg_count == 1 {" was"} else {"s were"});
1832
1833             tcx.sess.span_err(sp, msg.as_slice());
1834
1835             err_args(supplied_arg_count)
1836         }
1837     } else {
1838         let msg = format!(
1839             "this function takes {} parameter{} \
1840              but {} parameter{} supplied",
1841              expected_arg_count,
1842              if expected_arg_count == 1 {""} else {"s"},
1843              supplied_arg_count,
1844              if supplied_arg_count == 1 {" was"} else {"s were"});
1845
1846         tcx.sess.span_err(sp, msg.as_slice());
1847
1848         err_args(supplied_arg_count)
1849     };
1850
1851     debug!("check_argument_types: formal_tys={:?}",
1852            formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
1853
1854     // Check the arguments.
1855     // We do this in a pretty awful way: first we typecheck any arguments
1856     // that are not anonymous functions, then we typecheck the anonymous
1857     // functions. This is so that we have more information about the types
1858     // of arguments when we typecheck the functions. This isn't really the
1859     // right way to do this.
1860     let xs = [false, true];
1861     for check_blocks in xs.iter() {
1862         let check_blocks = *check_blocks;
1863         debug!("check_blocks={}", check_blocks);
1864
1865         // More awful hacks: before we check the blocks, try to do
1866         // an "opportunistic" vtable resolution of any trait
1867         // bounds on the call.
1868         if check_blocks {
1869             vtable::early_resolve_expr(callee_expr, fcx, true);
1870         }
1871
1872         // For variadic functions, we don't have a declared type for all of
1873         // the arguments hence we only do our usual type checking with
1874         // the arguments who's types we do know.
1875         let t = if variadic {
1876             expected_arg_count
1877         } else if tuple_arguments == TupleArguments {
1878             args.len()
1879         } else {
1880             supplied_arg_count
1881         };
1882         for (i, arg) in args.iter().take(t).enumerate() {
1883             let is_block = match arg.node {
1884                 ast::ExprFnBlock(..) |
1885                 ast::ExprProc(..) => true,
1886                 _ => false
1887             };
1888
1889             if is_block == check_blocks {
1890                 debug!("checking the argument");
1891                 let mut formal_ty = *formal_tys.get(i);
1892
1893                 match deref_args {
1894                     DoDerefArgs => {
1895                         match ty::get(formal_ty).sty {
1896                             ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1897                             ty::ty_err => (),
1898                             _ => {
1899                                 // So we hit this case when one implements the
1900                                 // operator traits but leaves an argument as
1901                                 // just T instead of &T. We'll catch it in the
1902                                 // mismatch impl/trait method phase no need to
1903                                 // ICE here.
1904                                 // See: #11450
1905                                 formal_ty = ty::mk_err();
1906                             }
1907                         }
1908                     }
1909                     DontDerefArgs => {}
1910                 }
1911
1912                 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1913
1914             }
1915         }
1916     }
1917
1918     // We also need to make sure we at least write the ty of the other
1919     // arguments which we skipped above.
1920     if variadic {
1921         for arg in args.iter().skip(expected_arg_count) {
1922             check_expr(fcx, &**arg);
1923
1924             // There are a few types which get autopromoted when passed via varargs
1925             // in C but we just error out instead and require explicit casts.
1926             let arg_ty = structurally_resolved_type(fcx, arg.span,
1927                                                     fcx.expr_ty(&**arg));
1928             match ty::get(arg_ty).sty {
1929                 ty::ty_float(ast::TyF32) => {
1930                     fcx.type_error_message(arg.span,
1931                                            |t| {
1932                         format!("can't pass an {} to variadic \
1933                                  function, cast to c_double", t)
1934                     }, arg_ty, None);
1935                 }
1936                 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1937                     fcx.type_error_message(arg.span, |t| {
1938                         format!("can't pass {} to variadic \
1939                                  function, cast to c_int",
1940                                        t)
1941                     }, arg_ty, None);
1942                 }
1943                 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1944                     fcx.type_error_message(arg.span, |t| {
1945                         format!("can't pass {} to variadic \
1946                                  function, cast to c_uint",
1947                                        t)
1948                     }, arg_ty, None);
1949                 }
1950                 _ => {}
1951             }
1952         }
1953     }
1954 }
1955
1956 fn err_args(len: uint) -> Vec<ty::t> {
1957     Vec::from_fn(len, |_| ty::mk_err())
1958 }
1959
1960 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1961     fcx.write_ty(call_expr.id, output);
1962 }
1963
1964 // AST fragment checking
1965 fn check_lit(fcx: &FnCtxt,
1966              lit: &ast::Lit,
1967              expected: Expectation)
1968              -> ty::t
1969 {
1970     let tcx = fcx.ccx.tcx;
1971
1972     match lit.node {
1973         ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1974         ast::LitBinary(..) => {
1975             ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1976         }
1977         ast::LitByte(_) => ty::mk_u8(),
1978         ast::LitChar(_) => ty::mk_char(),
1979         ast::LitInt(_, t) => ty::mk_mach_int(t),
1980         ast::LitUint(_, t) => ty::mk_mach_uint(t),
1981         ast::LitIntUnsuffixed(_) => {
1982             let opt_ty = expected.map_to_option(fcx, |sty| {
1983                 match *sty {
1984                     ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1985                     ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1986                     ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1987                     ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1988                     ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1989                     _ => None
1990                 }
1991             });
1992             opt_ty.unwrap_or_else(
1993                 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1994         }
1995         ast::LitFloat(_, t) => ty::mk_mach_float(t),
1996         ast::LitFloatUnsuffixed(_) => {
1997             let opt_ty = expected.map_to_option(fcx, |sty| {
1998                 match *sty {
1999                     ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2000                     _ => None
2001                 }
2002             });
2003             opt_ty.unwrap_or_else(
2004                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2005         }
2006         ast::LitNil => ty::mk_nil(),
2007         ast::LitBool(_) => ty::mk_bool()
2008     }
2009 }
2010
2011 pub fn valid_range_bounds(ccx: &CrateCtxt,
2012                           from: &ast::Expr,
2013                           to: &ast::Expr)
2014                        -> Option<bool> {
2015     match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2016         Some(val) => Some(val <= 0),
2017         None => None
2018     }
2019 }
2020
2021 pub fn check_expr_has_type(fcx: &FnCtxt,
2022                            expr: &ast::Expr,
2023                            expected: ty::t) {
2024     check_expr_with_unifier(
2025         fcx, expr, ExpectHasType(expected), NoPreference,
2026         || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2027 }
2028
2029 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2030                                 expr: &ast::Expr,
2031                                 expected: ty::t) {
2032     check_expr_with_unifier(
2033         fcx, expr, ExpectHasType(expected), NoPreference,
2034         || demand::coerce(fcx, expr.span, expected, expr));
2035 }
2036
2037 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2038     check_expr_with_unifier(
2039         fcx, expr, ExpectHasType(expected), NoPreference,
2040         || ())
2041 }
2042
2043 fn check_expr_with_expectation(fcx: &FnCtxt,
2044                                expr: &ast::Expr,
2045                                expected: Expectation) {
2046     check_expr_with_unifier(
2047         fcx, expr, expected, NoPreference,
2048         || ())
2049 }
2050
2051 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2052                                             expr: &ast::Expr,
2053                                             expected: Expectation,
2054                                             lvalue_pref: LvaluePreference)
2055 {
2056     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2057 }
2058
2059 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr)  {
2060     check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2061 }
2062
2063 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2064                                lvalue_pref: LvaluePreference)  {
2065     check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2066 }
2067
2068
2069 // determine the `self` type, using fresh variables for all variables
2070 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2071 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2072 // variables.
2073 pub fn impl_self_ty(vcx: &VtableContext,
2074                     span: Span, // (potential) receiver for this impl
2075                     did: ast::DefId)
2076                     -> TypeAndSubsts {
2077     let tcx = vcx.tcx();
2078
2079     let ity = ty::lookup_item_type(tcx, did);
2080     let (n_tps, rps, raw_ty) =
2081         (ity.generics.types.len(subst::TypeSpace),
2082          ity.generics.regions.get_slice(subst::TypeSpace),
2083          ity.ty);
2084
2085     let rps = vcx.infcx.region_vars_for_defs(span, rps);
2086     let tps = vcx.infcx.next_ty_vars(n_tps);
2087     let substs = subst::Substs::new_type(tps, rps);
2088     let substd_ty = raw_ty.subst(tcx, &substs);
2089
2090     TypeAndSubsts { substs: substs, ty: substd_ty }
2091 }
2092
2093 // Only for fields! Returns <none> for methods>
2094 // Indifferent to privacy flags
2095 pub fn lookup_field_ty(tcx: &ty::ctxt,
2096                        class_id: ast::DefId,
2097                        items: &[ty::field_ty],
2098                        fieldname: ast::Name,
2099                        substs: &subst::Substs) -> Option<ty::t> {
2100
2101     let o_field = items.iter().find(|f| f.name == fieldname);
2102     o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2103 }
2104
2105 // Controls whether the arguments are automatically referenced. This is useful
2106 // for overloaded binary and unary operators.
2107 pub enum DerefArgs {
2108     DontDerefArgs,
2109     DoDerefArgs
2110 }
2111
2112 /// Controls whether the arguments are tupled. This is used for the call
2113 /// operator.
2114 ///
2115 /// Tupling means that all call-side arguments are packed into a tuple and
2116 /// passed as a single parameter. For example, if tupling is enabled, this
2117 /// function:
2118 ///
2119 ///     fn f(x: (int, int))
2120 ///
2121 /// Can be called as:
2122 ///
2123 ///     f(1, 2);
2124 ///
2125 /// Instead of:
2126 ///
2127 ///     f((1, 2));
2128 #[deriving(Clone, Eq, PartialEq)]
2129 enum TupleArgumentsFlag {
2130     DontTupleArguments,
2131     TupleArguments,
2132 }
2133
2134 /// Invariant:
2135 /// If an expression has any sub-expressions that result in a type error,
2136 /// inspecting that expression's type with `ty::type_is_error` will return
2137 /// true. Likewise, if an expression is known to diverge, inspecting its
2138 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2139 /// strict, _|_ can appear in the type of an expression that does not,
2140 /// itself, diverge: for example, fn() -> _|_.)
2141 /// Note that inspecting a type's structure *directly* may expose the fact
2142 /// that there are actually multiple representations for both `ty_err` and
2143 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2144 fn check_expr_with_unifier(fcx: &FnCtxt,
2145                            expr: &ast::Expr,
2146                            expected: Expectation,
2147                            lvalue_pref: LvaluePreference,
2148                            unifier: ||)
2149 {
2150     debug!(">> typechecking");
2151
2152     // A generic function for doing all of the checking for call expressions
2153     fn check_call(fcx: &FnCtxt,
2154                   call_expr: &ast::Expr,
2155                   f: &ast::Expr,
2156                   args: &[Gc<ast::Expr>]) {
2157         // Store the type of `f` as the type of the callee
2158         let fn_ty = fcx.expr_ty(f);
2159
2160         // Extract the function signature from `in_fty`.
2161         let fn_sty = structure_of(fcx, f.span, fn_ty);
2162
2163         // This is the "default" function signature, used in case of error.
2164         // In that case, we check each argument against "error" in order to
2165         // set up all the node type bindings.
2166         let error_fn_sig = FnSig {
2167             binder_id: ast::CRATE_NODE_ID,
2168             inputs: err_args(args.len()),
2169             output: ty::mk_err(),
2170             variadic: false
2171         };
2172
2173         let fn_sig = match *fn_sty {
2174             ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2175             ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2176             _ => {
2177                 fcx.type_error_message(call_expr.span, |actual| {
2178                     format!("expected function but found `{}`", actual)
2179                 }, fn_ty, None);
2180                 &error_fn_sig
2181             }
2182         };
2183
2184         // Replace any bound regions that appear in the function
2185         // signature with region variables
2186         let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2187             fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2188         });
2189
2190         // Call the generic checker.
2191         check_argument_types(fcx,
2192                              call_expr.span,
2193                              fn_sig.inputs.as_slice(),
2194                              f,
2195                              args,
2196                              DontDerefArgs,
2197                              fn_sig.variadic,
2198                              DontTupleArguments);
2199
2200         write_call(fcx, call_expr, fn_sig.output);
2201     }
2202
2203     // Checks a method call.
2204     fn check_method_call(fcx: &FnCtxt,
2205                          expr: &ast::Expr,
2206                          method_name: ast::SpannedIdent,
2207                          args: &[Gc<ast::Expr>],
2208                          tps: &[ast::P<ast::Ty>]) {
2209         let rcvr = args[0].clone();
2210         // We can't know if we need &mut self before we look up the method,
2211         // so treat the receiver as mutable just in case - only explicit
2212         // overloaded dereferences care about the distinction.
2213         check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2214
2215         // no need to check for bot/err -- callee does that
2216         let expr_t = structurally_resolved_type(fcx,
2217                                                 expr.span,
2218                                                 fcx.expr_ty(&*rcvr));
2219
2220         let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2221         let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2222                                          method_name.node.name,
2223                                          expr_t, tps.as_slice(),
2224                                          DontDerefArgs,
2225                                          CheckTraitsAndInherentMethods,
2226                                          AutoderefReceiver, IgnoreStaticMethods) {
2227             Some(method) => {
2228                 let method_ty = method.ty;
2229                 let method_call = MethodCall::expr(expr.id);
2230                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2231                 method_ty
2232             }
2233             None => {
2234                 debug!("(checking method call) failing expr is {}", expr.id);
2235
2236                 fcx.type_error_message(method_name.span,
2237                   |actual| {
2238                       format!("type `{}` does not implement any \
2239                                method in scope named `{}`",
2240                               actual,
2241                               token::get_ident(method_name.node))
2242                   },
2243                   expr_t,
2244                   None);
2245
2246                 // Add error type for the result
2247                 fcx.write_error(expr.id);
2248
2249                 // Check for potential static matches (missing self parameters)
2250                 method::lookup(fcx,
2251                                expr,
2252                                &*rcvr,
2253                                method_name.node.name,
2254                                expr_t,
2255                                tps.as_slice(),
2256                                DontDerefArgs,
2257                                CheckTraitsAndInherentMethods,
2258                                DontAutoderefReceiver,
2259                                ReportStaticMethods);
2260
2261                 ty::mk_err()
2262             }
2263         };
2264
2265         // Call the generic checker.
2266         let ret_ty = check_method_argument_types(fcx,
2267                                                  method_name.span,
2268                                                  fn_ty,
2269                                                  expr,
2270                                                  args,
2271                                                  DontDerefArgs,
2272                                                  DontTupleArguments);
2273
2274         write_call(fcx, expr, ret_ty);
2275     }
2276
2277     // A generic function for checking the then and else in an if
2278     // or if-check
2279     fn check_then_else(fcx: &FnCtxt,
2280                        cond_expr: &ast::Expr,
2281                        then_blk: &ast::Block,
2282                        opt_else_expr: Option<Gc<ast::Expr>>,
2283                        id: ast::NodeId,
2284                        sp: Span,
2285                        expected: Expectation) {
2286         check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2287
2288         let branches_ty = match opt_else_expr {
2289             Some(ref else_expr) => {
2290                 // Disregard "castable to" expectations because they
2291                 // can lead us astray. Consider for example `if cond
2292                 // {22} else {c} as u8` -- if we propagate the
2293                 // "castable to u8" constraint to 22, it will pick the
2294                 // type 22u8, which is overly constrained (c might not
2295                 // be a u8). In effect, the problem is that the
2296                 // "castable to" expectation is not the tightest thing
2297                 // we can say, so we want to drop it in this case.
2298                 // The tightest thing we can say is "must unify with
2299                 // else branch". Note that in the case of a "has type"
2300                 // constraint, this limitation does not hold.
2301                 let expected = expected.only_has_type();
2302
2303                 check_block_with_expected(fcx, then_blk, expected);
2304                 let then_ty = fcx.node_ty(then_blk.id);
2305                 check_expr_with_expectation(fcx, &**else_expr, expected);
2306                 let else_ty = fcx.expr_ty(&**else_expr);
2307                 infer::common_supertype(fcx.infcx(),
2308                                         infer::IfExpression(sp),
2309                                         true,
2310                                         then_ty,
2311                                         else_ty)
2312             }
2313             None => {
2314                 check_block_no_value(fcx, then_blk);
2315                 ty::mk_nil()
2316             }
2317         };
2318
2319         let cond_ty = fcx.expr_ty(cond_expr);
2320         let if_ty = if ty::type_is_error(cond_ty) {
2321             ty::mk_err()
2322         } else if ty::type_is_bot(cond_ty) {
2323             ty::mk_bot()
2324         } else {
2325             branches_ty
2326         };
2327
2328         fcx.write_ty(id, if_ty);
2329     }
2330
2331     fn lookup_op_method(fcx: &FnCtxt,
2332                         op_ex: &ast::Expr,
2333                         self_t: ty::t,
2334                         opname: ast::Name,
2335                         trait_did: Option<ast::DefId>,
2336                         args: &[Gc<ast::Expr>],
2337                         autoderef_receiver: AutoderefReceiverFlag,
2338                         unbound_method: ||) -> ty::t {
2339         let method = match trait_did {
2340             Some(trait_did) => {
2341                 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2342                                         trait_did, self_t, [], autoderef_receiver,
2343                                         IgnoreStaticMethods)
2344             }
2345             None => None
2346         };
2347         match method {
2348             Some(method) => {
2349                 let method_ty = method.ty;
2350                 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2351                 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2352                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2353                 check_method_argument_types(fcx,
2354                                             op_ex.span,
2355                                             method_ty,
2356                                             op_ex,
2357                                             args,
2358                                             DoDerefArgs,
2359                                             DontTupleArguments)
2360             }
2361             None => {
2362                 unbound_method();
2363                 // Check the args anyway
2364                 // so we get all the error messages
2365                 let expected_ty = ty::mk_err();
2366                 check_method_argument_types(fcx,
2367                                             op_ex.span,
2368                                             expected_ty,
2369                                             op_ex,
2370                                             args,
2371                                             DoDerefArgs,
2372                                             DontTupleArguments);
2373                 ty::mk_err()
2374             }
2375         }
2376     }
2377
2378     // could be either an expr_binop or an expr_assign_binop
2379     fn check_binop(fcx: &FnCtxt,
2380                    expr: &ast::Expr,
2381                    op: ast::BinOp,
2382                    lhs: Gc<ast::Expr>,
2383                    rhs: Gc<ast::Expr>,
2384                    is_binop_assignment: IsBinopAssignment) {
2385         let tcx = fcx.ccx.tcx;
2386
2387         let lvalue_pref = match is_binop_assignment {
2388             BinopAssignment => PreferMutLvalue,
2389             SimpleBinop => NoPreference
2390         };
2391         check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2392
2393         // Callee does bot / err checking
2394         let lhs_t = structurally_resolved_type(fcx, lhs.span,
2395                                                fcx.expr_ty(&*lhs));
2396
2397         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2398             // Shift is a special case: rhs must be uint, no matter what lhs is
2399             check_expr_has_type(fcx, rhs, ty::mk_uint());
2400             fcx.write_ty(expr.id, lhs_t);
2401             return;
2402         }
2403
2404         if ty::is_binopable(tcx, lhs_t, op) {
2405             let tvar = fcx.infcx().next_ty_var();
2406             demand::suptype(fcx, expr.span, tvar, lhs_t);
2407             check_expr_has_type(fcx, &*rhs, tvar);
2408
2409             let result_t = match op {
2410                 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2411                 ast::BiGt => {
2412                     if ty::type_is_simd(tcx, lhs_t) {
2413                         if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2414                             fcx.type_error_message(expr.span,
2415                                 |actual| {
2416                                     format!("binary comparison \
2417                                              operation `{}` not \
2418                                              supported for floating \
2419                                              point SIMD vector `{}`",
2420                                             ast_util::binop_to_string(op),
2421                                             actual)
2422                                 },
2423                                 lhs_t,
2424                                 None
2425                             );
2426                             ty::mk_err()
2427                         } else {
2428                             lhs_t
2429                         }
2430                     } else {
2431                         ty::mk_bool()
2432                     }
2433                 },
2434                 _ => lhs_t,
2435             };
2436
2437             fcx.write_ty(expr.id, result_t);
2438             return;
2439         }
2440
2441         if op == ast::BiOr || op == ast::BiAnd {
2442             // This is an error; one of the operands must have the wrong
2443             // type
2444             fcx.write_error(expr.id);
2445             fcx.write_error(rhs.id);
2446             fcx.type_error_message(expr.span,
2447                                    |actual| {
2448                     format!("binary operation `{}` cannot be applied \
2449                              to type `{}`",
2450                             ast_util::binop_to_string(op),
2451                             actual)
2452                 },
2453                 lhs_t,
2454                 None)
2455         }
2456
2457         // Check for overloaded operators if not an assignment.
2458         let result_t = if is_binop_assignment == SimpleBinop {
2459             check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2460         } else {
2461             fcx.type_error_message(expr.span,
2462                                    |actual| {
2463                                         format!("binary assignment \
2464                                                  operation `{}=` \
2465                                                  cannot be applied to \
2466                                                  type `{}`",
2467                                                 ast_util::binop_to_string(op),
2468                                                 actual)
2469                                    },
2470                                    lhs_t,
2471                                    None);
2472             check_expr(fcx, &*rhs);
2473             ty::mk_err()
2474         };
2475
2476         fcx.write_ty(expr.id, result_t);
2477         if ty::type_is_error(result_t) {
2478             fcx.write_ty(rhs.id, result_t);
2479         }
2480     }
2481
2482     fn check_user_binop(fcx: &FnCtxt,
2483                         ex: &ast::Expr,
2484                         lhs_expr: Gc<ast::Expr>,
2485                         lhs_resolved_t: ty::t,
2486                         op: ast::BinOp,
2487                         rhs: Gc<ast::Expr>) -> ty::t {
2488         let tcx = fcx.ccx.tcx;
2489         let lang = &tcx.lang_items;
2490         let (name, trait_did) = match op {
2491             ast::BiAdd => ("add", lang.add_trait()),
2492             ast::BiSub => ("sub", lang.sub_trait()),
2493             ast::BiMul => ("mul", lang.mul_trait()),
2494             ast::BiDiv => ("div", lang.div_trait()),
2495             ast::BiRem => ("rem", lang.rem_trait()),
2496             ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2497             ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2498             ast::BiBitOr => ("bitor", lang.bitor_trait()),
2499             ast::BiShl => ("shl", lang.shl_trait()),
2500             ast::BiShr => ("shr", lang.shr_trait()),
2501             ast::BiLt => ("lt", lang.ord_trait()),
2502             ast::BiLe => ("le", lang.ord_trait()),
2503             ast::BiGe => ("ge", lang.ord_trait()),
2504             ast::BiGt => ("gt", lang.ord_trait()),
2505             ast::BiEq => ("eq", lang.eq_trait()),
2506             ast::BiNe => ("ne", lang.eq_trait()),
2507             ast::BiAnd | ast::BiOr => {
2508                 check_expr(fcx, &*rhs);
2509                 return ty::mk_err();
2510             }
2511         };
2512         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2513                          trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2514             fcx.type_error_message(ex.span, |actual| {
2515                 format!("binary operation `{}` cannot be applied to type `{}`",
2516                         ast_util::binop_to_string(op),
2517                         actual)
2518             }, lhs_resolved_t, None)
2519         })
2520     }
2521
2522     fn check_user_unop(fcx: &FnCtxt,
2523                        op_str: &str,
2524                        mname: &str,
2525                        trait_did: Option<ast::DefId>,
2526                        ex: &ast::Expr,
2527                        rhs_expr: Gc<ast::Expr>,
2528                        rhs_t: ty::t) -> ty::t {
2529        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2530                         trait_did, [rhs_expr], DontAutoderefReceiver, || {
2531             fcx.type_error_message(ex.span, |actual| {
2532                 format!("cannot apply unary operator `{}` to type `{}`",
2533                         op_str, actual)
2534             }, rhs_t, None);
2535         })
2536     }
2537
2538     fn check_expr_fn(fcx: &FnCtxt,
2539                      expr: &ast::Expr,
2540                      store: ty::TraitStore,
2541                      decl: &ast::FnDecl,
2542                      body: ast::P<ast::Block>,
2543                      expected: Expectation) {
2544         let tcx = fcx.ccx.tcx;
2545
2546         // Find the expected input/output types (if any). Substitute
2547         // fresh bound regions for any bound regions we find in the
2548         // expected types so as to avoid capture.
2549         let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2550         let (expected_sig,
2551              expected_onceness,
2552              expected_bounds) = {
2553             match expected_sty {
2554                 Some(ty::ty_closure(ref cenv)) => {
2555                     let (_, sig) =
2556                         replace_late_bound_regions_in_fn_sig(
2557                             tcx, &cenv.sig,
2558                             |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2559                     let onceness = match (&store, &cenv.store) {
2560                         // As the closure type and onceness go, only three
2561                         // combinations are legit:
2562                         //      once closure
2563                         //      many closure
2564                         //      once proc
2565                         // If the actual and expected closure type disagree with
2566                         // each other, set expected onceness to be always Once or
2567                         // Many according to the actual type. Otherwise, it will
2568                         // yield either an illegal "many proc" or a less known
2569                         // "once closure" in the error message.
2570                         (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2571                         (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2572                             cenv.onceness,
2573                         (&ty::UniqTraitStore, _) => ast::Once,
2574                         (&ty::RegionTraitStore(..), _) => ast::Many,
2575                     };
2576                     (Some(sig), onceness, cenv.bounds)
2577                 }
2578                 _ => {
2579                     // Not an error! Means we're inferring the closure type
2580                     let mut bounds = ty::empty_builtin_bounds();
2581                     let onceness = match expr.node {
2582                         ast::ExprProc(..) => {
2583                             bounds.add(ty::BoundSend);
2584                             ast::Once
2585                         }
2586                         _ => ast::Many
2587                     };
2588                     (None, onceness, bounds)
2589                 }
2590             }
2591         };
2592
2593         // construct the function type
2594         let fn_ty = astconv::ty_of_closure(fcx,
2595                                            expr.id,
2596                                            ast::NormalFn,
2597                                            expected_onceness,
2598                                            expected_bounds,
2599                                            store,
2600                                            decl,
2601                                            expected_sig);
2602         let fty_sig = fn_ty.sig.clone();
2603         let fty = ty::mk_closure(tcx, fn_ty);
2604         debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
2605
2606         fcx.write_ty(expr.id, fty);
2607
2608         // If the closure is a stack closure and hasn't had some non-standard
2609         // style inferred for it, then check it under its parent's style.
2610         // Otherwise, use its own
2611         let (inherited_style, id) = match store {
2612             ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2613                                          fcx.ps.borrow().def),
2614             ty::UniqTraitStore => (ast::NormalFn, expr.id)
2615         };
2616
2617         check_fn(fcx.ccx, inherited_style, &fty_sig,
2618                  &*decl, id, &*body, fcx.inh);
2619     }
2620
2621
2622     // Check field access expressions
2623     fn check_field(fcx: &FnCtxt,
2624                    expr: &ast::Expr,
2625                    lvalue_pref: LvaluePreference,
2626                    base: &ast::Expr,
2627                    field: &ast::SpannedIdent,
2628                    tys: &[ast::P<ast::Ty>]) {
2629         let tcx = fcx.ccx.tcx;
2630         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2631         let expr_t = structurally_resolved_type(fcx, expr.span,
2632                                                 fcx.expr_ty(base));
2633         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2634         let (_, autoderefs, field_ty) =
2635             autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2636                 match ty::get(base_t).sty {
2637                     ty::ty_struct(base_id, ref substs) => {
2638                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2639                         let fields = ty::lookup_struct_fields(tcx, base_id);
2640                         lookup_field_ty(tcx, base_id, fields.as_slice(),
2641                                         field.node.name, &(*substs))
2642                     }
2643                     _ => None
2644                 }
2645             });
2646         match field_ty {
2647             Some(field_ty) => {
2648                 fcx.write_ty(expr.id, field_ty);
2649                 fcx.write_autoderef_adjustment(base.id, autoderefs);
2650                 return;
2651             }
2652             None => {}
2653         }
2654
2655         let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2656         match method::lookup(fcx,
2657                              expr,
2658                              base,
2659                              field.node.name,
2660                              expr_t,
2661                              tps.as_slice(),
2662                              DontDerefArgs,
2663                              CheckTraitsAndInherentMethods,
2664                              AutoderefReceiver,
2665                              IgnoreStaticMethods) {
2666             Some(_) => {
2667                 fcx.type_error_message(
2668                     field.span,
2669                     |actual| {
2670                         format!("attempted to take value of method `{}` on type \
2671                                  `{}`", token::get_ident(field.node), actual)
2672                     },
2673                     expr_t, None);
2674
2675                 tcx.sess.span_note(field.span,
2676                     "maybe a missing `()` to call it? If not, try an anonymous function.");
2677             }
2678
2679             None => {
2680                 fcx.type_error_message(
2681                     expr.span,
2682                     |actual| {
2683                         format!("attempted access of field `{}` on \
2684                                         type `{}`, but no field with that \
2685                                         name was found",
2686                                        token::get_ident(field.node),
2687                                        actual)
2688                     },
2689                     expr_t, None);
2690             }
2691         }
2692
2693         fcx.write_error(expr.id);
2694     }
2695
2696     fn check_struct_or_variant_fields(fcx: &FnCtxt,
2697                                       struct_ty: ty::t,
2698                                       span: Span,
2699                                       class_id: ast::DefId,
2700                                       node_id: ast::NodeId,
2701                                       substitutions: subst::Substs,
2702                                       field_types: &[ty::field_ty],
2703                                       ast_fields: &[ast::Field],
2704                                       check_completeness: bool)  {
2705         let tcx = fcx.ccx.tcx;
2706
2707         let mut class_field_map = HashMap::new();
2708         let mut fields_found = 0;
2709         for field in field_types.iter() {
2710             class_field_map.insert(field.name, (field.id, false));
2711         }
2712
2713         let mut error_happened = false;
2714
2715         // Typecheck each field.
2716         for field in ast_fields.iter() {
2717             let mut expected_field_type = ty::mk_err();
2718
2719             let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2720             match pair {
2721                 None => {
2722                     fcx.type_error_message(
2723                       field.ident.span,
2724                       |actual| {
2725                           format!("structure `{}` has no field named `{}`",
2726                                   actual, token::get_ident(field.ident.node))
2727                       },
2728                       struct_ty,
2729                       None);
2730                     error_happened = true;
2731                 }
2732                 Some((_, true)) => {
2733                     tcx.sess.span_err(
2734                         field.ident.span,
2735                         format!("field `{}` specified more than once",
2736                                 token::get_ident(field.ident
2737                                                       .node)).as_slice());
2738                     error_happened = true;
2739                 }
2740                 Some((field_id, false)) => {
2741                     expected_field_type =
2742                         ty::lookup_field_type(
2743                             tcx, class_id, field_id, &substitutions);
2744                     class_field_map.insert(
2745                         field.ident.node.name, (field_id, true));
2746                     fields_found += 1;
2747                 }
2748             }
2749             // Make sure to give a type to the field even if there's
2750             // an error, so we can continue typechecking
2751             check_expr_coercable_to_type(
2752                     fcx,
2753                     &*field.expr,
2754                     expected_field_type);
2755         }
2756
2757         if error_happened {
2758             fcx.write_error(node_id);
2759         }
2760
2761         if check_completeness && !error_happened {
2762             // Make sure the programmer specified all the fields.
2763             assert!(fields_found <= field_types.len());
2764             if fields_found < field_types.len() {
2765                 let mut missing_fields = Vec::new();
2766                 for class_field in field_types.iter() {
2767                     let name = class_field.name;
2768                     let (_, seen) = *class_field_map.get(&name);
2769                     if !seen {
2770                         missing_fields.push(
2771                             format!("`{}`", token::get_name(name).get()))
2772                     }
2773                 }
2774
2775                 tcx.sess.span_err(span,
2776                     format!(
2777                         "missing field{}: {fields}",
2778                         if missing_fields.len() == 1 {""} else {"s"},
2779                         fields = missing_fields.connect(", ")).as_slice());
2780              }
2781         }
2782
2783         if !error_happened {
2784             fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2785                                 class_id, substitutions));
2786         }
2787     }
2788
2789     fn check_struct_constructor(fcx: &FnCtxt,
2790                                 id: ast::NodeId,
2791                                 span: codemap::Span,
2792                                 class_id: ast::DefId,
2793                                 fields: &[ast::Field],
2794                                 base_expr: Option<Gc<ast::Expr>>) {
2795         let tcx = fcx.ccx.tcx;
2796
2797         // Look up the number of type parameters and the raw type, and
2798         // determine whether the class is region-parameterized.
2799         let item_type = ty::lookup_item_type(tcx, class_id);
2800         let raw_type = item_type.ty;
2801
2802         // Generate the struct type.
2803         let substitutions = fcx.infcx().fresh_substs_for_type(
2804             span, &item_type.generics);
2805         let mut struct_type = raw_type.subst(tcx, &substitutions);
2806
2807         // Look up and check the fields.
2808         let class_fields = ty::lookup_struct_fields(tcx, class_id);
2809         check_struct_or_variant_fields(fcx,
2810                                        struct_type,
2811                                        span,
2812                                        class_id,
2813                                        id,
2814                                        substitutions,
2815                                        class_fields.as_slice(),
2816                                        fields,
2817                                        base_expr.is_none());
2818         if ty::type_is_error(fcx.node_ty(id)) {
2819             struct_type = ty::mk_err();
2820         }
2821
2822         // Check the base expression if necessary.
2823         match base_expr {
2824             None => {}
2825             Some(base_expr) => {
2826                 check_expr_has_type(fcx, &*base_expr, struct_type);
2827                 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2828                     struct_type = ty::mk_bot();
2829                 }
2830             }
2831         }
2832
2833         // Write in the resulting type.
2834         fcx.write_ty(id, struct_type);
2835     }
2836
2837     fn check_struct_enum_variant(fcx: &FnCtxt,
2838                                  id: ast::NodeId,
2839                                  span: codemap::Span,
2840                                  enum_id: ast::DefId,
2841                                  variant_id: ast::DefId,
2842                                  fields: &[ast::Field]) {
2843         let tcx = fcx.ccx.tcx;
2844
2845         // Look up the number of type parameters and the raw type, and
2846         // determine whether the enum is region-parameterized.
2847         let item_type = ty::lookup_item_type(tcx, enum_id);
2848         let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2849         let enum_type = item_type.ty.subst(tcx, &substitutions);
2850
2851         // Look up and check the enum variant fields.
2852         let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2853         check_struct_or_variant_fields(fcx,
2854                                        enum_type,
2855                                        span,
2856                                        variant_id,
2857                                        id,
2858                                        substitutions,
2859                                        variant_fields.as_slice(),
2860                                        fields,
2861                                        true);
2862         fcx.write_ty(id, enum_type);
2863     }
2864
2865     type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2866
2867     fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2868                                           expected: Expectation)
2869                                          -> (ExprCheckerWithTy, ty::t) {
2870         let tcx = fcx.ccx.tcx;
2871         let (coerce, t) = match expected {
2872             // If we're given an expected type, we can try to coerce to it
2873             ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2874             // Otherwise we just leave the type to be resolved later
2875             _ => (false, fcx.infcx().next_ty_var())
2876         };
2877         if coerce {
2878             (check_expr_coercable_to_type, t)
2879         } else {
2880             (check_expr_has_type, t)
2881         }
2882     }
2883
2884     let tcx = fcx.ccx.tcx;
2885     let id = expr.id;
2886     match expr.node {
2887         ast::ExprVstore(ev, vst) => {
2888             let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2889             let typ = match ev.node {
2890                 ast::ExprVec(ref args) => {
2891                     let mutability = match vst {
2892                         ast::ExprVstoreMutSlice => ast::MutMutable,
2893                         _ => ast::MutImmutable,
2894                     };
2895                     let mut any_error = false;
2896                     let mut any_bot = false;
2897                     for e in args.iter() {
2898                         check(fcx, &**e, t);
2899                         let arg_t = fcx.expr_ty(&**e);
2900                         if ty::type_is_error(arg_t) {
2901                             any_error = true;
2902                         }
2903                         else if ty::type_is_bot(arg_t) {
2904                             any_bot = true;
2905                         }
2906                     }
2907                     if any_error {
2908                         ty::mk_err()
2909                     } else if any_bot {
2910                         ty::mk_bot()
2911                     } else {
2912                         ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2913                             ty::mt{ ty: ty::mk_vec(tcx,
2914                                                    ty::mt {ty: t, mutbl: mutability},
2915                                                    None),
2916                                                    mutbl: mutability })
2917                     }
2918                 }
2919                 ast::ExprRepeat(ref element, ref count_expr) => {
2920                     check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2921                     let _ = ty::eval_repeat_count(fcx, &**count_expr);
2922                     let mutability = match vst {
2923                         ast::ExprVstoreMutSlice => ast::MutMutable,
2924                         _ => ast::MutImmutable,
2925                     };
2926                     check(fcx, &**element, t);
2927                     let arg_t = fcx.expr_ty(&**element);
2928                     if ty::type_is_error(arg_t) {
2929                         ty::mk_err()
2930                     } else if ty::type_is_bot(arg_t) {
2931                         ty::mk_bot()
2932                     } else {
2933                         ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2934                             ty::mt{ ty: ty::mk_vec(tcx,
2935                                                    ty::mt {ty: t, mutbl: mutability},
2936                                                    None),
2937                                                    mutbl: mutability})
2938                     }
2939                 }
2940                 ast::ExprLit(_) => {
2941                     let error = if vst == ast::ExprVstoreSlice {
2942                         "`&\"string\"` has been removed; use `\"string\"` instead"
2943                     } else {
2944                         "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2945                     };
2946                     tcx.sess.span_err(expr.span, error);
2947                     ty::mk_err()
2948                 }
2949                 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2950             };
2951             fcx.write_ty(ev.id, typ);
2952             fcx.write_ty(id, typ);
2953         }
2954
2955       ast::ExprBox(ref place, ref subexpr) => {
2956           check_expr(fcx, &**place);
2957           check_expr(fcx, &**subexpr);
2958
2959           let mut checked = false;
2960           match place.node {
2961               ast::ExprPath(ref path) => {
2962                   // FIXME(pcwalton): For now we hardcode the two permissible
2963                   // places: the exchange heap and the managed heap.
2964                   let definition = lookup_def(fcx, path.span, place.id);
2965                   let def_id = definition.def_id();
2966                   if tcx.lang_items.exchange_heap() == Some(def_id) {
2967                       fcx.write_ty(id, ty::mk_uniq(tcx,
2968                                                    fcx.expr_ty(&**subexpr)));
2969                       checked = true
2970                   } else if tcx.lang_items.managed_heap() == Some(def_id) {
2971                       fcx.write_ty(id, ty::mk_box(tcx,
2972                                                   fcx.expr_ty(&**subexpr)));
2973                       checked = true
2974                   }
2975               }
2976               _ => {}
2977           }
2978
2979           if !checked {
2980               tcx.sess.span_err(expr.span,
2981                                 "only the managed heap and exchange heap are \
2982                                  currently supported");
2983               fcx.write_ty(id, ty::mk_err());
2984           }
2985       }
2986
2987       ast::ExprLit(lit) => {
2988         let typ = check_lit(fcx, lit, expected);
2989         fcx.write_ty(id, typ);
2990       }
2991       ast::ExprBinary(op, ref lhs, ref rhs) => {
2992         check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2993
2994         let lhs_ty = fcx.expr_ty(&**lhs);
2995         let rhs_ty = fcx.expr_ty(&**rhs);
2996         if ty::type_is_error(lhs_ty) ||
2997             ty::type_is_error(rhs_ty) {
2998             fcx.write_error(id);
2999         }
3000         else if ty::type_is_bot(lhs_ty) ||
3001           (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3002             fcx.write_bot(id);
3003         }
3004       }
3005       ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3006         check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3007
3008         let lhs_t = fcx.expr_ty(&**lhs);
3009         let result_t = fcx.expr_ty(expr);
3010         demand::suptype(fcx, expr.span, result_t, lhs_t);
3011
3012         let tcx = fcx.tcx();
3013         if !ty::expr_is_lval(tcx, &**lhs) {
3014             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3015         }
3016
3017         // Overwrite result of check_binop...this preserves existing behavior
3018         // but seems quite dubious with regard to user-defined methods
3019         // and so forth. - Niko
3020         if !ty::type_is_error(result_t)
3021             && !ty::type_is_bot(result_t) {
3022             fcx.write_nil(expr.id);
3023         }
3024       }
3025       ast::ExprUnary(unop, ref oprnd) => {
3026         let expected = expected.only_has_type();
3027         let expected_inner = expected.map(fcx, |sty| {
3028             match unop {
3029                 ast::UnBox | ast::UnUniq => match *sty {
3030                     ty::ty_box(ty) | ty::ty_uniq(ty) => {
3031                         ExpectHasType(ty)
3032                     }
3033                     _ => {
3034                         NoExpectation
3035                     }
3036                 },
3037                 ast::UnNot | ast::UnNeg => {
3038                     expected
3039                 }
3040                 ast::UnDeref => {
3041                     NoExpectation
3042                 }
3043             }
3044         });
3045         let lvalue_pref = match unop {
3046             ast::UnDeref => lvalue_pref,
3047             _ => NoPreference
3048         };
3049         check_expr_with_expectation_and_lvalue_pref(
3050             fcx, &**oprnd, expected_inner, lvalue_pref);
3051         let mut oprnd_t = fcx.expr_ty(&**oprnd);
3052         if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3053             match unop {
3054                 ast::UnBox => {
3055                     oprnd_t = ty::mk_box(tcx, oprnd_t)
3056                 }
3057                 ast::UnUniq => {
3058                     oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3059                 }
3060                 ast::UnDeref => {
3061                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3062                     oprnd_t = match ty::deref(oprnd_t, true) {
3063                         Some(mt) => mt.ty,
3064                         None => match try_overloaded_deref(fcx, expr.span,
3065                                                            Some(MethodCall::expr(expr.id)),
3066                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
3067                             Some(mt) => mt.ty,
3068                             None => {
3069                                 let is_newtype = match ty::get(oprnd_t).sty {
3070                                     ty::ty_struct(did, ref substs) => {
3071                                         let fields = ty::struct_fields(fcx.tcx(), did, substs);
3072                                         fields.len() == 1
3073                                         && fields.get(0).ident ==
3074                                         token::special_idents::unnamed_field
3075                                     }
3076                                     _ => false
3077                                 };
3078                                 if is_newtype {
3079                                     // This is an obsolete struct deref
3080                                     tcx.sess.span_err(expr.span,
3081                                         "single-field tuple-structs can \
3082                                          no longer be dereferenced");
3083                                 } else {
3084                                     fcx.type_error_message(expr.span, |actual| {
3085                                         format!("type `{}` cannot be \
3086                                                 dereferenced", actual)
3087                                     }, oprnd_t, None);
3088                                 }
3089                                 ty::mk_err()
3090                             }
3091                         }
3092                     };
3093                 }
3094                 ast::UnNot => {
3095                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3096                                                          oprnd_t);
3097                     if !(ty::type_is_integral(oprnd_t) ||
3098                          ty::get(oprnd_t).sty == ty::ty_bool) {
3099                         oprnd_t = check_user_unop(fcx, "!", "not",
3100                                                   tcx.lang_items.not_trait(),
3101                                                   expr, oprnd.clone(), oprnd_t);
3102                     }
3103                 }
3104                 ast::UnNeg => {
3105                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3106                                                          oprnd_t);
3107                     if !(ty::type_is_integral(oprnd_t) ||
3108                          ty::type_is_fp(oprnd_t)) {
3109                         oprnd_t = check_user_unop(fcx, "-", "neg",
3110                                                   tcx.lang_items.neg_trait(),
3111                                                   expr, oprnd.clone(), oprnd_t);
3112                     }
3113                 }
3114             }
3115         }
3116         fcx.write_ty(id, oprnd_t);
3117       }
3118       ast::ExprAddrOf(mutbl, ref oprnd) => {
3119         let expected = expected.only_has_type();
3120         let hint = expected.map(fcx, |sty| {
3121             match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3122                          _ => NoExpectation }
3123         });
3124         let lvalue_pref = match mutbl {
3125             ast::MutMutable => PreferMutLvalue,
3126             ast::MutImmutable => NoPreference
3127         };
3128         check_expr_with_expectation_and_lvalue_pref(fcx,
3129                                                     &**oprnd,
3130                                                     hint,
3131                                                     lvalue_pref);
3132
3133         // Note: at this point, we cannot say what the best lifetime
3134         // is to use for resulting pointer.  We want to use the
3135         // shortest lifetime possible so as to avoid spurious borrowck
3136         // errors.  Moreover, the longest lifetime will depend on the
3137         // precise details of the value whose address is being taken
3138         // (and how long it is valid), which we don't know yet until type
3139         // inference is complete.
3140         //
3141         // Therefore, here we simply generate a region variable.  The
3142         // region inferencer will then select the ultimate value.
3143         // Finally, borrowck is charged with guaranteeing that the
3144         // value whose address was taken can actually be made to live
3145         // as long as it needs to live.
3146         let region = fcx.infcx().next_region_var(
3147             infer::AddrOfRegion(expr.span));
3148
3149         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3150         let oprnd_t = if ty::type_is_error(tm.ty) {
3151             ty::mk_err()
3152         } else if ty::type_is_bot(tm.ty) {
3153             ty::mk_bot()
3154         }
3155         else {
3156             ty::mk_rptr(tcx, region, tm)
3157         };
3158         fcx.write_ty(id, oprnd_t);
3159       }
3160       ast::ExprPath(ref pth) => {
3161         let defn = lookup_def(fcx, pth.span, id);
3162         let pty = polytype_for_def(fcx, expr.span, defn);
3163         instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3164       }
3165       ast::ExprInlineAsm(ref ia) => {
3166           for &(_, ref input) in ia.inputs.iter() {
3167               check_expr(fcx, &**input);
3168           }
3169           for &(_, ref out) in ia.outputs.iter() {
3170               check_expr(fcx, &**out);
3171           }
3172           fcx.write_nil(id);
3173       }
3174       ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3175       ast::ExprBreak(_) => { fcx.write_bot(id); }
3176       ast::ExprAgain(_) => { fcx.write_bot(id); }
3177       ast::ExprRet(ref expr_opt) => {
3178         let ret_ty = fcx.ret_ty;
3179         match *expr_opt {
3180           None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3181                                     ret_ty, ty::mk_nil()) {
3182             Ok(_) => { /* fall through */ }
3183             Err(_) => {
3184                 tcx.sess.span_err(
3185                     expr.span,
3186                     "`return;` in function returning non-nil");
3187             }
3188           },
3189           Some(ref e) => {
3190               check_expr_has_type(fcx, &**e, ret_ty);
3191           }
3192         }
3193         fcx.write_bot(id);
3194       }
3195       ast::ExprParen(a) => {
3196         check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3197         fcx.write_ty(id, fcx.expr_ty(a));
3198       }
3199       ast::ExprAssign(ref lhs, ref rhs) => {
3200         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3201
3202         let tcx = fcx.tcx();
3203         if !ty::expr_is_lval(tcx, &**lhs) {
3204             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3205         }
3206
3207         let lhs_ty = fcx.expr_ty(&**lhs);
3208         check_expr_has_type(fcx, &**rhs, lhs_ty);
3209         let rhs_ty = fcx.expr_ty(&**rhs);
3210
3211         if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3212             fcx.write_error(id);
3213         } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3214             fcx.write_bot(id);
3215         } else {
3216             fcx.write_nil(id);
3217         }
3218       }
3219       ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3220         check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3221                         id, expr.span, expected);
3222       }
3223       ast::ExprWhile(ref cond, ref body) => {
3224         check_expr_has_type(fcx, &**cond, ty::mk_bool());
3225         check_block_no_value(fcx, &**body);
3226         let cond_ty = fcx.expr_ty(&**cond);
3227         let body_ty = fcx.node_ty(body.id);
3228         if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3229             fcx.write_error(id);
3230         }
3231         else if ty::type_is_bot(cond_ty) {
3232             fcx.write_bot(id);
3233         }
3234         else {
3235             fcx.write_nil(id);
3236         }
3237       }
3238       ast::ExprForLoop(..) =>
3239           fail!("non-desugared expr_for_loop"),
3240       ast::ExprLoop(ref body, _) => {
3241         check_block_no_value(fcx, &**body);
3242         if !may_break(tcx, expr.id, body.clone()) {
3243             fcx.write_bot(id);
3244         }
3245         else {
3246             fcx.write_nil(id);
3247         }
3248       }
3249       ast::ExprMatch(ref discrim, ref arms) => {
3250         _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3251       }
3252       ast::ExprFnBlock(ref decl, ref body) => {
3253         let region = astconv::opt_ast_region_to_region(fcx,
3254                                                        fcx.infcx(),
3255                                                        expr.span,
3256                                                        &None);
3257         check_expr_fn(fcx,
3258                       expr,
3259                       ty::RegionTraitStore(region, ast::MutMutable),
3260                       &**decl,
3261                       body.clone(),
3262                       expected);
3263       }
3264       ast::ExprProc(ref decl, ref body) => {
3265         check_expr_fn(fcx,
3266                       expr,
3267                       ty::UniqTraitStore,
3268                       &**decl,
3269                       body.clone(),
3270                       expected);
3271       }
3272       ast::ExprBlock(ref b) => {
3273         check_block_with_expected(fcx, &**b, expected);
3274         fcx.write_ty(id, fcx.node_ty(b.id));
3275       }
3276       ast::ExprCall(ref f, ref args) => {
3277           // Index expressions need to be handled separately, to inform them
3278           // that they appear in call position.
3279           check_expr(fcx, &**f);
3280           let f_ty = fcx.expr_ty(&**f);
3281
3282           if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3283               check_call(fcx, expr, &**f, args.as_slice());
3284               let (args_bot, args_err) = args.iter().fold((false, false),
3285                  |(rest_bot, rest_err), a| {
3286                      // is this not working?
3287                      let a_ty = fcx.expr_ty(&**a);
3288                      (rest_bot || ty::type_is_bot(a_ty),
3289                       rest_err || ty::type_is_error(a_ty))});
3290               if ty::type_is_error(f_ty) || args_err {
3291                   fcx.write_error(id);
3292               }
3293               else if ty::type_is_bot(f_ty) || args_bot {
3294                   fcx.write_bot(id);
3295               }
3296           }
3297       }
3298       ast::ExprMethodCall(ident, ref tps, ref args) => {
3299         check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3300         let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3301         let (args_bot, args_err) = arg_tys.fold((false, false),
3302              |(rest_bot, rest_err), a| {
3303               (rest_bot || ty::type_is_bot(a),
3304                rest_err || ty::type_is_error(a))});
3305         if args_err {
3306             fcx.write_error(id);
3307         } else if args_bot {
3308             fcx.write_bot(id);
3309         }
3310       }
3311       ast::ExprCast(ref e, ref t) => {
3312         check_cast(fcx, &**e, &**t, id, expr.span);
3313       }
3314       ast::ExprVec(ref args) => {
3315         let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3316         for e in args.iter() {
3317             check(fcx, &**e, t);
3318         }
3319         let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3320                              Some(args.len()));
3321         fcx.write_ty(id, typ);
3322       }
3323       ast::ExprRepeat(ref element, ref count_expr) => {
3324         check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3325         let count = ty::eval_repeat_count(fcx, &**count_expr);
3326         let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3327         check(fcx, &**element, t);
3328         let element_ty = fcx.expr_ty(&**element);
3329         if ty::type_is_error(element_ty) {
3330             fcx.write_error(id);
3331         }
3332         else if ty::type_is_bot(element_ty) {
3333             fcx.write_bot(id);
3334         }
3335         else {
3336             let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3337                                Some(count));
3338             fcx.write_ty(id, t);
3339         }
3340       }
3341       ast::ExprTup(ref elts) => {
3342         let expected = expected.only_has_type();
3343         let flds = expected.map_to_option(fcx, |sty| {
3344             match *sty {
3345                 ty::ty_tup(ref flds) => Some((*flds).clone()),
3346                 _ => None
3347             }
3348         });
3349         let mut bot_field = false;
3350         let mut err_field = false;
3351
3352         let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3353             let opt_hint = match flds {
3354                 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3355                 _ => NoExpectation
3356             };
3357             check_expr_with_expectation(fcx, *e, opt_hint);
3358             let t = fcx.expr_ty(*e);
3359             err_field = err_field || ty::type_is_error(t);
3360             bot_field = bot_field || ty::type_is_bot(t);
3361             t
3362         }).collect();
3363         if bot_field {
3364             fcx.write_bot(id);
3365         } else if err_field {
3366             fcx.write_error(id);
3367         } else {
3368             let typ = ty::mk_tup(tcx, elt_ts);
3369             fcx.write_ty(id, typ);
3370         }
3371       }
3372       ast::ExprStruct(ref path, ref fields, base_expr) => {
3373         // Resolve the path.
3374         let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3375         match def {
3376             Some(def::DefVariant(enum_id, variant_id, _)) => {
3377                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3378                                           variant_id, fields.as_slice());
3379             }
3380             Some(def) => {
3381                 // Verify that this was actually a struct.
3382                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3383                 match ty::get(typ.ty).sty {
3384                     ty::ty_struct(struct_did, _) => {
3385                         check_struct_constructor(fcx,
3386                                                  id,
3387                                                  expr.span,
3388                                                  struct_did,
3389                                                  fields.as_slice(),
3390                                                  base_expr);
3391                     }
3392                     _ => {
3393                         tcx.sess
3394                            .span_err(path.span,
3395                                      format!("`{}` does not name a structure",
3396                                              pprust::path_to_string(
3397                                                  path)).as_slice())
3398                     }
3399                 }
3400             }
3401             _ => {
3402                 tcx.sess.span_bug(path.span,
3403                                   "structure constructor wasn't resolved")
3404             }
3405         }
3406       }
3407       ast::ExprField(ref base, ref field, ref tys) => {
3408         check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3409       }
3410       ast::ExprIndex(ref base, ref idx) => {
3411           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3412           check_expr(fcx, &**idx);
3413           let raw_base_t = fcx.expr_ty(&**base);
3414           let idx_t = fcx.expr_ty(&**idx);
3415           if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3416               fcx.write_ty(id, raw_base_t);
3417           } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3418               fcx.write_ty(id, idx_t);
3419           } else {
3420               let (_, autoderefs, field_ty) =
3421                 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3422                           lvalue_pref, |base_t, _| ty::index(base_t));
3423               match field_ty {
3424                   Some(mt) => {
3425                       check_expr_has_type(fcx, &**idx, ty::mk_uint());
3426                       fcx.write_ty(id, mt.ty);
3427                       fcx.write_autoderef_adjustment(base.id, autoderefs);
3428                   }
3429                   None => {
3430                       // This is an overloaded method.
3431                       let base_t = structurally_resolved_type(fcx,
3432                                                               expr.span,
3433                                                               raw_base_t);
3434                       let method_call = MethodCall::expr(expr.id);
3435                       match try_overloaded_index(fcx,
3436                                                  Some(method_call),
3437                                                  expr,
3438                                                  *base,
3439                                                  base_t,
3440                                                  *idx,
3441                                                  lvalue_pref) {
3442                           Some(mt) => fcx.write_ty(id, mt.ty),
3443                           None => {
3444                                 fcx.type_error_message(expr.span,
3445                                                        |actual| {
3446                                                         format!("cannot \
3447                                                                  index a \
3448                                                                  value of \
3449                                                                  type `{}`",
3450                                                                 actual)
3451                                                        },
3452                                                        base_t,
3453                                                        None);
3454                                 fcx.write_ty(id, ty::mk_err())
3455                           }
3456                       }
3457                   }
3458               }
3459           }
3460        }
3461     }
3462
3463     debug!("type of expr({}) {} is...", expr.id,
3464            syntax::print::pprust::expr_to_string(expr));
3465     debug!("... {}, expected is {}",
3466            ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3467            expected.repr(tcx));
3468
3469     unifier();
3470 }
3471
3472 impl Expectation {
3473     fn only_has_type(self) -> Expectation {
3474         match self {
3475             NoExpectation | ExpectCastableToType(..) => NoExpectation,
3476             ExpectHasType(t) => ExpectHasType(t)
3477         }
3478     }
3479
3480     // Resolves `expected` by a single level if it is a variable. If
3481     // there is no expected type or resolution is not possible (e.g.,
3482     // no constraints yet present), just returns `None`.
3483     fn resolve(self, fcx: &FnCtxt) -> Expectation {
3484         match self {
3485             NoExpectation => {
3486                 NoExpectation
3487             }
3488             ExpectCastableToType(t) => {
3489                 ExpectCastableToType(
3490                     fcx.infcx().resolve_type_vars_if_possible(t))
3491             }
3492             ExpectHasType(t) => {
3493                 ExpectHasType(
3494                     fcx.infcx().resolve_type_vars_if_possible(t))
3495             }
3496         }
3497     }
3498
3499     fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3500         match self.resolve(fcx) {
3501             NoExpectation => NoExpectation,
3502             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3503         }
3504     }
3505
3506     fn map_to_option<O>(self,
3507                         fcx: &FnCtxt,
3508                         unpack: |&ty::sty| -> Option<O>)
3509                         -> Option<O>
3510     {
3511         match self.resolve(fcx) {
3512             NoExpectation => None,
3513             ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3514         }
3515     }
3516 }
3517
3518 impl Repr for Expectation {
3519     fn repr(&self, tcx: &ty::ctxt) -> String {
3520         match *self {
3521             NoExpectation => format!("NoExpectation"),
3522             ExpectHasType(t) => format!("ExpectHasType({})",
3523                                         t.repr(tcx)),
3524             ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3525                                                t.repr(tcx)),
3526         }
3527     }
3528 }
3529
3530 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3531     if !type_is_uint(fcx, sp, t) {
3532         fcx.type_error_message(sp, |actual| {
3533             format!("mismatched types: expected `uint` type but found `{}`",
3534                     actual)
3535         }, t, None);
3536     }
3537 }
3538
3539 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3540     if !type_is_integral(fcx, sp, t) {
3541         fcx.type_error_message(sp, |actual| {
3542             format!("mismatched types: expected integral type but found `{}`",
3543                     actual)
3544         }, t, None);
3545     }
3546 }
3547
3548 pub fn check_decl_initializer(fcx: &FnCtxt,
3549                               nid: ast::NodeId,
3550                               init: &ast::Expr)
3551                             {
3552     let local_ty = fcx.local_ty(init.span, nid);
3553     check_expr_coercable_to_type(fcx, init, local_ty)
3554 }
3555
3556 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
3557     let tcx = fcx.ccx.tcx;
3558
3559     let t = fcx.local_ty(local.span, local.id);
3560     fcx.write_ty(local.id, t);
3561
3562     match local.init {
3563         Some(ref init) => {
3564             check_decl_initializer(fcx, local.id, &**init);
3565             let init_ty = fcx.expr_ty(&**init);
3566             if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3567                 fcx.write_ty(local.id, init_ty);
3568             }
3569         }
3570         _ => {}
3571     }
3572
3573     let pcx = pat_ctxt {
3574         fcx: fcx,
3575         map: pat_id_map(&tcx.def_map, &*local.pat),
3576     };
3577     _match::check_pat(&pcx, &*local.pat, t);
3578     let pat_ty = fcx.node_ty(local.pat.id);
3579     if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3580         fcx.write_ty(local.id, pat_ty);
3581     }
3582 }
3583
3584 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
3585     let node_id;
3586     let mut saw_bot = false;
3587     let mut saw_err = false;
3588     match stmt.node {
3589       ast::StmtDecl(decl, id) => {
3590         node_id = id;
3591         match decl.node {
3592           ast::DeclLocal(ref l) => {
3593               check_decl_local(fcx, &**l);
3594               let l_t = fcx.node_ty(l.id);
3595               saw_bot = saw_bot || ty::type_is_bot(l_t);
3596               saw_err = saw_err || ty::type_is_error(l_t);
3597           }
3598           ast::DeclItem(_) => {/* ignore for now */ }
3599         }
3600       }
3601       ast::StmtExpr(ref expr, id) => {
3602         node_id = id;
3603         // Check with expected type of ()
3604         check_expr_has_type(fcx, &**expr, ty::mk_nil());
3605         let expr_ty = fcx.expr_ty(&**expr);
3606         saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3607         saw_err = saw_err || ty::type_is_error(expr_ty);
3608       }
3609       ast::StmtSemi(ref expr, id) => {
3610         node_id = id;
3611         check_expr(fcx, &**expr);
3612         let expr_ty = fcx.expr_ty(&**expr);
3613         saw_bot |= ty::type_is_bot(expr_ty);
3614         saw_err |= ty::type_is_error(expr_ty);
3615       }
3616       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3617     }
3618     if saw_bot {
3619         fcx.write_bot(node_id);
3620     }
3621     else if saw_err {
3622         fcx.write_error(node_id);
3623     }
3624     else {
3625         fcx.write_nil(node_id)
3626     }
3627 }
3628
3629 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
3630     check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3631     let blkty = fcx.node_ty(blk.id);
3632     if ty::type_is_error(blkty) {
3633         fcx.write_error(blk.id);
3634     }
3635     else if ty::type_is_bot(blkty) {
3636         fcx.write_bot(blk.id);
3637     }
3638     else {
3639         let nilty = ty::mk_nil();
3640         demand::suptype(fcx, blk.span, nilty, blkty);
3641     }
3642 }
3643
3644 fn check_block_with_expected(fcx: &FnCtxt,
3645                              blk: &ast::Block,
3646                              expected: Expectation) {
3647     let prev = {
3648         let mut fcx_ps = fcx.ps.borrow_mut();
3649         let fn_style_state = fcx_ps.recurse(blk);
3650         replace(&mut *fcx_ps, fn_style_state)
3651     };
3652
3653     fcx.with_region_lb(blk.id, || {
3654         let mut warned = false;
3655         let mut last_was_bot = false;
3656         let mut any_bot = false;
3657         let mut any_err = false;
3658         for s in blk.stmts.iter() {
3659             check_stmt(fcx, &**s);
3660             let s_id = ast_util::stmt_id(&**s);
3661             let s_ty = fcx.node_ty(s_id);
3662             if last_was_bot && !warned && match s.node {
3663                   ast::StmtDecl(decl, _) => {
3664                       match decl.node {
3665                           ast::DeclLocal(_) => true,
3666                           _ => false,
3667                       }
3668                   }
3669                   ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3670                   _ => false
3671                 } {
3672                 fcx.ccx
3673                    .tcx
3674                    .sess
3675                    .add_lint(lint::builtin::UNREACHABLE_CODE,
3676                              s_id,
3677                              s.span,
3678                              "unreachable statement".to_string());
3679                 warned = true;
3680             }
3681             if ty::type_is_bot(s_ty) {
3682                 last_was_bot = true;
3683             }
3684             any_bot = any_bot || ty::type_is_bot(s_ty);
3685             any_err = any_err || ty::type_is_error(s_ty);
3686         }
3687         match blk.expr {
3688             None => if any_err {
3689                 fcx.write_error(blk.id);
3690             }
3691             else if any_bot {
3692                 fcx.write_bot(blk.id);
3693             }
3694             else  {
3695                 fcx.write_nil(blk.id);
3696             },
3697           Some(e) => {
3698             if any_bot && !warned {
3699                 fcx.ccx
3700                    .tcx
3701                    .sess
3702                    .add_lint(lint::builtin::UNREACHABLE_CODE,
3703                              e.id,
3704                              e.span,
3705                              "unreachable expression".to_string());
3706             }
3707             check_expr_with_expectation(fcx, e, expected);
3708               let ety = fcx.expr_ty(e);
3709               fcx.write_ty(blk.id, ety);
3710               if any_err {
3711                   fcx.write_error(blk.id);
3712               }
3713               else if any_bot {
3714                   fcx.write_bot(blk.id);
3715               }
3716           }
3717         };
3718     });
3719
3720     *fcx.ps.borrow_mut() = prev;
3721 }
3722
3723 pub fn check_const(ccx: &CrateCtxt,
3724                    sp: Span,
3725                    e: &ast::Expr,
3726                    id: ast::NodeId) {
3727     let inh = blank_inherited_fields(ccx);
3728     let rty = ty::node_id_to_type(ccx.tcx, id);
3729     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3730     let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3731     check_const_with_ty(&fcx, sp, e, declty);
3732 }
3733
3734 pub fn check_const_with_ty(fcx: &FnCtxt,
3735                            _: Span,
3736                            e: &ast::Expr,
3737                            declty: ty::t) {
3738     // Gather locals in statics (because of block expressions).
3739     // This is technically unnecessary because locals in static items are forbidden,
3740     // but prevents type checking from blowing up before const checking can properly
3741     // emit a error.
3742     GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3743
3744     check_expr(fcx, e);
3745     let cty = fcx.expr_ty(e);
3746     demand::suptype(fcx, e.span, declty, cty);
3747     regionck::regionck_expr(fcx, e);
3748     writeback::resolve_type_vars_in_expr(fcx, e);
3749 }
3750
3751 /// Checks whether a type can be represented in memory. In particular, it
3752 /// identifies types that contain themselves without indirection through a
3753 /// pointer, which would mean their size is unbounded. This is different from
3754 /// the question of whether a type can be instantiated. See the definition of
3755 /// `check_instantiable`.
3756 pub fn check_representable(tcx: &ty::ctxt,
3757                            sp: Span,
3758                            item_id: ast::NodeId,
3759                            designation: &str) -> bool {
3760     let rty = ty::node_id_to_type(tcx, item_id);
3761
3762     // Check that it is possible to represent this type. This call identifies
3763     // (1) types that contain themselves and (2) types that contain a different
3764     // recursive type. It is only necessary to throw an error on those that
3765     // contain themselves. For case 2, there must be an inner type that will be
3766     // caught by case 1.
3767     match ty::is_type_representable(tcx, sp, rty) {
3768       ty::SelfRecursive => {
3769         tcx.sess.span_err(
3770           sp, format!("illegal recursive {} type; \
3771                        wrap the inner value in a box to make it representable",
3772                       designation).as_slice());
3773         return false
3774       }
3775       ty::Representable | ty::ContainsRecursive => (),
3776     }
3777     return true
3778 }
3779
3780 /// Checks whether a type can be created without an instance of itself.
3781 /// This is similar but different from the question of whether a type
3782 /// can be represented.  For example, the following type:
3783 ///
3784 ///     enum foo { None, Some(foo) }
3785 ///
3786 /// is instantiable but is not representable.  Similarly, the type
3787 ///
3788 ///     enum foo { Some(@foo) }
3789 ///
3790 /// is representable, but not instantiable.
3791 pub fn check_instantiable(tcx: &ty::ctxt,
3792                           sp: Span,
3793                           item_id: ast::NodeId)
3794                           -> bool {
3795     let item_ty = ty::node_id_to_type(tcx, item_id);
3796     if !ty::is_instantiable(tcx, item_ty) {
3797         tcx.sess
3798            .span_err(sp,
3799                      format!("this type cannot be instantiated without an \
3800                               instance of itself; consider using \
3801                               `Option<{}>`",
3802                              ppaux::ty_to_string(tcx, item_ty)).as_slice());
3803         false
3804     } else {
3805         true
3806     }
3807 }
3808
3809 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3810     let t = ty::node_id_to_type(tcx, id);
3811     if ty::type_needs_subst(t) {
3812         tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3813         return;
3814     }
3815     match ty::get(t).sty {
3816         ty::ty_struct(did, ref substs) => {
3817             let fields = ty::lookup_struct_fields(tcx, did);
3818             if fields.is_empty() {
3819                 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3820                 return;
3821             }
3822             let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3823             if !fields.iter().all(
3824                          |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3825                 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3826                 return;
3827             }
3828             if !ty::type_is_machine(e) {
3829                 tcx.sess.span_err(sp, "SIMD vector element type should be \
3830                                        machine type");
3831                 return;
3832             }
3833         }
3834         _ => ()
3835     }
3836 }
3837
3838 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3839                                  vs: &[ast::P<ast::Variant>]) {
3840     for &v in vs.iter() {
3841         match v.node.kind {
3842             ast::TupleVariantKind(ref args) if args.len() > 0 => {
3843                 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3844                 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3845                 let len = arg_tys.len();
3846                 if len == 0 {
3847                     return;
3848                 }
3849                 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3850                     // Allow the last field in an enum to be unsized.
3851                     // We want to do this so that we can support smart pointers.
3852                     // A struct value with an unsized final field is itself
3853                     // unsized and we must track this in the type system.
3854                     if !ty::type_is_sized(ccx.tcx, *t) {
3855                         ccx.tcx
3856                            .sess
3857                            .span_err(
3858                                args.get(i).ty.span,
3859                                format!("type `{}` is dynamically sized. \
3860                                         dynamically sized types may only \
3861                                         appear as the final type in a \
3862                                         variant",
3863                                        ppaux::ty_to_string(ccx.tcx,
3864                                                         *t)).as_slice());
3865                     }
3866                 }
3867             },
3868             ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3869             _ => {}
3870         }
3871     }
3872 }
3873
3874 pub fn check_enum_variants(ccx: &CrateCtxt,
3875                            sp: Span,
3876                            vs: &[ast::P<ast::Variant>],
3877                            id: ast::NodeId) {
3878
3879     fn disr_in_range(ccx: &CrateCtxt,
3880                      ty: attr::IntType,
3881                      disr: ty::Disr) -> bool {
3882         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3883             match ty {
3884                 ast::TyU8 => disr as u8 as Disr == disr,
3885                 ast::TyU16 => disr as u16 as Disr == disr,
3886                 ast::TyU32 => disr as u32 as Disr == disr,
3887                 ast::TyU64 => disr as u64 as Disr == disr,
3888                 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3889             }
3890         }
3891         fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3892             match ty {
3893                 ast::TyI8 => disr as i8 as Disr == disr,
3894                 ast::TyI16 => disr as i16 as Disr == disr,
3895                 ast::TyI32 => disr as i32 as Disr == disr,
3896                 ast::TyI64 => disr as i64 as Disr == disr,
3897                 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3898             }
3899         }
3900         match ty {
3901             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3902             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3903         }
3904     }
3905
3906     fn do_check(ccx: &CrateCtxt,
3907                 vs: &[ast::P<ast::Variant>],
3908                 id: ast::NodeId,
3909                 hint: attr::ReprAttr)
3910                 -> Vec<Rc<ty::VariantInfo>> {
3911
3912         let rty = ty::node_id_to_type(ccx.tcx, id);
3913         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3914         let mut disr_vals: Vec<ty::Disr> = Vec::new();
3915         let mut prev_disr_val: Option<ty::Disr> = None;
3916
3917         for &v in vs.iter() {
3918
3919             // If the discriminant value is specified explicitly in the enum check whether the
3920             // initialization expression is valid, otherwise use the last value plus one.
3921             let mut current_disr_val = match prev_disr_val {
3922                 Some(prev_disr_val) => prev_disr_val + 1,
3923                 None => ty::INITIAL_DISCRIMINANT_VALUE
3924             };
3925
3926             match v.node.disr_expr {
3927                 Some(e) => {
3928                     debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
3929
3930                     let inh = blank_inherited_fields(ccx);
3931                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3932                     let declty = match hint {
3933                         attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3934                         attr::ReprInt(_, attr::SignedInt(ity)) => {
3935                             ty::mk_mach_int(ity)
3936                         }
3937                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3938                             ty::mk_mach_uint(ity)
3939                         }
3940                     };
3941                     check_const_with_ty(&fcx, e.span, &*e, declty);
3942                     // check_expr (from check_const pass) doesn't guarantee
3943                     // that the expression is in a form that eval_const_expr can
3944                     // handle, so we may still get an internal compiler error
3945
3946                     match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3947                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3948                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3949                         Ok(_) => {
3950                             ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3951                         }
3952                         Err(ref err) => {
3953                             ccx.tcx
3954                                .sess
3955                                .span_err(e.span,
3956                                          format!("expected constant: {}",
3957                                                  *err).as_slice());
3958                         }
3959                     }
3960                 },
3961                 None => ()
3962             };
3963
3964             // Check for duplicate discriminant values
3965             if disr_vals.contains(&current_disr_val) {
3966                 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3967             }
3968             // Check for unrepresentable discriminant values
3969             match hint {
3970                 attr::ReprAny | attr::ReprExtern => (),
3971                 attr::ReprInt(sp, ity) => {
3972                     if !disr_in_range(ccx, ity, current_disr_val) {
3973                         ccx.tcx.sess.span_err(v.span,
3974                                               "discriminant value outside specified type");
3975                         ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3976                     }
3977                 }
3978             }
3979             disr_vals.push(current_disr_val);
3980
3981             let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3982                                                                      current_disr_val));
3983             prev_disr_val = Some(current_disr_val);
3984
3985             variants.push(variant_info);
3986         }
3987
3988         return variants;
3989     }
3990
3991     let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3992     if hint != attr::ReprAny && vs.len() <= 1 {
3993         let msg = if vs.len() == 1 {
3994             "unsupported representation for univariant enum"
3995         } else {
3996             "unsupported representation for zero-variant enum"
3997         };
3998         ccx.tcx.sess.span_err(sp, msg)
3999     }
4000
4001     let variants = do_check(ccx, vs, id, hint);
4002
4003     // cache so that ty::enum_variants won't repeat this work
4004     ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4005
4006     check_representable(ccx.tcx, sp, id, "enum");
4007
4008     // Check that it is possible to instantiate this enum:
4009     //
4010     // This *sounds* like the same that as representable, but it's
4011     // not.  See def'n of `check_instantiable()` for details.
4012     check_instantiable(ccx.tcx, sp, id);
4013 }
4014
4015 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4016     lookup_def_ccx(fcx.ccx, sp, id)
4017 }
4018
4019 // Returns the type parameter count and the type for the given definition.
4020 pub fn polytype_for_def(fcx: &FnCtxt,
4021                         sp: Span,
4022                         defn: def::Def)
4023                         -> Polytype {
4024     match defn {
4025       def::DefArg(nid, _) | def::DefLocal(nid, _) |
4026       def::DefBinding(nid, _) => {
4027           let typ = fcx.local_ty(sp, nid);
4028           return no_params(typ);
4029       }
4030       def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4031       def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4032       def::DefStruct(id) => {
4033         return ty::lookup_item_type(fcx.ccx.tcx, id);
4034       }
4035       def::DefUpvar(_, inner, _, _) => {
4036         return polytype_for_def(fcx, sp, *inner);
4037       }
4038       def::DefTrait(_) |
4039       def::DefTy(_) |
4040       def::DefPrimTy(_) |
4041       def::DefTyParam(..)=> {
4042         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4043       }
4044       def::DefMod(..) | def::DefForeignMod(..) => {
4045         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4046       }
4047       def::DefUse(..) => {
4048         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4049       }
4050       def::DefRegion(..) => {
4051         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4052       }
4053       def::DefTyParamBinder(..) => {
4054         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4055       }
4056       def::DefLabel(..) => {
4057         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4058       }
4059       def::DefSelfTy(..) => {
4060         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4061       }
4062       def::DefMethod(..) => {
4063         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4064       }
4065     }
4066 }
4067
4068 // Instantiates the given path, which must refer to an item with the given
4069 // number of type parameters and type.
4070 pub fn instantiate_path(fcx: &FnCtxt,
4071                         path: &ast::Path,
4072                         polytype: Polytype,
4073                         def: def::Def,
4074                         span: Span,
4075                         node_id: ast::NodeId) {
4076     debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4077            path.repr(fcx.tcx()),
4078            def.repr(fcx.tcx()),
4079            node_id,
4080            polytype.repr(fcx.tcx()));
4081
4082     // We need to extract the type parameters supplied by the user in
4083     // the path `path`. Due to the current setup, this is a bit of a
4084     // tricky-process; the problem is that resolve only tells us the
4085     // end-point of the path resolution, and not the intermediate steps.
4086     // Luckily, we can (at least for now) deduce the intermediate steps
4087     // just from the end-point.
4088     //
4089     // There are basically three cases to consider:
4090     //
4091     // 1. Reference to a *type*, such as a struct or enum:
4092     //
4093     //        mod a { struct Foo<T> { ... } }
4094     //
4095     //    Because we don't allow types to be declared within one
4096     //    another, a path that leads to a type will always look like
4097     //    `a::b::Foo<T>` where `a` and `b` are modules. This implies
4098     //    that only the final segment can have type parameters, and
4099     //    they are located in the TypeSpace.
4100     //
4101     //    *Note:* Generally speaking, references to types don't
4102     //    actually pass through this function, but rather the
4103     //    `ast_ty_to_ty` function in `astconv`. However, in the case
4104     //    of struct patterns (and maybe literals) we do invoke
4105     //    `instantiate_path` to get the general type of an instance of
4106     //    a struct. (In these cases, there are actually no type
4107     //    parameters permitted at present, but perhaps we will allow
4108     //    them in the future.)
4109     //
4110     // 1b. Reference to a enum variant or tuple-like struct:
4111     //
4112     //        struct foo<T>(...)
4113     //        enum E<T> { foo(...) }
4114     //
4115     //    In these cases, the parameters are declared in the type
4116     //    space.
4117     //
4118     // 2. Reference to a *fn item*:
4119     //
4120     //        fn foo<T>() { }
4121     //
4122     //    In this case, the path will again always have the form
4123     //    `a::b::foo::<T>` where only the final segment should have
4124     //    type parameters. However, in this case, those parameters are
4125     //    declared on a value, and hence are in the `FnSpace`.
4126     //
4127     // 3. Reference to a *method*:
4128     //
4129     //        impl<A> SomeStruct<A> {
4130     //            fn foo<B>(...)
4131     //        }
4132     //
4133     //    Here we can have a path like
4134     //    `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4135     //    may appear in two places. The penultimate segment,
4136     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4137     //    final segment, `foo::<B>` contains parameters in fn space.
4138     //
4139     // The first step then is to categorize the segments appropriately.
4140
4141     assert!(path.segments.len() >= 1);
4142     let mut segment_spaces;
4143     match def {
4144         // Case 1 and 1b. Reference to a *type* or *enum variant*.
4145         def::DefSelfTy(..) |
4146         def::DefStruct(..) |
4147         def::DefVariant(..) |
4148         def::DefTyParamBinder(..) |
4149         def::DefTy(..) |
4150         def::DefTrait(..) |
4151         def::DefPrimTy(..) |
4152         def::DefTyParam(..) => {
4153             // Everything but the final segment should have no
4154             // parameters at all.
4155             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4156             segment_spaces.push(Some(subst::TypeSpace));
4157         }
4158
4159         // Case 2. Reference to a top-level value.
4160         def::DefFn(..) |
4161         def::DefStatic(..) => {
4162             segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4163             segment_spaces.push(Some(subst::FnSpace));
4164         }
4165
4166         // Case 3. Reference to a method.
4167         def::DefStaticMethod(..) => {
4168             assert!(path.segments.len() >= 2);
4169             segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4170             segment_spaces.push(Some(subst::TypeSpace));
4171             segment_spaces.push(Some(subst::FnSpace));
4172         }
4173
4174         // Other cases. Various nonsense that really shouldn't show up
4175         // here. If they do, an error will have been reported
4176         // elsewhere. (I hope)
4177         def::DefMod(..) |
4178         def::DefForeignMod(..) |
4179         def::DefArg(..) |
4180         def::DefLocal(..) |
4181         def::DefMethod(..) |
4182         def::DefBinding(..) |
4183         def::DefUse(..) |
4184         def::DefRegion(..) |
4185         def::DefLabel(..) |
4186         def::DefUpvar(..) => {
4187             segment_spaces = Vec::from_elem(path.segments.len(), None);
4188         }
4189     }
4190     assert_eq!(segment_spaces.len(), path.segments.len());
4191
4192     debug!("segment_spaces={}", segment_spaces);
4193
4194     // Next, examine the definition, and determine how many type
4195     // parameters we expect from each space.
4196     let type_defs = &polytype.generics.types;
4197     let region_defs = &polytype.generics.regions;
4198
4199     // Now that we have categorized what space the parameters for each
4200     // segment belong to, let's sort out the parameters that the user
4201     // provided (if any) into their appropriate spaces. We'll also report
4202     // errors if type parameters are provided in an inappropriate place.
4203     let mut substs = Substs::empty();
4204     for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4205         match *opt_space {
4206             None => {
4207                 report_error_if_segment_contains_type_parameters(fcx, segment);
4208             }
4209
4210             Some(space) => {
4211                 push_explicit_parameters_from_segment_to_substs(fcx,
4212                                                                 space,
4213                                                                 type_defs,
4214                                                                 region_defs,
4215                                                                 segment,
4216                                                                 &mut substs);
4217             }
4218         }
4219     }
4220
4221     // Now we have to compare the types that the user *actually*
4222     // provided against the types that were *expected*. If the user
4223     // did not provide any types, then we want to substitute inference
4224     // variables. If the user provided some types, we may still need
4225     // to add defaults. If the user provided *too many* types, that's
4226     // a problem.
4227     for &space in ParamSpace::all().iter() {
4228         adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4229         assert_eq!(substs.types.len(space), type_defs.len(space));
4230
4231         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4232         assert_eq!(substs.regions().len(space), region_defs.len(space));
4233     }
4234
4235     fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4236         substs: substs,
4237     });
4238
4239     fn report_error_if_segment_contains_type_parameters(
4240         fcx: &FnCtxt,
4241         segment: &ast::PathSegment)
4242     {
4243         for typ in segment.types.iter() {
4244             fcx.tcx().sess.span_err(
4245                 typ.span,
4246                 "type parameters may not appear here");
4247             break;
4248         }
4249
4250         for lifetime in segment.lifetimes.iter() {
4251             fcx.tcx().sess.span_err(
4252                 lifetime.span,
4253                 "lifetime parameters may not appear here");
4254             break;
4255         }
4256     }
4257
4258     fn push_explicit_parameters_from_segment_to_substs(
4259         fcx: &FnCtxt,
4260         space: subst::ParamSpace,
4261         type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4262         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4263         segment: &ast::PathSegment,
4264         substs: &mut Substs)
4265     {
4266         /*!
4267          * Finds the parameters that the user provided and adds them
4268          * to `substs`. If too many parameters are provided, then
4269          * reports an error and clears the output vector.
4270          *
4271          * We clear the output vector because that will cause the
4272          * `adjust_XXX_parameters()` later to use inference
4273          * variables. This seems less likely to lead to derived
4274          * errors.
4275          *
4276          * Note that we *do not* check for *too few* parameters here.
4277          * Due to the presence of defaults etc that is more
4278          * complicated. I wanted however to do the reporting of *too
4279          * many* parameters here because we can easily use the precise
4280          * span of the N+1'th parameter.
4281          */
4282
4283         {
4284             let type_count = type_defs.len(space);
4285             assert_eq!(substs.types.len(space), 0);
4286             for (i, &typ) in segment.types.iter().enumerate() {
4287                 let t = fcx.to_ty(&*typ);
4288                 if i < type_count {
4289                     substs.types.push(space, t);
4290                 } else if i == type_count {
4291                     fcx.tcx().sess.span_err(
4292                         typ.span,
4293                         format!(
4294                             "too many type parameters provided: \
4295                              expected at most {} parameter(s) \
4296                              but found {} parameter(s)",
4297                             type_count,
4298                             segment.types.len()).as_slice());
4299                     substs.types.truncate(space, 0);
4300                 }
4301             }
4302         }
4303
4304         {
4305             let region_count = region_defs.len(space);
4306             assert_eq!(substs.regions().len(space), 0);
4307             for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4308                 let r = ast_region_to_region(fcx.tcx(), lifetime);
4309                 if i < region_count {
4310                     substs.mut_regions().push(space, r);
4311                 } else if i == region_count {
4312                     fcx.tcx().sess.span_err(
4313                         lifetime.span,
4314                         format!(
4315                             "too many lifetime parameters provided: \
4316                              expected {} parameter(s) but found {} parameter(s)",
4317                             region_count,
4318                             segment.lifetimes.len()).as_slice());
4319                     substs.mut_regions().truncate(space, 0);
4320                 }
4321             }
4322         }
4323     }
4324
4325     fn adjust_type_parameters(
4326         fcx: &FnCtxt,
4327         span: Span,
4328         space: ParamSpace,
4329         defs: &VecPerParamSpace<ty::TypeParameterDef>,
4330         substs: &mut Substs)
4331     {
4332         let provided_len = substs.types.len(space);
4333         let desired = defs.get_slice(space);
4334         let required_len = desired.iter()
4335                               .take_while(|d| d.default.is_none())
4336                               .count();
4337
4338         debug!("adjust_type_parameters(space={}, \
4339                provided_len={}, \
4340                desired_len={}, \
4341                required_len={})",
4342                space,
4343                provided_len,
4344                desired.len(),
4345                required_len);
4346
4347         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4348         assert!(provided_len <= desired.len());
4349
4350         // Nothing specified at all: supply inference variables for
4351         // everything.
4352         if provided_len == 0 {
4353             substs.types.replace(space,
4354                                  fcx.infcx().next_ty_vars(desired.len()));
4355             return;
4356         }
4357
4358         // Too few parameters specified: report an error and use Err
4359         // for everything.
4360         if provided_len < required_len {
4361             let qualifier =
4362                 if desired.len() != required_len { "at least " } else { "" };
4363             fcx.tcx().sess.span_err(
4364                 span,
4365                 format!("too few type parameters provided: \
4366                              expected {}{} parameter(s) \
4367                              but found {} parameter(s)",
4368                             qualifier,
4369                             required_len,
4370                             provided_len).as_slice());
4371             substs.types.replace(space,
4372                                  Vec::from_elem(desired.len(), ty::mk_err()));
4373             return;
4374         }
4375
4376         // Otherwise, add in any optional parameters that the user
4377         // omitted. The case of *too many* parameters is handled
4378         // already by
4379         // push_explicit_parameters_from_segment_to_substs(). Note
4380         // that the *default* type are expressed in terms of all prior
4381         // parameters, so we have to substitute as we go with the
4382         // partial substitution that we have built up.
4383         for i in range(provided_len, desired.len()) {
4384             let default = desired[i].default.unwrap();
4385             let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4386             substs.types.push(space, default);
4387         }
4388         assert_eq!(substs.types.len(space), desired.len());
4389
4390         debug!("Final substs: {}", substs.repr(fcx.tcx()));
4391     }
4392
4393     fn adjust_region_parameters(
4394         fcx: &FnCtxt,
4395         span: Span,
4396         space: ParamSpace,
4397         defs: &VecPerParamSpace<ty::RegionParameterDef>,
4398         substs: &mut Substs)
4399     {
4400         let provided_len = substs.mut_regions().len(space);
4401         let desired = defs.get_slice(space);
4402
4403         // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4404         assert!(provided_len <= desired.len());
4405
4406         // If nothing was provided, just use inference variables.
4407         if provided_len == 0 {
4408             substs.mut_regions().replace(
4409                 space,
4410                 fcx.infcx().region_vars_for_defs(span, desired));
4411             return;
4412         }
4413
4414         // If just the right number were provided, everybody is happy.
4415         if provided_len == desired.len() {
4416             return;
4417         }
4418
4419         // Otherwise, too few were provided. Report an error and then
4420         // use inference variables.
4421         fcx.tcx().sess.span_err(
4422             span,
4423             format!(
4424                 "too few lifetime parameters provided: \
4425                          expected {} parameter(s) \
4426                          but found {} parameter(s)",
4427                 desired.len(),
4428                 provided_len).as_slice());
4429
4430         substs.mut_regions().replace(
4431             space,
4432             fcx.infcx().region_vars_for_defs(span, desired));
4433     }
4434 }
4435
4436 // Resolves `typ` by a single level if `typ` is a type variable.  If no
4437 // resolution is possible, then an error is reported.
4438 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4439     match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4440         Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4441         _ => {
4442             fcx.type_error_message(sp, |_actual| {
4443                 "the type of this value must be known in this \
4444                  context".to_string()
4445             }, tp, None);
4446             demand::suptype(fcx, sp, ty::mk_err(), tp);
4447             tp
4448         }
4449     }
4450 }
4451
4452 // Returns the one-level-deep structure of the given type.
4453 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4454                         -> &'a ty::sty {
4455     &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4456 }
4457
4458 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4459     let typ_s = structurally_resolved_type(fcx, sp, typ);
4460     return ty::type_is_integral(typ_s);
4461 }
4462
4463 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4464     let typ_s = structurally_resolved_type(fcx, sp, typ);
4465     return ty::type_is_uint(typ_s);
4466 }
4467
4468 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4469                              e: &ast::Expr,
4470                              v: ast::ExprVstore,
4471                              mk_inner: || -> ty::mt)
4472                              -> ty::t {
4473     match v {
4474         ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4475         ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4476             match e.node {
4477                 ast::ExprLit(..) => {
4478                     // string literals and *empty slices* live in static memory
4479                     ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4480                 }
4481                 ast::ExprVec(ref elements) if elements.len() == 0 => {
4482                     // string literals and *empty slices* live in static memory
4483                     ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4484                 }
4485                 ast::ExprRepeat(..) |
4486                 ast::ExprVec(..) => {
4487                     // vector literals are temporaries on the stack
4488                     match fcx.tcx().region_maps.temporary_scope(e.id) {
4489                         Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4490                         None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4491                     }
4492                 }
4493                 _ => {
4494                     fcx.ccx.tcx.sess.span_bug(e.span,
4495                                               "vstore with unexpected \
4496                                                contents")
4497                 }
4498             }
4499         }
4500     }
4501 }
4502
4503 // Returns true if b contains a break that can exit from b
4504 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4505     // First: is there an unlabeled break immediately
4506     // inside the loop?
4507     (loop_query(&*b, |e| {
4508         match *e {
4509             ast::ExprBreak(_) => true,
4510             _ => false
4511         }
4512     })) ||
4513    // Second: is there a labeled break with label
4514    // <id> nested anywhere inside the loop?
4515     (block_query(b, |e| {
4516         match e.node {
4517             ast::ExprBreak(Some(_)) => {
4518                 match cx.def_map.borrow().find(&e.id) {
4519                     Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4520                     _ => false,
4521                 }
4522             }
4523             _ => false
4524         }}))
4525 }
4526
4527 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4528                              span: Span,
4529                              tps: &OwnedSlice<ast::TyParam>,
4530                              ty: ty::t) {
4531     debug!("check_bounds_are_used(n_tps={}, ty={})",
4532            tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4533
4534     // make a vector of booleans initially false, set to true when used
4535     if tps.len() == 0u { return; }
4536     let mut tps_used = Vec::from_elem(tps.len(), false);
4537
4538     ty::walk_ty(ty, |t| {
4539             match ty::get(t).sty {
4540                 ty::ty_param(ParamTy {idx, ..}) => {
4541                     debug!("Found use of ty param num {}", idx);
4542                     *tps_used.get_mut(idx) = true;
4543                 }
4544                 _ => ()
4545             }
4546         });
4547
4548     for (i, b) in tps_used.iter().enumerate() {
4549         if !*b {
4550             ccx.tcx.sess.span_err(
4551                 span,
4552                 format!("type parameter `{}` is unused",
4553                         token::get_ident(tps.get(i).ident)).as_slice());
4554         }
4555     }
4556 }
4557
4558 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4559     fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4560         ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4561     }
4562
4563     let tcx = ccx.tcx;
4564     let name = token::get_ident(it.ident);
4565     let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4566         let split : Vec<&str> = name.get().split('_').collect();
4567         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4568
4569         //We only care about the operation here
4570         match *split.get(1) {
4571             "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4572                                 param(ccx, 0),
4573                                 param(ccx, 0)),
4574                         param(ccx, 0)),
4575             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4576                        param(ccx, 0)),
4577             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4578                         ty::mk_nil()),
4579
4580             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
4581             "min"  | "umax" | "umin" => {
4582                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4583                  param(ccx, 0))
4584             }
4585             "fence" => {
4586                 (0, Vec::new(), ty::mk_nil())
4587             }
4588             op => {
4589                 tcx.sess.span_err(it.span,
4590                                   format!("unrecognized atomic operation \
4591                                            function: `{}`",
4592                                           op).as_slice());
4593                 return;
4594             }
4595         }
4596
4597     } else {
4598         match name.get() {
4599             "abort" => (0, Vec::new(), ty::mk_bot()),
4600             "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4601             "size_of" |
4602             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4603             "init" => (1u, Vec::new(), param(ccx, 0u)),
4604             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4605             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4606             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4607             "move_val_init" => {
4608                 (1u,
4609                  vec!(
4610                     ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4611                     param(ccx, 0u)
4612                   ),
4613                ty::mk_nil())
4614             }
4615             "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4616             "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4617
4618             "get_tydesc" => {
4619               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4620                   Ok(t) => t,
4621                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4622               };
4623               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4624                   ty: tydesc_ty,
4625                   mutbl: ast::MutImmutable
4626               });
4627               (1u, Vec::new(), td_ptr)
4628             }
4629             "type_id" => {
4630                 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4631                 match langid {
4632                     Ok(did) => (1u,
4633                                 Vec::new(),
4634                                 ty::mk_struct(ccx.tcx, did,
4635                                               subst::Substs::empty())),
4636                     Err(msg) => {
4637                         tcx.sess.span_fatal(it.span, msg.as_slice());
4638                     }
4639                 }
4640             },
4641             "visit_tydesc" => {
4642               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4643                   Ok(t) => t,
4644                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4645               };
4646               let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4647               let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4648                   Ok((_, vot)) => vot,
4649                   Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4650               };
4651
4652               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4653                   ty: tydesc_ty,
4654                   mutbl: ast::MutImmutable
4655               });
4656               (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4657             }
4658             "offset" => {
4659               (1,
4660                vec!(
4661                   ty::mk_ptr(tcx, ty::mt {
4662                       ty: param(ccx, 0),
4663                       mutbl: ast::MutImmutable
4664                   }),
4665                   ty::mk_int()
4666                ),
4667                ty::mk_ptr(tcx, ty::mt {
4668                    ty: param(ccx, 0),
4669                    mutbl: ast::MutImmutable
4670                }))
4671             }
4672             "copy_memory" | "copy_nonoverlapping_memory" |
4673             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4674               (1,
4675                vec!(
4676                   ty::mk_ptr(tcx, ty::mt {
4677                       ty: param(ccx, 0),
4678                       mutbl: ast::MutMutable
4679                   }),
4680                   ty::mk_ptr(tcx, ty::mt {
4681                       ty: param(ccx, 0),
4682                       mutbl: ast::MutImmutable
4683                   }),
4684                   ty::mk_uint()
4685                ),
4686                ty::mk_nil())
4687             }
4688             "set_memory" | "volatile_set_memory" => {
4689               (1,
4690                vec!(
4691                   ty::mk_ptr(tcx, ty::mt {
4692                       ty: param(ccx, 0),
4693                       mutbl: ast::MutMutable
4694                   }),
4695                   ty::mk_u8(),
4696                   ty::mk_uint()
4697                ),
4698                ty::mk_nil())
4699             }
4700             "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4701             "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4702             "powif32" => {
4703                (0,
4704                 vec!( ty::mk_f32(), ty::mk_i32() ),
4705                 ty::mk_f32())
4706             }
4707             "powif64" => {
4708                (0,
4709                 vec!( ty::mk_f64(), ty::mk_i32() ),
4710                 ty::mk_f64())
4711             }
4712             "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4713             "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4714             "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4715             "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4716             "powf32" => {
4717                (0,
4718                 vec!( ty::mk_f32(), ty::mk_f32() ),
4719                 ty::mk_f32())
4720             }
4721             "powf64" => {
4722                (0,
4723                 vec!( ty::mk_f64(), ty::mk_f64() ),
4724                 ty::mk_f64())
4725             }
4726             "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4727             "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4728             "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4729             "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4730             "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4731             "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4732             "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4733             "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4734             "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4735             "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4736             "fmaf32" => {
4737                 (0,
4738                  vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4739                  ty::mk_f32())
4740             }
4741             "fmaf64" => {
4742                 (0,
4743                  vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4744                  ty::mk_f64())
4745             }
4746             "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4747             "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4748             "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4749             "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4750             "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4751             "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4752             "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4753             "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4754             "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4755             "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4756             "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4757             "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4758             "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4759             "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4760             "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4761             "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4762             "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4763             "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4764             "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4765             "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4766             "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4767             "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4768             "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4769             "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4770             "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
4771             "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4772             "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4773             "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4774             "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4775             "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4776             "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4777
4778             "volatile_load" =>
4779                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4780             "volatile_store" =>
4781                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4782
4783             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4784                 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4785                 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4786
4787             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4788                 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4789                 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4790
4791             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4792                 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4793                 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4794
4795             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4796                 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4797                 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4798
4799             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4800                 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4801                 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4802
4803             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4804                 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4805                 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4806
4807             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4808                 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4809                 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4810
4811             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
4812                 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4813                 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4814
4815             ref other => {
4816                 tcx.sess.span_err(it.span,
4817                                   format!("unrecognized intrinsic function: `{}`",
4818                                           *other).as_slice());
4819                 return;
4820             }
4821         }
4822     };
4823     let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4824         fn_style: ast::UnsafeFn,
4825         abi: abi::RustIntrinsic,
4826         sig: FnSig {
4827             binder_id: it.id,
4828             inputs: inputs,
4829             output: output,
4830             variadic: false,
4831         }
4832     });
4833     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4834     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4835     if i_n_tps != n_tps {
4836         tcx.sess.span_err(it.span,
4837                           format!("intrinsic has wrong number of type \
4838                                    parameters: found {}, expected {}",
4839                                   i_n_tps,
4840                                   n_tps).as_slice());
4841     } else {
4842         require_same_types(tcx,
4843                            None,
4844                            false,
4845                            it.span,
4846                            i_ty.ty,
4847                            fty,
4848                            || {
4849                 format!("intrinsic has wrong type: expected `{}`",
4850                         ppaux::ty_to_string(ccx.tcx, fty))
4851             });
4852     }
4853 }