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.
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.
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
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
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.
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.
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
43 - vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
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.
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`.
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.
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
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
80 use middle::const_eval;
82 use middle::pat_util::pat_id_map;
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};
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;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
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,
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>,
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(ty::t),
181 /// This expression will be cast to the `ty::t`
182 ExpectCastableToType(ty::t),
186 pub struct FnStyleState {
187 pub def: ast::NodeId,
188 pub fn_style: ast::FnStyle,
193 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
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,
206 let (fn_style, def) = match blk.rules {
207 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208 ast::DefaultBlock => (fn_style, self.def),
210 FnStyleState{ def: def,
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{
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>,
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,
240 ps: RefCell<FnStyleState>,
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.
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>,
257 inh: &'a Inherited<'a>,
259 ccx: &'a CrateCtxt<'a>,
262 impl<'a> Inherited<'a> {
263 fn new(tcx: &'a ty::ctxt,
264 param_env: ty::ParameterEnvironment)
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()),
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282 inh: &'a Inherited<'a>,
284 region_bnd: ast::NodeId)
287 writeback_errors: Cell::new(false),
288 err_count_on_creation: ccx.tcx.sess.err_count(),
290 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291 region_lb: Cell::new(region_bnd),
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()
304 Inherited::new(ccx.tcx, param_env)
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
312 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
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, ());
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
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, ());
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, ());
339 ccx.tcx.sess.abort_if_errors();
341 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342 visit::walk_crate(&mut visit, krate, ());
345 fn check_bare_fn(ccx: &CrateCtxt,
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, ¶m_env.free_substs);
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);
361 vtable::resolve_in_block(&fcx, body);
362 regionck::regionck_fn(&fcx, body);
363 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
365 _ => ccx.tcx.sess.impossible_case(body.span,
366 "check_bare_fn: function type expected")
370 struct GatherLocalsVisitor<'a> {
374 impl<'a> GatherLocalsVisitor<'a> {
375 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
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);
384 // take type that the user specified
385 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
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))
398 self.assign(local.id, o_ty);
399 debug!("Local variable {} is assigned type {}",
400 self.fcx.pat_to_str(&*local.pat),
401 self.fcx.infcx().ty_to_str(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
406 // Add pattern bindings.
407 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
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_str(
415 self.fcx.inh.locals.borrow().get_copy(&p.id)));
419 visit::walk_pat(self, p, ());
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, ()));
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, _: ()) { }
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438 fn_style: ast::FnStyle,
443 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
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.
452 * - inherited: other fields inherited from the enclosing fn (if any)
456 let err_count_on_creation = tcx.sess.err_count();
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})
464 relate_free_regions(tcx, &fn_sig);
466 let arg_tys = fn_sig.inputs.as_slice();
467 let ret_ty = fn_sig.output;
469 debug!("check_fn(arg_tys={}, ret_ty={})",
473 // Create the function context. This is either derived from scratch or,
474 // in the case of function expressions, based on the outer context.
476 writeback_errors: Cell::new(false),
477 err_count_on_creation: err_count_on_creation,
479 ps: RefCell::new(FnStyleState::function(fn_style, id)),
480 region_lb: Cell::new(body.id),
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,
493 |_bm, pat_id, _sp, _path| {
494 visit.assign(pat_id, None);
497 // Check the pattern.
500 map: pat_id_map(&tcx.def_map, &*input.pat),
502 _match::check_pat(&pcx, &*input.pat, *arg_ty);
505 visit.visit_block(body, ());
508 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
510 // We unify the tail expr's type with the
511 // function result type, if there is a tail 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),
519 fcx.report_mismatched_return_types(sp, e, a, s);
525 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526 fcx.write_ty(input.id, *arg);
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_str(struct_id.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,
549 .bug(format!("Could not find field {}",
550 token::get_name(field.name)).as_slice())
554 _ => tcx.sess.bug("Field found outside of a struct?"),
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
561 let struct_fields = tcx.struct_fields.borrow();
562 let fields = struct_fields.get(&id);
564 let superstructs = tcx.superstructs.borrow();
565 let super_struct = superstructs.get(&id);
566 match *super_struct {
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 \
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");
587 fn check_fields_sized(tcx: &ty::ctxt,
588 struct_def: &ast::StructDef) {
589 let len = struct_def.fields.len();
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) {
597 ast::NamedField(ident, _) => {
600 format!("type `{}` is dynamically sized. \
601 dynamically sized types may only \
602 appear as the type of the final \
604 token::get_ident(ident)).as_slice());
606 ast::UnnamedField(_) => {
607 tcx.sess.span_err(f.span, "dynamically sized type in field");
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
617 check_representable(tcx, span, id, "struct");
618 check_instantiable(tcx, span, id);
620 // Check there are no overlapping fields in super-structs
621 check_for_field_shadowing(tcx, local_def(id));
623 if ty::lookup_simd(tcx, local_def(id)) {
624 check_simd(tcx, span, id);
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629 debug!("check_item(it.id={}, it.ident={})",
631 ty::item_path_str(ccx.tcx, local_def(it.id)));
632 let _indenter = indenter();
635 ast::ItemEnum(ref enum_definition, _) => {
636 check_enum_variants_sized(ccx,
637 enum_definition.variants.as_slice());
639 ast::ItemStruct(..) => {
640 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647 debug!("check_item(it.id={}, it.ident={})",
649 ty::item_path_str(ccx.tcx, local_def(it.id)));
650 let _indenter = indenter();
653 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654 ast::ItemEnum(ref enum_definition, _) => {
655 check_enum_variants(ccx,
657 enum_definition.variants.as_slice(),
660 ast::ItemFn(ref decl, _, _, _, ref body) => {
661 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
663 let param_env = ty::construct_parameter_environment(ccx.tcx,
667 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
669 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
672 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
674 check_method_body(ccx, &impl_pty.generics, &**m);
677 match *opt_trait_ref {
678 Some(ref ast_trait_ref) => {
680 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681 check_impl_methods_against_trait(ccx,
686 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
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 {
697 // Nothing to do, since required methods don't have
701 check_method_body(ccx, &trait_def.generics, &*m);
706 ast::ItemStruct(..) => {
707 check_struct(ccx, it.id, it.span);
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);
713 ast::ItemForeignMod(ref m) => {
714 if m.abi == abi::RustIntrinsic {
715 for item in m.items.iter() {
716 check_intrinsic_type(ccx, &**item);
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");
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");
737 _ => {/* nothing to do */ }
741 fn check_method_body(ccx: &CrateCtxt,
742 item_generics: &ty::Generics,
743 method: &ast::Method) {
745 * Type checks a method body.
748 * - `item_generics`: generics defined on the impl/trait that contains
750 * - `self_bound`: bound for the `Self` type parameter, if any
751 * - `method`: the method definition
754 debug!("check_method_body(item_generics={}, method.id={})",
755 item_generics.repr(ccx.tcx),
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;
761 let param_env = ty::construct_parameter_environment(ccx.tcx,
765 let fty = ty::node_id_to_type(ccx.tcx, method.id);
767 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
772 ast_trait_ref: &ast::TraitRef,
773 impl_trait_ref: &ty::TraitRef,
774 impl_methods: &[Gc<ast::Method>]) {
775 // Locate trait methods
777 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
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);
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,
797 &impl_trait_ref.substs);
800 // This is span_bug as it should have already been caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_ident(impl_method_ty.ident),
806 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
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() {
817 impl_methods.iter().any(
818 |m| m.ident.name == trait_method.ident.name);
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)));
828 if !missing_methods.is_empty() {
831 format!("not all trait methods implemented, missing: {}",
832 missing_methods.connect(", ")).as_slice());
837 * Checks that a method from an impl/class conforms to the signature of
838 * the same method as declared in the trait.
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
849 fn compare_impl_method(tcx: &ty::ctxt,
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);
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
865 match (&trait_m.explicit_self, &impl_m.explicit_self) {
866 (&ast::SelfStatic, &ast::SelfStatic) => {}
867 (&ast::SelfStatic, _) => {
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_str(
874 impl_m.explicit_self)).as_slice());
877 (_, &ast::SelfStatic) => {
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_str(
884 trait_m.explicit_self)).as_slice());
888 // Let the type checker catch other errors below
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 {
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());
907 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
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());
920 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
921 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
923 // This code is best explained by example. Consider a trait:
926 // fn method<'a,M>(t: T, m: &'a M) -> Self;
931 // impl<'i, U> Trait<&'i U> for Foo {
932 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
935 // We wish to decide if those two method types are compatible.
937 // We start out with trait_to_impl_substs, that maps the trait type
938 // parameters to impl type parameters:
940 // trait_to_impl_substs = {T => &'i U, Self => Foo}
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).
949 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
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
955 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
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.
964 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
966 // Applying this to the trait method type yields:
968 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
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.
974 // Create mapping from impl to skolemized.
976 impl_m.generics.types.map(
977 |d| ty::mk_param_from_def(tcx, d));
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());
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);
988 // Compute skolemized form of trait method ty.
989 let trait_to_skol_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);
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:
1002 impl_param_def.bounds.builtin_bounds -
1003 trait_param_def.bounds.builtin_bounds;
1004 if !extra_bounds.is_empty() {
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),
1014 extra_bounds.user_string(tcx)).as_slice());
1018 // Check that the trait bounds of the trait imply the bounds of its
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);
1028 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
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,
1034 infer::Misc(impl_m_span),
1036 impl_trait_bound.clone()) {
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 \
1052 token::get_ident(trait_m.ident),
1054 ppaux::trait_ref_to_str(
1056 &*impl_trait_bound)).as_slice())
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
1070 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1071 impl_fty, trait_fty) {
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);
1084 fn check_cast(fcx: &FnCtxt,
1089 // Find the type of `e`. Supply hints based on the type we are casting to,
1091 let t_1 = fcx.to_ty(t);
1092 let t_1 = structurally_resolved_type(fcx, span, t_1);
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)
1102 let t_e = fcx.expr_ty(e);
1104 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
1105 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
1107 if ty::type_is_error(t_e) {
1108 fcx.write_error(id);
1111 if ty::type_is_bot(t_e) {
1116 if ty::type_is_trait(t_1) {
1117 // This will be looked up later on.
1118 fcx.write_ty(id, t_1);
1122 let t_1 = structurally_resolved_type(fcx, span, t_1);
1123 let t_e = structurally_resolved_type(fcx, span, t_e);
1125 if ty::type_is_nil(t_e) {
1126 fcx.type_error_message(span, |actual| {
1127 format!("cast from nil: `{}` as `{}`",
1129 fcx.infcx().ty_to_str(t_1))
1131 } else if ty::type_is_nil(t_1) {
1132 fcx.type_error_message(span, |actual| {
1133 format!("cast to nil: `{}` as `{}`",
1135 fcx.infcx().ty_to_str(t_1))
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);
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 {
1148 fcx.type_error_message(span, |actual| {
1149 format!("illegal cast; cast through an \
1150 integer first: `{}` as `{}`",
1152 fcx.infcx().ty_to_str(t_1))
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)
1164 } else if ty::get(t_1).sty == ty::ty_bool {
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.
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
1184 let el = ty::sequence_element_type(fcx.tcx(), t1);
1185 infer::mk_eqty(fcx.infcx(),
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.
1199 /* this cast is only allowed from &[T] to *T or
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 */
1208 demand::coerce(fcx, e.span, t_1, &*e);
1211 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
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.
1217 fcx.type_error_message(span, |actual| {
1218 format!("non-scalar cast: `{}` as `{}`",
1220 fcx.infcx().ty_to_str(t_1))
1224 fcx.write_ty(id, t_1);
1227 impl<'a> AstConv for FnCtxt<'a> {
1228 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1230 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1231 ty::lookup_item_type(self.tcx(), id)
1234 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1235 ty::lookup_trait_def(self.tcx(), id)
1238 fn ty_infer(&self, _span: Span) -> ty::t {
1239 self.infcx().next_ty_var()
1243 impl<'a> FnCtxt<'a> {
1244 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1248 pub fn err_count_since_creation(&self) -> uint {
1249 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1252 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1254 infcx: self.infcx(),
1255 param_env: &self.inh.param_env
1260 impl<'a> RegionScope for infer::InferCtxt<'a> {
1261 fn anon_regions(&self, span: Span, count: uint)
1262 -> Result<Vec<ty::Region> , ()> {
1263 Ok(Vec::from_fn(count, |_| {
1264 self.next_region_var(infer::MiscVariable(span))
1269 impl<'a> FnCtxt<'a> {
1270 pub fn tag(&self) -> String {
1271 format!("{}", self as *const FnCtxt)
1274 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1275 match self.inh.locals.borrow().find(&nid) {
1278 self.tcx().sess.span_bug(
1280 format!("no type for local variable {:?}",
1287 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1288 debug!("write_ty({}, {}) in fcx {}",
1289 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1290 self.inh.node_types.borrow_mut().insert(node_id, ty);
1293 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1294 if !substs.substs.is_noop() {
1295 debug!("write_substs({}, {}) in fcx {}",
1297 substs.repr(self.tcx()),
1300 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1304 pub fn write_ty_substs(&self,
1305 node_id: ast::NodeId,
1307 substs: ty::ItemSubsts) {
1308 let ty = ty.subst(self.tcx(), &substs.substs);
1309 self.write_ty(node_id, ty);
1310 self.write_substs(node_id, substs);
1313 pub fn write_autoderef_adjustment(&self,
1314 node_id: ast::NodeId,
1316 if derefs == 0 { return; }
1317 self.write_adjustment(
1319 ty::AutoDerefRef(ty::AutoDerefRef {
1325 pub fn write_adjustment(&self,
1326 node_id: ast::NodeId,
1327 adj: ty::AutoAdjustment) {
1328 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1329 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1332 pub fn write_nil(&self, node_id: ast::NodeId) {
1333 self.write_ty(node_id, ty::mk_nil());
1335 pub fn write_bot(&self, node_id: ast::NodeId) {
1336 self.write_ty(node_id, ty::mk_bot());
1338 pub fn write_error(&self, node_id: ast::NodeId) {
1339 self.write_ty(node_id, ty::mk_err());
1342 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1343 ast_ty_to_ty(self, self.infcx(), ast_t)
1346 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1347 pat.repr(self.tcx())
1350 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1351 match self.inh.node_types.borrow().find(&ex.id) {
1354 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1355 self.tag()).as_slice());
1360 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1361 match self.inh.node_types.borrow().find(&id) {
1364 self.tcx().sess.bug(
1365 format!("no type for node {}: {} in fcx {}",
1366 id, self.tcx().map.node_to_str(id),
1367 self.tag()).as_slice());
1372 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1373 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1374 Some(method) => method.substs.clone(),
1376 self.tcx().sess.bug(
1377 format!("no method entry for node {}: {} in fcx {}",
1378 id, self.tcx().map.node_to_str(id),
1379 self.tag()).as_slice());
1384 pub fn opt_node_ty_substs(&self,
1386 f: |&ty::ItemSubsts|) {
1387 match self.inh.item_substs.borrow().find(&id) {
1393 pub fn mk_subty(&self,
1394 a_is_expected: bool,
1395 origin: infer::TypeOrigin,
1398 -> Result<(), ty::type_err> {
1399 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1402 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1403 -> Result<(), ty::type_err> {
1404 infer::can_mk_subty(self.infcx(), sub, sup)
1407 pub fn mk_assignty(&self,
1411 -> Result<(), ty::type_err> {
1412 match infer::mk_coercety(self.infcx(),
1414 infer::ExprAssignable(expr.span),
1418 Err(ref e) => Err((*e)),
1419 Ok(Some(adjustment)) => {
1420 self.write_adjustment(expr.id, adjustment);
1426 pub fn mk_eqty(&self,
1427 a_is_expected: bool,
1428 origin: infer::TypeOrigin,
1431 -> Result<(), ty::type_err> {
1432 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1435 pub fn mk_subr(&self,
1436 a_is_expected: bool,
1437 origin: infer::SubregionOrigin,
1440 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1443 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1444 let old_region_lb = self.region_lb.get();
1445 self.region_lb.set(lb);
1447 self.region_lb.set(old_region_lb);
1451 pub fn type_error_message(&self,
1453 mk_msg: |String| -> String,
1455 err: Option<&ty::type_err>) {
1456 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1459 pub fn report_mismatched_return_types(&self,
1463 err: &ty::type_err) {
1465 if ty::type_is_error(e) || ty::type_is_error(a) {
1468 self.infcx().report_mismatched_types(sp, e, a, err)
1471 pub fn report_mismatched_types(&self,
1475 err: &ty::type_err) {
1476 self.infcx().report_mismatched_types(sp, e, a, err)
1480 pub enum LvaluePreference {
1485 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1486 expr_id: Option<ast::NodeId>,
1487 mut lvalue_pref: LvaluePreference,
1488 should_stop: |ty::t, uint| -> Option<T>)
1489 -> (ty::t, uint, Option<T>) {
1491 * Executes an autoderef loop for the type `t`. At each step, invokes
1492 * `should_stop` to decide whether to terminate the loop. Returns
1493 * the final type and number of derefs that it performed.
1495 * Note: this method does not modify the adjustments table. The caller is
1496 * responsible for inserting an AutoAdjustment record into the `fcx`
1497 * using one of the suitable methods.
1500 let mut t = base_ty;
1501 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1502 let resolved_t = structurally_resolved_type(fcx, sp, t);
1504 match should_stop(resolved_t, autoderefs) {
1505 Some(x) => return (resolved_t, autoderefs, Some(x)),
1509 // Otherwise, deref if type is derefable:
1510 let mt = match ty::deref(resolved_t, false) {
1511 Some(mt) => Some(mt),
1513 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1514 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1520 if mt.mutbl == ast::MutImmutable {
1521 lvalue_pref = NoPreference;
1524 None => return (resolved_t, autoderefs, None)
1528 // We've reached the recursion limit, error gracefully.
1529 fcx.tcx().sess.span_err(sp,
1530 format!("reached the recursion limit while auto-dereferencing {}",
1531 base_ty.repr(fcx.tcx())).as_slice());
1532 (ty::mk_err(), 0, None)
1535 /// Attempts to resolve a call expression as an overloaded call.
1536 fn try_overloaded_call(fcx: &FnCtxt,
1537 call_expression: &ast::Expr,
1538 callee: Gc<ast::Expr>,
1540 args: &[Gc<ast::Expr>])
1542 // Try `FnOnce`, then `FnMut`, then `Fn`.
1543 for &(maybe_function_trait, method_name) in [
1544 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1545 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1546 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1548 let function_trait = match maybe_function_trait {
1550 Some(function_trait) => function_trait,
1552 let method_callee = match method::lookup_in_trait(
1554 call_expression.span,
1560 DontAutoderefReceiver,
1561 IgnoreStaticMethods) {
1563 Some(method_callee) => method_callee,
1565 let method_call = MethodCall::expr(call_expression.id);
1566 let output_type = check_method_argument_types(fcx,
1567 call_expression.span,
1573 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1574 write_call(fcx, call_expression, output_type);
1576 if !fcx.tcx().sess.features.overloaded_calls.get() {
1577 fcx.tcx().sess.span_err(call_expression.span,
1578 "overloaded calls are experimental");
1579 fcx.tcx().sess.span_note(call_expression.span,
1580 "add `#[feature(overloaded_calls)]` to \
1581 the crate attributes to enable");
1590 fn try_overloaded_deref(fcx: &FnCtxt,
1592 method_call: Option<MethodCall>,
1593 base_expr: Option<&ast::Expr>,
1595 lvalue_pref: LvaluePreference)
1597 // Try DerefMut first, if preferred.
1598 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1599 (PreferMutLvalue, Some(trait_did)) => {
1600 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1601 token::intern("deref_mut"), trait_did,
1602 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1607 // Otherwise, fall back to Deref.
1608 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1609 (None, Some(trait_did)) => {
1610 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1611 token::intern("deref"), trait_did,
1612 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1614 (method, _) => method
1619 let ref_ty = ty::ty_fn_ret(method.ty);
1621 Some(method_call) => {
1622 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1626 ty::deref(ref_ty, true)
1632 fn try_overloaded_index(fcx: &FnCtxt,
1633 method_call: Option<MethodCall>,
1635 base_expr: Gc<ast::Expr>,
1637 index_expr: Gc<ast::Expr>,
1638 lvalue_pref: LvaluePreference)
1640 // Try `IndexMut` first, if preferred.
1641 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1642 (PreferMutLvalue, Some(trait_did)) => {
1643 method::lookup_in_trait(fcx,
1646 token::intern("index_mut"),
1650 DontAutoderefReceiver,
1651 IgnoreStaticMethods)
1656 // Otherwise, fall back to `Index`.
1657 let method = match (method, fcx.tcx().lang_items.index_trait()) {
1658 (None, Some(trait_did)) => {
1659 method::lookup_in_trait(fcx,
1662 token::intern("index"),
1666 DontAutoderefReceiver,
1667 IgnoreStaticMethods)
1669 (method, _) => method,
1672 // Regardless of whether the lookup succeeds, check the method arguments
1673 // so that we have *some* type for each argument.
1674 let method_type = match method {
1675 Some(ref method) => method.ty,
1676 None => ty::mk_err()
1678 check_method_argument_types(fcx,
1682 [base_expr, index_expr],
1684 DontTupleArguments);
1688 let ref_ty = ty::ty_fn_ret(method.ty);
1690 Some(method_call) => {
1691 fcx.inh.method_map.borrow_mut().insert(method_call,
1696 ty::deref(ref_ty, true)
1702 fn check_method_argument_types(fcx: &FnCtxt,
1704 method_fn_ty: ty::t,
1705 callee_expr: &ast::Expr,
1706 args: &[Gc<ast::Expr>],
1707 deref_args: DerefArgs,
1708 tuple_arguments: TupleArgumentsFlag)
1710 // HACK(eddyb) ignore provided self (it has special typeck rules).
1711 let args = if tuple_arguments == DontTupleArguments {
1716 if ty::type_is_error(method_fn_ty) {
1717 let err_inputs = err_args(args.len());
1718 check_argument_types(fcx,
1720 err_inputs.as_slice(),
1728 match ty::get(method_fn_ty).sty {
1729 ty::ty_bare_fn(ref fty) => {
1730 // HACK(eddyb) ignore self in the definition (see above).
1731 check_argument_types(fcx,
1733 fty.sig.inputs.slice_from(1),
1742 fcx.tcx().sess.span_bug(callee_expr.span,
1743 "method without bare fn type");
1749 fn check_argument_types(fcx: &FnCtxt,
1751 fn_inputs: &[ty::t],
1752 callee_expr: &ast::Expr,
1753 args: &[Gc<ast::Expr>],
1754 deref_args: DerefArgs,
1756 tuple_arguments: TupleArgumentsFlag) {
1759 * Generic function that factors out common logic from
1760 * function calls, method calls and overloaded operators.
1763 let tcx = fcx.ccx.tcx;
1765 // Grab the argument types, supplying fresh type variables
1766 // if the wrong number of arguments were supplied
1767 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1773 let expected_arg_count = fn_inputs.len();
1774 let formal_tys = if tuple_arguments == TupleArguments {
1775 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1776 match ty::get(tuple_type).sty {
1777 ty::ty_tup(ref arg_types) => {
1778 if arg_types.len() != args.len() {
1780 "this function takes {} parameter{} \
1781 but {} parameter{} supplied",
1783 if arg_types.len() == 1 {""} else {"s"},
1785 if args.len() == 1 {" was"} else {"s were"});
1786 tcx.sess.span_err(sp, msg.as_slice());
1787 err_args(args.len())
1789 (*arg_types).clone()
1793 if args.len() != 0 {
1795 "this function takes 0 parameters \
1796 but {} parameter{} supplied",
1798 if args.len() == 1 {" was"} else {"s were"});
1799 tcx.sess.span_err(sp, msg.as_slice());
1806 "cannot use call notation; the first type \
1807 parameter for the function trait is neither a \
1809 err_args(supplied_arg_count)
1812 } else if expected_arg_count == supplied_arg_count {
1813 fn_inputs.iter().map(|a| *a).collect()
1814 } else if variadic {
1815 if supplied_arg_count >= expected_arg_count {
1816 fn_inputs.iter().map(|a| *a).collect()
1819 "this function takes at least {} parameter{} \
1820 but {} parameter{} supplied",
1822 if expected_arg_count == 1 {""} else {"s"},
1824 if supplied_arg_count == 1 {" was"} else {"s were"});
1826 tcx.sess.span_err(sp, msg.as_slice());
1828 err_args(supplied_arg_count)
1832 "this function takes {} parameter{} \
1833 but {} parameter{} supplied",
1835 if expected_arg_count == 1 {""} else {"s"},
1837 if supplied_arg_count == 1 {" was"} else {"s were"});
1839 tcx.sess.span_err(sp, msg.as_slice());
1841 err_args(supplied_arg_count)
1844 debug!("check_argument_types: formal_tys={:?}",
1845 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1847 // Check the arguments.
1848 // We do this in a pretty awful way: first we typecheck any arguments
1849 // that are not anonymous functions, then we typecheck the anonymous
1850 // functions. This is so that we have more information about the types
1851 // of arguments when we typecheck the functions. This isn't really the
1852 // right way to do this.
1853 let xs = [false, true];
1854 for check_blocks in xs.iter() {
1855 let check_blocks = *check_blocks;
1856 debug!("check_blocks={}", check_blocks);
1858 // More awful hacks: before we check the blocks, try to do
1859 // an "opportunistic" vtable resolution of any trait
1860 // bounds on the call.
1862 vtable::early_resolve_expr(callee_expr, fcx, true);
1865 // For variadic functions, we don't have a declared type for all of
1866 // the arguments hence we only do our usual type checking with
1867 // the arguments who's types we do know.
1868 let t = if variadic {
1870 } else if tuple_arguments == TupleArguments {
1875 for (i, arg) in args.iter().take(t).enumerate() {
1876 let is_block = match arg.node {
1877 ast::ExprFnBlock(..) |
1878 ast::ExprProc(..) => true,
1882 if is_block == check_blocks {
1883 debug!("checking the argument");
1884 let mut formal_ty = *formal_tys.get(i);
1888 match ty::get(formal_ty).sty {
1889 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1892 // So we hit this case when one implements the
1893 // operator traits but leaves an argument as
1894 // just T instead of &T. We'll catch it in the
1895 // mismatch impl/trait method phase no need to
1898 formal_ty = ty::mk_err();
1905 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1911 // We also need to make sure we at least write the ty of the other
1912 // arguments which we skipped above.
1914 for arg in args.iter().skip(expected_arg_count) {
1915 check_expr(fcx, &**arg);
1917 // There are a few types which get autopromoted when passed via varargs
1918 // in C but we just error out instead and require explicit casts.
1919 let arg_ty = structurally_resolved_type(fcx, arg.span,
1920 fcx.expr_ty(&**arg));
1921 match ty::get(arg_ty).sty {
1922 ty::ty_float(ast::TyF32) => {
1923 fcx.type_error_message(arg.span,
1925 format!("can't pass an {} to variadic \
1926 function, cast to c_double", t)
1929 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1930 fcx.type_error_message(arg.span, |t| {
1931 format!("can't pass {} to variadic \
1932 function, cast to c_int",
1936 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1937 fcx.type_error_message(arg.span, |t| {
1938 format!("can't pass {} to variadic \
1939 function, cast to c_uint",
1949 fn err_args(len: uint) -> Vec<ty::t> {
1950 Vec::from_fn(len, |_| ty::mk_err())
1953 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1954 fcx.write_ty(call_expr.id, output);
1957 // AST fragment checking
1958 fn check_lit(fcx: &FnCtxt,
1960 expected: Expectation)
1963 let tcx = fcx.ccx.tcx;
1966 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1967 ast::LitBinary(..) => {
1968 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1970 ast::LitByte(_) => ty::mk_u8(),
1971 ast::LitChar(_) => ty::mk_char(),
1972 ast::LitInt(_, t) => ty::mk_mach_int(t),
1973 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1974 ast::LitIntUnsuffixed(_) => {
1975 let opt_ty = expected.map_to_option(fcx, |sty| {
1977 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1978 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1979 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1980 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1981 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1985 opt_ty.unwrap_or_else(
1986 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1988 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1989 ast::LitFloatUnsuffixed(_) => {
1990 let opt_ty = expected.map_to_option(fcx, |sty| {
1992 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
1996 opt_ty.unwrap_or_else(
1997 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
1999 ast::LitNil => ty::mk_nil(),
2000 ast::LitBool(_) => ty::mk_bool()
2004 pub fn valid_range_bounds(ccx: &CrateCtxt,
2008 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2009 Some(val) => Some(val <= 0),
2014 pub fn check_expr_has_type(fcx: &FnCtxt,
2017 check_expr_with_unifier(
2018 fcx, expr, ExpectHasType(expected), NoPreference,
2019 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2022 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2025 check_expr_with_unifier(
2026 fcx, expr, ExpectHasType(expected), NoPreference,
2027 || demand::coerce(fcx, expr.span, expected, expr));
2030 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2031 check_expr_with_unifier(
2032 fcx, expr, ExpectHasType(expected), NoPreference,
2036 fn check_expr_with_expectation(fcx: &FnCtxt,
2038 expected: Expectation) {
2039 check_expr_with_unifier(
2040 fcx, expr, expected, NoPreference,
2044 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2046 expected: Expectation,
2047 lvalue_pref: LvaluePreference)
2049 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2052 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2053 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2056 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2057 lvalue_pref: LvaluePreference) {
2058 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2062 // determine the `self` type, using fresh variables for all variables
2063 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2064 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2066 pub fn impl_self_ty(vcx: &VtableContext,
2067 span: Span, // (potential) receiver for this impl
2070 let tcx = vcx.tcx();
2072 let ity = ty::lookup_item_type(tcx, did);
2073 let (n_tps, rps, raw_ty) =
2074 (ity.generics.types.len(subst::TypeSpace),
2075 ity.generics.regions.get_slice(subst::TypeSpace),
2078 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2079 let tps = vcx.infcx.next_ty_vars(n_tps);
2080 let substs = subst::Substs::new_type(tps, rps);
2081 let substd_ty = raw_ty.subst(tcx, &substs);
2083 TypeAndSubsts { substs: substs, ty: substd_ty }
2086 // Only for fields! Returns <none> for methods>
2087 // Indifferent to privacy flags
2088 pub fn lookup_field_ty(tcx: &ty::ctxt,
2089 class_id: ast::DefId,
2090 items: &[ty::field_ty],
2091 fieldname: ast::Name,
2092 substs: &subst::Substs) -> Option<ty::t> {
2094 let o_field = items.iter().find(|f| f.name == fieldname);
2095 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2098 // Controls whether the arguments are automatically referenced. This is useful
2099 // for overloaded binary and unary operators.
2100 pub enum DerefArgs {
2105 /// Controls whether the arguments are tupled. This is used for the call
2108 /// Tupling means that all call-side arguments are packed into a tuple and
2109 /// passed as a single parameter. For example, if tupling is enabled, this
2112 /// fn f(x: (int, int))
2114 /// Can be called as:
2121 #[deriving(Clone, Eq, PartialEq)]
2122 enum TupleArgumentsFlag {
2128 /// If an expression has any sub-expressions that result in a type error,
2129 /// inspecting that expression's type with `ty::type_is_error` will return
2130 /// true. Likewise, if an expression is known to diverge, inspecting its
2131 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2132 /// strict, _|_ can appear in the type of an expression that does not,
2133 /// itself, diverge: for example, fn() -> _|_.)
2134 /// Note that inspecting a type's structure *directly* may expose the fact
2135 /// that there are actually multiple representations for both `ty_err` and
2136 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2137 fn check_expr_with_unifier(fcx: &FnCtxt,
2139 expected: Expectation,
2140 lvalue_pref: LvaluePreference,
2143 debug!(">> typechecking");
2145 // A generic function for doing all of the checking for call expressions
2146 fn check_call(fcx: &FnCtxt,
2147 call_expr: &ast::Expr,
2149 args: &[Gc<ast::Expr>]) {
2150 // Store the type of `f` as the type of the callee
2151 let fn_ty = fcx.expr_ty(f);
2153 // Extract the function signature from `in_fty`.
2154 let fn_sty = structure_of(fcx, f.span, fn_ty);
2156 // This is the "default" function signature, used in case of error.
2157 // In that case, we check each argument against "error" in order to
2158 // set up all the node type bindings.
2159 let error_fn_sig = FnSig {
2160 binder_id: ast::CRATE_NODE_ID,
2161 inputs: err_args(args.len()),
2162 output: ty::mk_err(),
2166 let fn_sig = match *fn_sty {
2167 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2168 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2170 fcx.type_error_message(call_expr.span, |actual| {
2171 format!("expected function but found `{}`", actual)
2177 // Replace any bound regions that appear in the function
2178 // signature with region variables
2179 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2180 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2183 // Call the generic checker.
2184 check_argument_types(fcx,
2186 fn_sig.inputs.as_slice(),
2191 DontTupleArguments);
2193 write_call(fcx, call_expr, fn_sig.output);
2196 // Checks a method call.
2197 fn check_method_call(fcx: &FnCtxt,
2199 method_name: ast::SpannedIdent,
2200 args: &[Gc<ast::Expr>],
2201 tps: &[ast::P<ast::Ty>]) {
2202 let rcvr = args[0].clone();
2203 // We can't know if we need &mut self before we look up the method,
2204 // so treat the receiver as mutable just in case - only explicit
2205 // overloaded dereferences care about the distinction.
2206 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2208 // no need to check for bot/err -- callee does that
2209 let expr_t = structurally_resolved_type(fcx,
2211 fcx.expr_ty(&*rcvr));
2213 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2214 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2215 method_name.node.name,
2216 expr_t, tps.as_slice(),
2218 CheckTraitsAndInherentMethods,
2219 AutoderefReceiver, IgnoreStaticMethods) {
2221 let method_ty = method.ty;
2222 let method_call = MethodCall::expr(expr.id);
2223 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2227 debug!("(checking method call) failing expr is {}", expr.id);
2229 fcx.type_error_message(method_name.span,
2231 format!("type `{}` does not implement any \
2232 method in scope named `{}`",
2234 token::get_ident(method_name.node))
2239 // Add error type for the result
2240 fcx.write_error(expr.id);
2242 // Check for potential static matches (missing self parameters)
2246 method_name.node.name,
2250 CheckTraitsAndInherentMethods,
2251 DontAutoderefReceiver,
2252 ReportStaticMethods);
2258 // Call the generic checker.
2259 let ret_ty = check_method_argument_types(fcx,
2265 DontTupleArguments);
2267 write_call(fcx, expr, ret_ty);
2270 // A generic function for checking the then and else in an if
2272 fn check_then_else(fcx: &FnCtxt,
2273 cond_expr: &ast::Expr,
2274 then_blk: &ast::Block,
2275 opt_else_expr: Option<Gc<ast::Expr>>,
2278 expected: Expectation) {
2279 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2281 let branches_ty = match opt_else_expr {
2282 Some(ref else_expr) => {
2283 // Disregard "castable to" expectations because they
2284 // can lead us astray. Consider for example `if cond
2285 // {22} else {c} as u8` -- if we propagate the
2286 // "castable to u8" constraint to 22, it will pick the
2287 // type 22u8, which is overly constrained (c might not
2288 // be a u8). In effect, the problem is that the
2289 // "castable to" expectation is not the tightest thing
2290 // we can say, so we want to drop it in this case.
2291 // The tightest thing we can say is "must unify with
2292 // else branch". Note that in the case of a "has type"
2293 // constraint, this limitation does not hold.
2294 let expected = expected.only_has_type();
2296 check_block_with_expected(fcx, then_blk, expected);
2297 let then_ty = fcx.node_ty(then_blk.id);
2298 check_expr_with_expectation(fcx, &**else_expr, expected);
2299 let else_ty = fcx.expr_ty(&**else_expr);
2300 infer::common_supertype(fcx.infcx(),
2301 infer::IfExpression(sp),
2307 check_block_no_value(fcx, then_blk);
2312 let cond_ty = fcx.expr_ty(cond_expr);
2313 let if_ty = if ty::type_is_error(cond_ty) {
2315 } else if ty::type_is_bot(cond_ty) {
2321 fcx.write_ty(id, if_ty);
2324 fn lookup_op_method(fcx: &FnCtxt,
2328 trait_did: Option<ast::DefId>,
2329 args: &[Gc<ast::Expr>],
2330 autoderef_receiver: AutoderefReceiverFlag,
2331 unbound_method: ||) -> ty::t {
2332 let method = match trait_did {
2333 Some(trait_did) => {
2334 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2335 trait_did, self_t, [], autoderef_receiver,
2336 IgnoreStaticMethods)
2342 let method_ty = method.ty;
2343 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2344 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2345 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2346 check_method_argument_types(fcx,
2356 // Check the args anyway
2357 // so we get all the error messages
2358 let expected_ty = ty::mk_err();
2359 check_method_argument_types(fcx,
2365 DontTupleArguments);
2371 // could be either an expr_binop or an expr_assign_binop
2372 fn check_binop(fcx: &FnCtxt,
2377 is_binop_assignment: IsBinopAssignment) {
2378 let tcx = fcx.ccx.tcx;
2380 let lvalue_pref = match is_binop_assignment {
2381 BinopAssignment => PreferMutLvalue,
2382 SimpleBinop => NoPreference
2384 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2386 // Callee does bot / err checking
2387 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2388 fcx.expr_ty(&*lhs));
2390 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2391 // Shift is a special case: rhs must be uint, no matter what lhs is
2392 check_expr_has_type(fcx, rhs, ty::mk_uint());
2393 fcx.write_ty(expr.id, lhs_t);
2397 if ty::is_binopable(tcx, lhs_t, op) {
2398 let tvar = fcx.infcx().next_ty_var();
2399 demand::suptype(fcx, expr.span, tvar, lhs_t);
2400 check_expr_has_type(fcx, &*rhs, tvar);
2402 let result_t = match op {
2403 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2405 if ty::type_is_simd(tcx, lhs_t) {
2406 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2407 fcx.type_error_message(expr.span,
2409 format!("binary comparison \
2410 operation `{}` not \
2411 supported for floating \
2412 point SIMD vector `{}`",
2413 ast_util::binop_to_str(op),
2430 fcx.write_ty(expr.id, result_t);
2434 if op == ast::BiOr || op == ast::BiAnd {
2435 // This is an error; one of the operands must have the wrong
2437 fcx.write_error(expr.id);
2438 fcx.write_error(rhs.id);
2439 fcx.type_error_message(expr.span,
2441 format!("binary operation `{}` cannot be applied \
2443 ast_util::binop_to_str(op),
2450 // Check for overloaded operators if not an assignment.
2451 let result_t = if is_binop_assignment == SimpleBinop {
2452 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2454 fcx.type_error_message(expr.span,
2456 format!("binary assignment \
2458 cannot be applied to \
2460 ast_util::binop_to_str(op),
2465 check_expr(fcx, &*rhs);
2469 fcx.write_ty(expr.id, result_t);
2470 if ty::type_is_error(result_t) {
2471 fcx.write_ty(rhs.id, result_t);
2475 fn check_user_binop(fcx: &FnCtxt,
2477 lhs_expr: Gc<ast::Expr>,
2478 lhs_resolved_t: ty::t,
2480 rhs: Gc<ast::Expr>) -> ty::t {
2481 let tcx = fcx.ccx.tcx;
2482 let lang = &tcx.lang_items;
2483 let (name, trait_did) = match op {
2484 ast::BiAdd => ("add", lang.add_trait()),
2485 ast::BiSub => ("sub", lang.sub_trait()),
2486 ast::BiMul => ("mul", lang.mul_trait()),
2487 ast::BiDiv => ("div", lang.div_trait()),
2488 ast::BiRem => ("rem", lang.rem_trait()),
2489 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2490 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2491 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2492 ast::BiShl => ("shl", lang.shl_trait()),
2493 ast::BiShr => ("shr", lang.shr_trait()),
2494 ast::BiLt => ("lt", lang.ord_trait()),
2495 ast::BiLe => ("le", lang.ord_trait()),
2496 ast::BiGe => ("ge", lang.ord_trait()),
2497 ast::BiGt => ("gt", lang.ord_trait()),
2498 ast::BiEq => ("eq", lang.eq_trait()),
2499 ast::BiNe => ("ne", lang.eq_trait()),
2500 ast::BiAnd | ast::BiOr => {
2501 check_expr(fcx, &*rhs);
2502 return ty::mk_err();
2505 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2506 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2507 fcx.type_error_message(ex.span, |actual| {
2508 format!("binary operation `{}` cannot be applied to type `{}`",
2509 ast_util::binop_to_str(op),
2511 }, lhs_resolved_t, None)
2515 fn check_user_unop(fcx: &FnCtxt,
2518 trait_did: Option<ast::DefId>,
2520 rhs_expr: Gc<ast::Expr>,
2521 rhs_t: ty::t) -> ty::t {
2522 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2523 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2524 fcx.type_error_message(ex.span, |actual| {
2525 format!("cannot apply unary operator `{}` to type `{}`",
2531 fn check_expr_fn(fcx: &FnCtxt,
2533 store: ty::TraitStore,
2535 body: ast::P<ast::Block>,
2536 expected: Expectation) {
2537 let tcx = fcx.ccx.tcx;
2539 // Find the expected input/output types (if any). Substitute
2540 // fresh bound regions for any bound regions we find in the
2541 // expected types so as to avoid capture.
2542 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2545 expected_bounds) = {
2546 match expected_sty {
2547 Some(ty::ty_closure(ref cenv)) => {
2549 replace_late_bound_regions_in_fn_sig(
2551 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2552 let onceness = match (&store, &cenv.store) {
2553 // As the closure type and onceness go, only three
2554 // combinations are legit:
2558 // If the actual and expected closure type disagree with
2559 // each other, set expected onceness to be always Once or
2560 // Many according to the actual type. Otherwise, it will
2561 // yield either an illegal "many proc" or a less known
2562 // "once closure" in the error message.
2563 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2564 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2566 (&ty::UniqTraitStore, _) => ast::Once,
2567 (&ty::RegionTraitStore(..), _) => ast::Many,
2569 (Some(sig), onceness, cenv.bounds)
2572 // Not an error! Means we're inferring the closure type
2573 let mut bounds = ty::empty_builtin_bounds();
2574 let onceness = match expr.node {
2575 ast::ExprProc(..) => {
2576 bounds.add(ty::BoundSend);
2581 (None, onceness, bounds)
2586 // construct the function type
2587 let fn_ty = astconv::ty_of_closure(fcx,
2595 let fty_sig = fn_ty.sig.clone();
2596 let fty = ty::mk_closure(tcx, fn_ty);
2597 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2599 fcx.write_ty(expr.id, fty);
2601 // If the closure is a stack closure and hasn't had some non-standard
2602 // style inferred for it, then check it under its parent's style.
2603 // Otherwise, use its own
2604 let (inherited_style, id) = match store {
2605 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2606 fcx.ps.borrow().def),
2607 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2610 check_fn(fcx.ccx, inherited_style, &fty_sig,
2611 &*decl, id, &*body, fcx.inh);
2615 // Check field access expressions
2616 fn check_field(fcx: &FnCtxt,
2618 lvalue_pref: LvaluePreference,
2620 field: &ast::SpannedIdent,
2621 tys: &[ast::P<ast::Ty>]) {
2622 let tcx = fcx.ccx.tcx;
2623 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2624 let expr_t = structurally_resolved_type(fcx, expr.span,
2626 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2627 let (_, autoderefs, field_ty) =
2628 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2629 match ty::get(base_t).sty {
2630 ty::ty_struct(base_id, ref substs) => {
2631 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2632 let fields = ty::lookup_struct_fields(tcx, base_id);
2633 lookup_field_ty(tcx, base_id, fields.as_slice(),
2634 field.node.name, &(*substs))
2641 fcx.write_ty(expr.id, field_ty);
2642 fcx.write_autoderef_adjustment(base.id, autoderefs);
2648 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2649 match method::lookup(fcx,
2656 CheckTraitsAndInherentMethods,
2658 IgnoreStaticMethods) {
2660 fcx.type_error_message(
2663 format!("attempted to take value of method `{}` on type \
2664 `{}`", token::get_ident(field.node), actual)
2668 tcx.sess.span_note(field.span,
2669 "maybe a missing `()` to call it? If not, try an anonymous function.");
2673 fcx.type_error_message(
2676 format!("attempted access of field `{}` on \
2677 type `{}`, but no field with that \
2679 token::get_ident(field.node),
2686 fcx.write_error(expr.id);
2689 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2692 class_id: ast::DefId,
2693 node_id: ast::NodeId,
2694 substitutions: subst::Substs,
2695 field_types: &[ty::field_ty],
2696 ast_fields: &[ast::Field],
2697 check_completeness: bool) {
2698 let tcx = fcx.ccx.tcx;
2700 let mut class_field_map = HashMap::new();
2701 let mut fields_found = 0;
2702 for field in field_types.iter() {
2703 class_field_map.insert(field.name, (field.id, false));
2706 let mut error_happened = false;
2708 // Typecheck each field.
2709 for field in ast_fields.iter() {
2710 let mut expected_field_type = ty::mk_err();
2712 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2715 fcx.type_error_message(
2718 format!("structure `{}` has no field named `{}`",
2719 actual, token::get_ident(field.ident.node))
2723 error_happened = true;
2725 Some((_, true)) => {
2728 format!("field `{}` specified more than once",
2729 token::get_ident(field.ident
2730 .node)).as_slice());
2731 error_happened = true;
2733 Some((field_id, false)) => {
2734 expected_field_type =
2735 ty::lookup_field_type(
2736 tcx, class_id, field_id, &substitutions);
2737 class_field_map.insert(
2738 field.ident.node.name, (field_id, true));
2742 // Make sure to give a type to the field even if there's
2743 // an error, so we can continue typechecking
2744 check_expr_coercable_to_type(
2747 expected_field_type);
2751 fcx.write_error(node_id);
2754 if check_completeness && !error_happened {
2755 // Make sure the programmer specified all the fields.
2756 assert!(fields_found <= field_types.len());
2757 if fields_found < field_types.len() {
2758 let mut missing_fields = Vec::new();
2759 for class_field in field_types.iter() {
2760 let name = class_field.name;
2761 let (_, seen) = *class_field_map.get(&name);
2763 missing_fields.push(
2764 format!("`{}`", token::get_name(name).get()))
2768 tcx.sess.span_err(span,
2770 "missing field{}: {fields}",
2771 if missing_fields.len() == 1 {""} else {"s"},
2772 fields = missing_fields.connect(", ")).as_slice());
2776 if !error_happened {
2777 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2778 class_id, substitutions));
2782 fn check_struct_constructor(fcx: &FnCtxt,
2784 span: codemap::Span,
2785 class_id: ast::DefId,
2786 fields: &[ast::Field],
2787 base_expr: Option<Gc<ast::Expr>>) {
2788 let tcx = fcx.ccx.tcx;
2790 // Look up the number of type parameters and the raw type, and
2791 // determine whether the class is region-parameterized.
2792 let item_type = ty::lookup_item_type(tcx, class_id);
2793 let raw_type = item_type.ty;
2795 // Generate the struct type.
2796 let substitutions = fcx.infcx().fresh_substs_for_type(
2797 span, &item_type.generics);
2798 let mut struct_type = raw_type.subst(tcx, &substitutions);
2800 // Look up and check the fields.
2801 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2802 check_struct_or_variant_fields(fcx,
2808 class_fields.as_slice(),
2810 base_expr.is_none());
2811 if ty::type_is_error(fcx.node_ty(id)) {
2812 struct_type = ty::mk_err();
2815 // Check the base expression if necessary.
2818 Some(base_expr) => {
2819 check_expr_has_type(fcx, &*base_expr, struct_type);
2820 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2821 struct_type = ty::mk_bot();
2826 // Write in the resulting type.
2827 fcx.write_ty(id, struct_type);
2830 fn check_struct_enum_variant(fcx: &FnCtxt,
2832 span: codemap::Span,
2833 enum_id: ast::DefId,
2834 variant_id: ast::DefId,
2835 fields: &[ast::Field]) {
2836 let tcx = fcx.ccx.tcx;
2838 // Look up the number of type parameters and the raw type, and
2839 // determine whether the enum is region-parameterized.
2840 let item_type = ty::lookup_item_type(tcx, enum_id);
2841 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2842 let enum_type = item_type.ty.subst(tcx, &substitutions);
2844 // Look up and check the enum variant fields.
2845 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2846 check_struct_or_variant_fields(fcx,
2852 variant_fields.as_slice(),
2855 fcx.write_ty(id, enum_type);
2858 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2860 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2861 expected: Expectation)
2862 -> (ExprCheckerWithTy, ty::t) {
2863 let tcx = fcx.ccx.tcx;
2864 let (coerce, t) = match expected {
2865 // If we're given an expected type, we can try to coerce to it
2866 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2867 // Otherwise we just leave the type to be resolved later
2868 _ => (false, fcx.infcx().next_ty_var())
2871 (check_expr_coercable_to_type, t)
2873 (check_expr_has_type, t)
2877 let tcx = fcx.ccx.tcx;
2880 ast::ExprVstore(ev, vst) => {
2881 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2882 let typ = match ev.node {
2883 ast::ExprVec(ref args) => {
2884 let mutability = match vst {
2885 ast::ExprVstoreMutSlice => ast::MutMutable,
2886 _ => ast::MutImmutable,
2888 let mut any_error = false;
2889 let mut any_bot = false;
2890 for e in args.iter() {
2891 check(fcx, &**e, t);
2892 let arg_t = fcx.expr_ty(&**e);
2893 if ty::type_is_error(arg_t) {
2896 else if ty::type_is_bot(arg_t) {
2905 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2906 ty::mt{ ty: ty::mk_vec(tcx,
2907 ty::mt {ty: t, mutbl: mutability},
2909 mutbl: mutability })
2912 ast::ExprRepeat(ref element, ref count_expr) => {
2913 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2914 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2915 let mutability = match vst {
2916 ast::ExprVstoreMutSlice => ast::MutMutable,
2917 _ => ast::MutImmutable,
2919 check(fcx, &**element, t);
2920 let arg_t = fcx.expr_ty(&**element);
2921 if ty::type_is_error(arg_t) {
2923 } else if ty::type_is_bot(arg_t) {
2926 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2927 ty::mt{ ty: ty::mk_vec(tcx,
2928 ty::mt {ty: t, mutbl: mutability},
2933 ast::ExprLit(_) => {
2934 let error = if vst == ast::ExprVstoreSlice {
2935 "`&\"string\"` has been removed; use `\"string\"` instead"
2937 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2939 tcx.sess.span_err(expr.span, error);
2942 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2944 fcx.write_ty(ev.id, typ);
2945 fcx.write_ty(id, typ);
2948 ast::ExprBox(ref place, ref subexpr) => {
2949 check_expr(fcx, &**place);
2950 check_expr(fcx, &**subexpr);
2952 let mut checked = false;
2954 ast::ExprPath(ref path) => {
2955 // FIXME(pcwalton): For now we hardcode the two permissible
2956 // places: the exchange heap and the managed heap.
2957 let definition = lookup_def(fcx, path.span, place.id);
2958 let def_id = definition.def_id();
2959 if tcx.lang_items.exchange_heap() == Some(def_id) {
2960 fcx.write_ty(id, ty::mk_uniq(tcx,
2961 fcx.expr_ty(&**subexpr)));
2963 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2964 fcx.write_ty(id, ty::mk_box(tcx,
2965 fcx.expr_ty(&**subexpr)));
2973 tcx.sess.span_err(expr.span,
2974 "only the managed heap and exchange heap are \
2975 currently supported");
2976 fcx.write_ty(id, ty::mk_err());
2980 ast::ExprLit(lit) => {
2981 let typ = check_lit(fcx, lit, expected);
2982 fcx.write_ty(id, typ);
2984 ast::ExprBinary(op, ref lhs, ref rhs) => {
2985 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2987 let lhs_ty = fcx.expr_ty(&**lhs);
2988 let rhs_ty = fcx.expr_ty(&**rhs);
2989 if ty::type_is_error(lhs_ty) ||
2990 ty::type_is_error(rhs_ty) {
2991 fcx.write_error(id);
2993 else if ty::type_is_bot(lhs_ty) ||
2994 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2998 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2999 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3001 let lhs_t = fcx.expr_ty(&**lhs);
3002 let result_t = fcx.expr_ty(expr);
3003 demand::suptype(fcx, expr.span, result_t, lhs_t);
3005 let tcx = fcx.tcx();
3006 if !ty::expr_is_lval(tcx, &**lhs) {
3007 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3010 // Overwrite result of check_binop...this preserves existing behavior
3011 // but seems quite dubious with regard to user-defined methods
3012 // and so forth. - Niko
3013 if !ty::type_is_error(result_t)
3014 && !ty::type_is_bot(result_t) {
3015 fcx.write_nil(expr.id);
3018 ast::ExprUnary(unop, ref oprnd) => {
3019 let expected = expected.only_has_type();
3020 let expected_inner = expected.map(fcx, |sty| {
3022 ast::UnBox | ast::UnUniq => match *sty {
3023 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3030 ast::UnNot | ast::UnNeg => {
3038 let lvalue_pref = match unop {
3039 ast::UnDeref => lvalue_pref,
3042 check_expr_with_expectation_and_lvalue_pref(
3043 fcx, &**oprnd, expected_inner, lvalue_pref);
3044 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3045 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3048 oprnd_t = ty::mk_box(tcx, oprnd_t)
3051 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3054 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3055 oprnd_t = match ty::deref(oprnd_t, true) {
3057 None => match try_overloaded_deref(fcx, expr.span,
3058 Some(MethodCall::expr(expr.id)),
3059 Some(&**oprnd), oprnd_t, lvalue_pref) {
3062 let is_newtype = match ty::get(oprnd_t).sty {
3063 ty::ty_struct(did, ref substs) => {
3064 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3066 && fields.get(0).ident ==
3067 token::special_idents::unnamed_field
3072 // This is an obsolete struct deref
3073 tcx.sess.span_err(expr.span,
3074 "single-field tuple-structs can \
3075 no longer be dereferenced");
3077 fcx.type_error_message(expr.span, |actual| {
3078 format!("type `{}` cannot be \
3079 dereferenced", actual)
3088 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3090 if !(ty::type_is_integral(oprnd_t) ||
3091 ty::get(oprnd_t).sty == ty::ty_bool) {
3092 oprnd_t = check_user_unop(fcx, "!", "not",
3093 tcx.lang_items.not_trait(),
3094 expr, oprnd.clone(), oprnd_t);
3098 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3100 if !(ty::type_is_integral(oprnd_t) ||
3101 ty::type_is_fp(oprnd_t)) {
3102 oprnd_t = check_user_unop(fcx, "-", "neg",
3103 tcx.lang_items.neg_trait(),
3104 expr, oprnd.clone(), oprnd_t);
3109 fcx.write_ty(id, oprnd_t);
3111 ast::ExprAddrOf(mutbl, ref oprnd) => {
3112 let expected = expected.only_has_type();
3113 let hint = expected.map(fcx, |sty| {
3114 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3115 _ => NoExpectation }
3117 let lvalue_pref = match mutbl {
3118 ast::MutMutable => PreferMutLvalue,
3119 ast::MutImmutable => NoPreference
3121 check_expr_with_expectation_and_lvalue_pref(fcx,
3126 // Note: at this point, we cannot say what the best lifetime
3127 // is to use for resulting pointer. We want to use the
3128 // shortest lifetime possible so as to avoid spurious borrowck
3129 // errors. Moreover, the longest lifetime will depend on the
3130 // precise details of the value whose address is being taken
3131 // (and how long it is valid), which we don't know yet until type
3132 // inference is complete.
3134 // Therefore, here we simply generate a region variable. The
3135 // region inferencer will then select the ultimate value.
3136 // Finally, borrowck is charged with guaranteeing that the
3137 // value whose address was taken can actually be made to live
3138 // as long as it needs to live.
3139 let region = fcx.infcx().next_region_var(
3140 infer::AddrOfRegion(expr.span));
3142 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3143 let oprnd_t = if ty::type_is_error(tm.ty) {
3145 } else if ty::type_is_bot(tm.ty) {
3149 ty::mk_rptr(tcx, region, tm)
3151 fcx.write_ty(id, oprnd_t);
3153 ast::ExprPath(ref pth) => {
3154 let defn = lookup_def(fcx, pth.span, id);
3155 let pty = polytype_for_def(fcx, expr.span, defn);
3156 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3158 ast::ExprInlineAsm(ref ia) => {
3159 for &(_, ref input) in ia.inputs.iter() {
3160 check_expr(fcx, &**input);
3162 for &(_, ref out) in ia.outputs.iter() {
3163 check_expr(fcx, &**out);
3167 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3168 ast::ExprBreak(_) => { fcx.write_bot(id); }
3169 ast::ExprAgain(_) => { fcx.write_bot(id); }
3170 ast::ExprRet(ref expr_opt) => {
3171 let ret_ty = fcx.ret_ty;
3173 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3174 ret_ty, ty::mk_nil()) {
3175 Ok(_) => { /* fall through */ }
3179 "`return;` in function returning non-nil");
3183 check_expr_has_type(fcx, &**e, ret_ty);
3188 ast::ExprParen(a) => {
3189 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3190 fcx.write_ty(id, fcx.expr_ty(a));
3192 ast::ExprAssign(ref lhs, ref rhs) => {
3193 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3195 let tcx = fcx.tcx();
3196 if !ty::expr_is_lval(tcx, &**lhs) {
3197 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3200 let lhs_ty = fcx.expr_ty(&**lhs);
3201 check_expr_has_type(fcx, &**rhs, lhs_ty);
3202 let rhs_ty = fcx.expr_ty(&**rhs);
3204 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3205 fcx.write_error(id);
3206 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3212 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3213 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3214 id, expr.span, expected);
3216 ast::ExprWhile(ref cond, ref body) => {
3217 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3218 check_block_no_value(fcx, &**body);
3219 let cond_ty = fcx.expr_ty(&**cond);
3220 let body_ty = fcx.node_ty(body.id);
3221 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3222 fcx.write_error(id);
3224 else if ty::type_is_bot(cond_ty) {
3231 ast::ExprForLoop(..) =>
3232 fail!("non-desugared expr_for_loop"),
3233 ast::ExprLoop(ref body, _) => {
3234 check_block_no_value(fcx, &**body);
3235 if !may_break(tcx, expr.id, body.clone()) {
3242 ast::ExprMatch(ref discrim, ref arms) => {
3243 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3245 ast::ExprFnBlock(ref decl, ref body) => {
3246 let region = astconv::opt_ast_region_to_region(fcx,
3252 ty::RegionTraitStore(region, ast::MutMutable),
3257 ast::ExprProc(ref decl, ref body) => {
3265 ast::ExprBlock(ref b) => {
3266 check_block_with_expected(fcx, &**b, expected);
3267 fcx.write_ty(id, fcx.node_ty(b.id));
3269 ast::ExprCall(ref f, ref args) => {
3270 // Index expressions need to be handled separately, to inform them
3271 // that they appear in call position.
3272 check_expr(fcx, &**f);
3273 let f_ty = fcx.expr_ty(&**f);
3275 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3276 check_call(fcx, expr, &**f, args.as_slice());
3277 let (args_bot, args_err) = args.iter().fold((false, false),
3278 |(rest_bot, rest_err), a| {
3279 // is this not working?
3280 let a_ty = fcx.expr_ty(&**a);
3281 (rest_bot || ty::type_is_bot(a_ty),
3282 rest_err || ty::type_is_error(a_ty))});
3283 if ty::type_is_error(f_ty) || args_err {
3284 fcx.write_error(id);
3286 else if ty::type_is_bot(f_ty) || args_bot {
3291 ast::ExprMethodCall(ident, ref tps, ref args) => {
3292 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3293 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3294 let (args_bot, args_err) = arg_tys.fold((false, false),
3295 |(rest_bot, rest_err), a| {
3296 (rest_bot || ty::type_is_bot(a),
3297 rest_err || ty::type_is_error(a))});
3299 fcx.write_error(id);
3300 } else if args_bot {
3304 ast::ExprCast(ref e, ref t) => {
3305 check_cast(fcx, &**e, &**t, id, expr.span);
3307 ast::ExprVec(ref args) => {
3308 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3309 for e in args.iter() {
3310 check(fcx, &**e, t);
3312 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3314 fcx.write_ty(id, typ);
3316 ast::ExprRepeat(ref element, ref count_expr) => {
3317 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3318 let count = ty::eval_repeat_count(fcx, &**count_expr);
3319 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3320 check(fcx, &**element, t);
3321 let element_ty = fcx.expr_ty(&**element);
3322 if ty::type_is_error(element_ty) {
3323 fcx.write_error(id);
3325 else if ty::type_is_bot(element_ty) {
3329 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3331 fcx.write_ty(id, t);
3334 ast::ExprTup(ref elts) => {
3335 let expected = expected.only_has_type();
3336 let flds = expected.map_to_option(fcx, |sty| {
3338 ty::ty_tup(ref flds) => Some((*flds).clone()),
3342 let mut bot_field = false;
3343 let mut err_field = false;
3345 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3346 let opt_hint = match flds {
3347 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3350 check_expr_with_expectation(fcx, *e, opt_hint);
3351 let t = fcx.expr_ty(*e);
3352 err_field = err_field || ty::type_is_error(t);
3353 bot_field = bot_field || ty::type_is_bot(t);
3358 } else if err_field {
3359 fcx.write_error(id);
3361 let typ = ty::mk_tup(tcx, elt_ts);
3362 fcx.write_ty(id, typ);
3365 ast::ExprStruct(ref path, ref fields, base_expr) => {
3366 // Resolve the path.
3367 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3369 Some(def::DefStruct(type_def_id)) => {
3370 check_struct_constructor(fcx, id, expr.span, type_def_id,
3371 fields.as_slice(), base_expr);
3373 Some(def::DefVariant(enum_id, variant_id, _)) => {
3374 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3375 variant_id, fields.as_slice());
3378 tcx.sess.span_bug(path.span,
3379 "structure constructor does not name a structure type");
3383 ast::ExprField(ref base, ref field, ref tys) => {
3384 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3386 ast::ExprIndex(ref base, ref idx) => {
3387 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3388 check_expr(fcx, &**idx);
3389 let raw_base_t = fcx.expr_ty(&**base);
3390 let idx_t = fcx.expr_ty(&**idx);
3391 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3392 fcx.write_ty(id, raw_base_t);
3393 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3394 fcx.write_ty(id, idx_t);
3396 let (_, autoderefs, field_ty) =
3397 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3398 lvalue_pref, |base_t, _| ty::index(base_t));
3401 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3402 fcx.write_ty(id, mt.ty);
3403 fcx.write_autoderef_adjustment(base.id, autoderefs);
3406 // This is an overloaded method.
3407 let base_t = structurally_resolved_type(fcx,
3410 let method_call = MethodCall::expr(expr.id);
3411 match try_overloaded_index(fcx,
3418 Some(mt) => fcx.write_ty(id, mt.ty),
3420 fcx.type_error_message(expr.span,
3430 fcx.write_ty(id, ty::mk_err())
3439 debug!("type of expr({}) {} is...", expr.id,
3440 syntax::print::pprust::expr_to_str(expr));
3441 debug!("... {}, expected is {}",
3442 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3449 fn only_has_type(self) -> Expectation {
3451 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3452 ExpectHasType(t) => ExpectHasType(t)
3456 // Resolves `expected` by a single level if it is a variable. If
3457 // there is no expected type or resolution is not possible (e.g.,
3458 // no constraints yet present), just returns `None`.
3459 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3464 ExpectCastableToType(t) => {
3465 ExpectCastableToType(
3466 fcx.infcx().resolve_type_vars_if_possible(t))
3468 ExpectHasType(t) => {
3470 fcx.infcx().resolve_type_vars_if_possible(t))
3475 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3476 match self.resolve(fcx) {
3477 NoExpectation => NoExpectation,
3478 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3482 fn map_to_option<O>(self,
3484 unpack: |&ty::sty| -> Option<O>)
3487 match self.resolve(fcx) {
3488 NoExpectation => None,
3489 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3494 impl Repr for Expectation {
3495 fn repr(&self, tcx: &ty::ctxt) -> String {
3497 NoExpectation => format!("NoExpectation"),
3498 ExpectHasType(t) => format!("ExpectHasType({})",
3500 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3506 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3507 if !type_is_uint(fcx, sp, t) {
3508 fcx.type_error_message(sp, |actual| {
3509 format!("mismatched types: expected `uint` type but found `{}`",
3515 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3516 if !type_is_integral(fcx, sp, t) {
3517 fcx.type_error_message(sp, |actual| {
3518 format!("mismatched types: expected integral type but found `{}`",
3524 pub fn check_decl_initializer(fcx: &FnCtxt,
3528 let local_ty = fcx.local_ty(init.span, nid);
3529 check_expr_coercable_to_type(fcx, init, local_ty)
3532 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3533 let tcx = fcx.ccx.tcx;
3535 let t = fcx.local_ty(local.span, local.id);
3536 fcx.write_ty(local.id, t);
3540 check_decl_initializer(fcx, local.id, &**init);
3541 let init_ty = fcx.expr_ty(&**init);
3542 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3543 fcx.write_ty(local.id, init_ty);
3549 let pcx = pat_ctxt {
3551 map: pat_id_map(&tcx.def_map, &*local.pat),
3553 _match::check_pat(&pcx, &*local.pat, t);
3554 let pat_ty = fcx.node_ty(local.pat.id);
3555 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3556 fcx.write_ty(local.id, pat_ty);
3560 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3562 let mut saw_bot = false;
3563 let mut saw_err = false;
3565 ast::StmtDecl(decl, id) => {
3568 ast::DeclLocal(ref l) => {
3569 check_decl_local(fcx, &**l);
3570 let l_t = fcx.node_ty(l.id);
3571 saw_bot = saw_bot || ty::type_is_bot(l_t);
3572 saw_err = saw_err || ty::type_is_error(l_t);
3574 ast::DeclItem(_) => {/* ignore for now */ }
3577 ast::StmtExpr(ref expr, id) => {
3579 // Check with expected type of ()
3580 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3581 let expr_ty = fcx.expr_ty(&**expr);
3582 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3583 saw_err = saw_err || ty::type_is_error(expr_ty);
3585 ast::StmtSemi(ref expr, id) => {
3587 check_expr(fcx, &**expr);
3588 let expr_ty = fcx.expr_ty(&**expr);
3589 saw_bot |= ty::type_is_bot(expr_ty);
3590 saw_err |= ty::type_is_error(expr_ty);
3592 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3595 fcx.write_bot(node_id);
3598 fcx.write_error(node_id);
3601 fcx.write_nil(node_id)
3605 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3606 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3607 let blkty = fcx.node_ty(blk.id);
3608 if ty::type_is_error(blkty) {
3609 fcx.write_error(blk.id);
3611 else if ty::type_is_bot(blkty) {
3612 fcx.write_bot(blk.id);
3615 let nilty = ty::mk_nil();
3616 demand::suptype(fcx, blk.span, nilty, blkty);
3620 fn check_block_with_expected(fcx: &FnCtxt,
3622 expected: Expectation) {
3624 let mut fcx_ps = fcx.ps.borrow_mut();
3625 let fn_style_state = fcx_ps.recurse(blk);
3626 replace(&mut *fcx_ps, fn_style_state)
3629 fcx.with_region_lb(blk.id, || {
3630 let mut warned = false;
3631 let mut last_was_bot = false;
3632 let mut any_bot = false;
3633 let mut any_err = false;
3634 for s in blk.stmts.iter() {
3635 check_stmt(fcx, &**s);
3636 let s_id = ast_util::stmt_id(&**s);
3637 let s_ty = fcx.node_ty(s_id);
3638 if last_was_bot && !warned && match s.node {
3639 ast::StmtDecl(decl, _) => {
3641 ast::DeclLocal(_) => true,
3645 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3651 .add_lint(lint::builtin::UNREACHABLE_CODE,
3654 "unreachable statement".to_string());
3657 if ty::type_is_bot(s_ty) {
3658 last_was_bot = true;
3660 any_bot = any_bot || ty::type_is_bot(s_ty);
3661 any_err = any_err || ty::type_is_error(s_ty);
3664 None => if any_err {
3665 fcx.write_error(blk.id);
3668 fcx.write_bot(blk.id);
3671 fcx.write_nil(blk.id);
3674 if any_bot && !warned {
3678 .add_lint(lint::builtin::UNREACHABLE_CODE,
3681 "unreachable expression".to_string());
3683 check_expr_with_expectation(fcx, e, expected);
3684 let ety = fcx.expr_ty(e);
3685 fcx.write_ty(blk.id, ety);
3687 fcx.write_error(blk.id);
3690 fcx.write_bot(blk.id);
3696 *fcx.ps.borrow_mut() = prev;
3699 pub fn check_const(ccx: &CrateCtxt,
3703 let inh = blank_inherited_fields(ccx);
3704 let rty = ty::node_id_to_type(ccx.tcx, id);
3705 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3706 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3707 check_const_with_ty(&fcx, sp, e, declty);
3710 pub fn check_const_with_ty(fcx: &FnCtxt,
3714 // Gather locals in statics (because of block expressions).
3715 // This is technically unnecessary because locals in static items are forbidden,
3716 // but prevents type checking from blowing up before const checking can properly
3718 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3721 let cty = fcx.expr_ty(e);
3722 demand::suptype(fcx, e.span, declty, cty);
3723 regionck::regionck_expr(fcx, e);
3724 writeback::resolve_type_vars_in_expr(fcx, e);
3727 /// Checks whether a type can be represented in memory. In particular, it
3728 /// identifies types that contain themselves without indirection through a
3729 /// pointer, which would mean their size is unbounded. This is different from
3730 /// the question of whether a type can be instantiated. See the definition of
3731 /// `check_instantiable`.
3732 pub fn check_representable(tcx: &ty::ctxt,
3734 item_id: ast::NodeId,
3735 designation: &str) -> bool {
3736 let rty = ty::node_id_to_type(tcx, item_id);
3738 // Check that it is possible to represent this type. This call identifies
3739 // (1) types that contain themselves and (2) types that contain a different
3740 // recursive type. It is only necessary to throw an error on those that
3741 // contain themselves. For case 2, there must be an inner type that will be
3742 // caught by case 1.
3743 match ty::is_type_representable(tcx, sp, rty) {
3744 ty::SelfRecursive => {
3746 sp, format!("illegal recursive {} type; \
3747 wrap the inner value in a box to make it representable",
3748 designation).as_slice());
3751 ty::Representable | ty::ContainsRecursive => (),
3756 /// Checks whether a type can be created without an instance of itself.
3757 /// This is similar but different from the question of whether a type
3758 /// can be represented. For example, the following type:
3760 /// enum foo { None, Some(foo) }
3762 /// is instantiable but is not representable. Similarly, the type
3764 /// enum foo { Some(@foo) }
3766 /// is representable, but not instantiable.
3767 pub fn check_instantiable(tcx: &ty::ctxt,
3769 item_id: ast::NodeId)
3771 let item_ty = ty::node_id_to_type(tcx, item_id);
3772 if !ty::is_instantiable(tcx, item_ty) {
3775 format!("this type cannot be instantiated without an \
3776 instance of itself; consider using \
3778 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3785 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3786 let t = ty::node_id_to_type(tcx, id);
3787 if ty::type_needs_subst(t) {
3788 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3791 match ty::get(t).sty {
3792 ty::ty_struct(did, ref substs) => {
3793 let fields = ty::lookup_struct_fields(tcx, did);
3794 if fields.is_empty() {
3795 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3798 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3799 if !fields.iter().all(
3800 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3801 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3804 if !ty::type_is_machine(e) {
3805 tcx.sess.span_err(sp, "SIMD vector element type should be \
3814 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3815 vs: &[ast::P<ast::Variant>]) {
3816 for &v in vs.iter() {
3818 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3819 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3820 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3821 let len = arg_tys.len();
3825 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3826 // Allow the last field in an enum to be unsized.
3827 // We want to do this so that we can support smart pointers.
3828 // A struct value with an unsized final field is itself
3829 // unsized and we must track this in the type system.
3830 if !ty::type_is_sized(ccx.tcx, *t) {
3834 args.get(i).ty.span,
3835 format!("type `{}` is dynamically sized. \
3836 dynamically sized types may only \
3837 appear as the final type in a \
3839 ppaux::ty_to_str(ccx.tcx,
3844 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3850 pub fn check_enum_variants(ccx: &CrateCtxt,
3852 vs: &[ast::P<ast::Variant>],
3855 fn disr_in_range(ccx: &CrateCtxt,
3857 disr: ty::Disr) -> bool {
3858 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3860 ast::TyU8 => disr as u8 as Disr == disr,
3861 ast::TyU16 => disr as u16 as Disr == disr,
3862 ast::TyU32 => disr as u32 as Disr == disr,
3863 ast::TyU64 => disr as u64 as Disr == disr,
3864 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3867 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3869 ast::TyI8 => disr as i8 as Disr == disr,
3870 ast::TyI16 => disr as i16 as Disr == disr,
3871 ast::TyI32 => disr as i32 as Disr == disr,
3872 ast::TyI64 => disr as i64 as Disr == disr,
3873 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3877 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3878 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3882 fn do_check(ccx: &CrateCtxt,
3883 vs: &[ast::P<ast::Variant>],
3885 hint: attr::ReprAttr)
3886 -> Vec<Rc<ty::VariantInfo>> {
3888 let rty = ty::node_id_to_type(ccx.tcx, id);
3889 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3890 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3891 let mut prev_disr_val: Option<ty::Disr> = None;
3893 for &v in vs.iter() {
3895 // If the discriminant value is specified explicitly in the enum check whether the
3896 // initialization expression is valid, otherwise use the last value plus one.
3897 let mut current_disr_val = match prev_disr_val {
3898 Some(prev_disr_val) => prev_disr_val + 1,
3899 None => ty::INITIAL_DISCRIMINANT_VALUE
3902 match v.node.disr_expr {
3904 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3906 let inh = blank_inherited_fields(ccx);
3907 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3908 let declty = match hint {
3909 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3910 attr::ReprInt(_, attr::SignedInt(ity)) => {
3911 ty::mk_mach_int(ity)
3913 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3914 ty::mk_mach_uint(ity)
3917 check_const_with_ty(&fcx, e.span, &*e, declty);
3918 // check_expr (from check_const pass) doesn't guarantee
3919 // that the expression is in a form that eval_const_expr can
3920 // handle, so we may still get an internal compiler error
3922 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3923 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3924 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3926 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3932 format!("expected constant: {}",
3940 // Check for duplicate discriminant values
3941 if disr_vals.contains(¤t_disr_val) {
3942 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3944 // Check for unrepresentable discriminant values
3946 attr::ReprAny | attr::ReprExtern => (),
3947 attr::ReprInt(sp, ity) => {
3948 if !disr_in_range(ccx, ity, current_disr_val) {
3949 ccx.tcx.sess.span_err(v.span,
3950 "discriminant value outside specified type");
3951 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3955 disr_vals.push(current_disr_val);
3957 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3959 prev_disr_val = Some(current_disr_val);
3961 variants.push(variant_info);
3967 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3968 if hint != attr::ReprAny && vs.len() <= 1 {
3969 let msg = if vs.len() == 1 {
3970 "unsupported representation for univariant enum"
3972 "unsupported representation for zero-variant enum"
3974 ccx.tcx.sess.span_err(sp, msg)
3977 let variants = do_check(ccx, vs, id, hint);
3979 // cache so that ty::enum_variants won't repeat this work
3980 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3982 check_representable(ccx.tcx, sp, id, "enum");
3984 // Check that it is possible to instantiate this enum:
3986 // This *sounds* like the same that as representable, but it's
3987 // not. See def'n of `check_instantiable()` for details.
3988 check_instantiable(ccx.tcx, sp, id);
3991 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3992 lookup_def_ccx(fcx.ccx, sp, id)
3995 // Returns the type parameter count and the type for the given definition.
3996 pub fn polytype_for_def(fcx: &FnCtxt,
4001 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4002 def::DefBinding(nid, _) => {
4003 let typ = fcx.local_ty(sp, nid);
4004 return no_params(typ);
4006 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4007 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4008 def::DefStruct(id) => {
4009 return ty::lookup_item_type(fcx.ccx.tcx, id);
4011 def::DefUpvar(_, inner, _, _) => {
4012 return polytype_for_def(fcx, sp, *inner);
4017 def::DefTyParam(..)=> {
4018 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4020 def::DefMod(..) | def::DefForeignMod(..) => {
4021 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4023 def::DefUse(..) => {
4024 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4026 def::DefRegion(..) => {
4027 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4029 def::DefTyParamBinder(..) => {
4030 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4032 def::DefLabel(..) => {
4033 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4035 def::DefSelfTy(..) => {
4036 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4038 def::DefMethod(..) => {
4039 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4044 // Instantiates the given path, which must refer to an item with the given
4045 // number of type parameters and type.
4046 pub fn instantiate_path(fcx: &FnCtxt,
4051 node_id: ast::NodeId) {
4052 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4053 path.repr(fcx.tcx()),
4054 def.repr(fcx.tcx()),
4056 polytype.repr(fcx.tcx()));
4058 // We need to extract the type parameters supplied by the user in
4059 // the path `path`. Due to the current setup, this is a bit of a
4060 // tricky-process; the problem is that resolve only tells us the
4061 // end-point of the path resolution, and not the intermediate steps.
4062 // Luckily, we can (at least for now) deduce the intermediate steps
4063 // just from the end-point.
4065 // There are basically three cases to consider:
4067 // 1. Reference to a *type*, such as a struct or enum:
4069 // mod a { struct Foo<T> { ... } }
4071 // Because we don't allow types to be declared within one
4072 // another, a path that leads to a type will always look like
4073 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4074 // that only the final segment can have type parameters, and
4075 // they are located in the TypeSpace.
4077 // *Note:* Generally speaking, references to types don't
4078 // actually pass through this function, but rather the
4079 // `ast_ty_to_ty` function in `astconv`. However, in the case
4080 // of struct patterns (and maybe literals) we do invoke
4081 // `instantiate_path` to get the general type of an instance of
4082 // a struct. (In these cases, there are actually no type
4083 // parameters permitted at present, but perhaps we will allow
4084 // them in the future.)
4086 // 1b. Reference to a enum variant or tuple-like struct:
4088 // struct foo<T>(...)
4089 // enum E<T> { foo(...) }
4091 // In these cases, the parameters are declared in the type
4094 // 2. Reference to a *fn item*:
4098 // In this case, the path will again always have the form
4099 // `a::b::foo::<T>` where only the final segment should have
4100 // type parameters. However, in this case, those parameters are
4101 // declared on a value, and hence are in the `FnSpace`.
4103 // 3. Reference to a *method*:
4105 // impl<A> SomeStruct<A> {
4109 // Here we can have a path like
4110 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4111 // may appear in two places. The penultimate segment,
4112 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4113 // final segment, `foo::<B>` contains parameters in fn space.
4115 // The first step then is to categorize the segments appropriately.
4117 assert!(path.segments.len() >= 1);
4118 let mut segment_spaces;
4120 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4121 def::DefSelfTy(..) |
4122 def::DefStruct(..) |
4123 def::DefVariant(..) |
4124 def::DefTyParamBinder(..) |
4127 def::DefPrimTy(..) |
4128 def::DefTyParam(..) => {
4129 // Everything but the final segment should have no
4130 // parameters at all.
4131 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4132 segment_spaces.push(Some(subst::TypeSpace));
4135 // Case 2. Reference to a top-level value.
4137 def::DefStatic(..) => {
4138 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4139 segment_spaces.push(Some(subst::FnSpace));
4142 // Case 3. Reference to a method.
4143 def::DefStaticMethod(..) => {
4144 assert!(path.segments.len() >= 2);
4145 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4146 segment_spaces.push(Some(subst::TypeSpace));
4147 segment_spaces.push(Some(subst::FnSpace));
4150 // Other cases. Various nonsense that really shouldn't show up
4151 // here. If they do, an error will have been reported
4152 // elsewhere. (I hope)
4154 def::DefForeignMod(..) |
4157 def::DefMethod(..) |
4158 def::DefBinding(..) |
4160 def::DefRegion(..) |
4162 def::DefUpvar(..) => {
4163 segment_spaces = Vec::from_elem(path.segments.len(), None);
4166 assert_eq!(segment_spaces.len(), path.segments.len());
4168 debug!("segment_spaces={}", segment_spaces);
4170 // Next, examine the definition, and determine how many type
4171 // parameters we expect from each space.
4172 let type_defs = &polytype.generics.types;
4173 let region_defs = &polytype.generics.regions;
4175 // Now that we have categorized what space the parameters for each
4176 // segment belong to, let's sort out the parameters that the user
4177 // provided (if any) into their appropriate spaces. We'll also report
4178 // errors if type parameters are provided in an inappropriate place.
4179 let mut substs = Substs::empty();
4180 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4183 report_error_if_segment_contains_type_parameters(fcx, segment);
4187 push_explicit_parameters_from_segment_to_substs(fcx,
4197 // Now we have to compare the types that the user *actually*
4198 // provided against the types that were *expected*. If the user
4199 // did not provide any types, then we want to substitute inference
4200 // variables. If the user provided some types, we may still need
4201 // to add defaults. If the user provided *too many* types, that's
4203 for &space in ParamSpace::all().iter() {
4204 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4205 assert_eq!(substs.types.len(space), type_defs.len(space));
4207 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4208 assert_eq!(substs.regions().len(space), region_defs.len(space));
4211 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4215 fn report_error_if_segment_contains_type_parameters(
4217 segment: &ast::PathSegment)
4219 for typ in segment.types.iter() {
4220 fcx.tcx().sess.span_err(
4222 "type parameters may not appear here");
4226 for lifetime in segment.lifetimes.iter() {
4227 fcx.tcx().sess.span_err(
4229 "lifetime parameters may not appear here");
4234 fn push_explicit_parameters_from_segment_to_substs(
4236 space: subst::ParamSpace,
4237 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4238 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4239 segment: &ast::PathSegment,
4240 substs: &mut Substs)
4243 * Finds the parameters that the user provided and adds them
4244 * to `substs`. If too many parameters are provided, then
4245 * reports an error and clears the output vector.
4247 * We clear the output vector because that will cause the
4248 * `adjust_XXX_parameters()` later to use inference
4249 * variables. This seems less likely to lead to derived
4252 * Note that we *do not* check for *too few* parameters here.
4253 * Due to the presence of defaults etc that is more
4254 * complicated. I wanted however to do the reporting of *too
4255 * many* parameters here because we can easily use the precise
4256 * span of the N+1'th parameter.
4260 let type_count = type_defs.len(space);
4261 assert_eq!(substs.types.len(space), 0);
4262 for (i, &typ) in segment.types.iter().enumerate() {
4263 let t = fcx.to_ty(&*typ);
4265 substs.types.push(space, t);
4266 } else if i == type_count {
4267 fcx.tcx().sess.span_err(
4270 "too many type parameters provided: \
4271 expected at most {} parameter(s) \
4272 but found {} parameter(s)",
4274 segment.types.len()).as_slice());
4275 substs.types.truncate(space, 0);
4281 let region_count = region_defs.len(space);
4282 assert_eq!(substs.regions().len(space), 0);
4283 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4284 let r = ast_region_to_region(fcx.tcx(), lifetime);
4285 if i < region_count {
4286 substs.mut_regions().push(space, r);
4287 } else if i == region_count {
4288 fcx.tcx().sess.span_err(
4291 "too many lifetime parameters provided: \
4292 expected {} parameter(s) but found {} parameter(s)",
4294 segment.lifetimes.len()).as_slice());
4295 substs.mut_regions().truncate(space, 0);
4301 fn adjust_type_parameters(
4305 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4306 substs: &mut Substs)
4308 let provided_len = substs.types.len(space);
4309 let desired = defs.get_slice(space);
4310 let required_len = desired.iter()
4311 .take_while(|d| d.default.is_none())
4314 debug!("adjust_type_parameters(space={}, \
4323 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4324 assert!(provided_len <= desired.len());
4326 // Nothing specified at all: supply inference variables for
4328 if provided_len == 0 {
4329 substs.types.replace(space,
4330 fcx.infcx().next_ty_vars(desired.len()));
4334 // Too few parameters specified: report an error and use Err
4336 if provided_len < required_len {
4338 if desired.len() != required_len { "at least " } else { "" };
4339 fcx.tcx().sess.span_err(
4341 format!("too few type parameters provided: \
4342 expected {}{} parameter(s) \
4343 but found {} parameter(s)",
4346 provided_len).as_slice());
4347 substs.types.replace(space,
4348 Vec::from_elem(desired.len(), ty::mk_err()));
4352 // Otherwise, add in any optional parameters that the user
4353 // omitted. The case of *too many* parameters is handled
4355 // push_explicit_parameters_from_segment_to_substs(). Note
4356 // that the *default* type are expressed in terms of all prior
4357 // parameters, so we have to substitute as we go with the
4358 // partial substitution that we have built up.
4359 for i in range(provided_len, desired.len()) {
4360 let default = desired[i].default.unwrap();
4361 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4362 substs.types.push(space, default);
4364 assert_eq!(substs.types.len(space), desired.len());
4366 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4369 fn adjust_region_parameters(
4373 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4374 substs: &mut Substs)
4376 let provided_len = substs.mut_regions().len(space);
4377 let desired = defs.get_slice(space);
4379 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4380 assert!(provided_len <= desired.len());
4382 // If nothing was provided, just use inference variables.
4383 if provided_len == 0 {
4384 substs.mut_regions().replace(
4386 fcx.infcx().region_vars_for_defs(span, desired));
4390 // If just the right number were provided, everybody is happy.
4391 if provided_len == desired.len() {
4395 // Otherwise, too few were provided. Report an error and then
4396 // use inference variables.
4397 fcx.tcx().sess.span_err(
4400 "too few lifetime parameters provided: \
4401 expected {} parameter(s) \
4402 but found {} parameter(s)",
4404 provided_len).as_slice());
4406 substs.mut_regions().replace(
4408 fcx.infcx().region_vars_for_defs(span, desired));
4412 // Resolves `typ` by a single level if `typ` is a type variable. If no
4413 // resolution is possible, then an error is reported.
4414 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4415 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4416 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4418 fcx.type_error_message(sp, |_actual| {
4419 "the type of this value must be known in this \
4420 context".to_string()
4422 demand::suptype(fcx, sp, ty::mk_err(), tp);
4428 // Returns the one-level-deep structure of the given type.
4429 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4431 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4434 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4435 let typ_s = structurally_resolved_type(fcx, sp, typ);
4436 return ty::type_is_integral(typ_s);
4439 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4440 let typ_s = structurally_resolved_type(fcx, sp, typ);
4441 return ty::type_is_uint(typ_s);
4444 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4447 mk_inner: || -> ty::mt)
4450 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4451 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4453 ast::ExprLit(..) => {
4454 // string literals and *empty slices* live in static memory
4455 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4457 ast::ExprVec(ref elements) if elements.len() == 0 => {
4458 // string literals and *empty slices* live in static memory
4459 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4461 ast::ExprRepeat(..) |
4462 ast::ExprVec(..) => {
4463 // vector literals are temporaries on the stack
4464 match fcx.tcx().region_maps.temporary_scope(e.id) {
4465 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4466 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4470 fcx.ccx.tcx.sess.span_bug(e.span,
4471 "vstore with unexpected \
4479 // Returns true if b contains a break that can exit from b
4480 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4481 // First: is there an unlabeled break immediately
4483 (loop_query(&*b, |e| {
4485 ast::ExprBreak(_) => true,
4489 // Second: is there a labeled break with label
4490 // <id> nested anywhere inside the loop?
4491 (block_query(b, |e| {
4493 ast::ExprBreak(Some(_)) => {
4494 match cx.def_map.borrow().find(&e.id) {
4495 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4503 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4505 tps: &OwnedSlice<ast::TyParam>,
4507 debug!("check_bounds_are_used(n_tps={}, ty={})",
4508 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4510 // make a vector of booleans initially false, set to true when used
4511 if tps.len() == 0u { return; }
4512 let mut tps_used = Vec::from_elem(tps.len(), false);
4514 ty::walk_ty(ty, |t| {
4515 match ty::get(t).sty {
4516 ty::ty_param(ParamTy {idx, ..}) => {
4517 debug!("Found use of ty param num {}", idx);
4518 *tps_used.get_mut(idx) = true;
4524 for (i, b) in tps_used.iter().enumerate() {
4526 ccx.tcx.sess.span_err(
4528 format!("type parameter `{}` is unused",
4529 token::get_ident(tps.get(i).ident)).as_slice());
4534 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4535 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4536 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4540 let name = token::get_ident(it.ident);
4541 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4542 let split : Vec<&str> = name.get().split('_').collect();
4543 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4545 //We only care about the operation here
4546 match *split.get(1) {
4547 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4551 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4553 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4556 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4557 "min" | "umax" | "umin" => {
4558 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4562 (0, Vec::new(), ty::mk_nil())
4565 tcx.sess.span_err(it.span,
4566 format!("unrecognized atomic operation \
4575 "abort" => (0, Vec::new(), ty::mk_bot()),
4576 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4578 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4579 "init" => (1u, Vec::new(), param(ccx, 0u)),
4580 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4581 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4582 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4583 "move_val_init" => {
4586 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4591 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4592 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4595 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4597 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4599 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4601 mutbl: ast::MutImmutable
4603 (1u, Vec::new(), td_ptr)
4606 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4610 ty::mk_struct(ccx.tcx, did,
4611 subst::Substs::empty())),
4613 tcx.sess.span_fatal(it.span, msg.as_slice());
4618 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4620 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4622 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4623 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4624 Ok((_, vot)) => vot,
4625 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4628 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4630 mutbl: ast::MutImmutable
4632 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4637 ty::mk_ptr(tcx, ty::mt {
4639 mutbl: ast::MutImmutable
4643 ty::mk_ptr(tcx, ty::mt {
4645 mutbl: ast::MutImmutable
4648 "copy_memory" | "copy_nonoverlapping_memory" |
4649 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4652 ty::mk_ptr(tcx, ty::mt {
4654 mutbl: ast::MutMutable
4656 ty::mk_ptr(tcx, ty::mt {
4658 mutbl: ast::MutImmutable
4664 "set_memory" | "volatile_set_memory" => {
4667 ty::mk_ptr(tcx, ty::mt {
4669 mutbl: ast::MutMutable
4676 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4677 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4680 vec!( ty::mk_f32(), ty::mk_i32() ),
4685 vec!( ty::mk_f64(), ty::mk_i32() ),
4688 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4689 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4690 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4691 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4694 vec!( ty::mk_f32(), ty::mk_f32() ),
4699 vec!( ty::mk_f64(), ty::mk_f64() ),
4702 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4703 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4704 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4705 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4706 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4707 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4708 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4709 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4710 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4711 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4714 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4719 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4722 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4723 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4724 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4725 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4726 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4727 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4728 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4729 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4730 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4731 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4732 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4733 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4734 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4735 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4736 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4737 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4738 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4739 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4740 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4741 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4742 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4743 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4744 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4745 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4746 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4747 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4748 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4749 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4750 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4751 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4752 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4755 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4757 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4759 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4760 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4761 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4763 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4764 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4765 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4767 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4768 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4769 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4771 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4772 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4773 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4775 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4776 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4777 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4779 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4780 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4781 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4783 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4784 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4785 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4787 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4788 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4789 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4792 tcx.sess.span_err(it.span,
4793 format!("unrecognized intrinsic function: `{}`",
4794 *other).as_slice());
4799 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4800 fn_style: ast::UnsafeFn,
4801 abi: abi::RustIntrinsic,
4809 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4810 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4811 if i_n_tps != n_tps {
4812 tcx.sess.span_err(it.span,
4813 format!("intrinsic has wrong number of type \
4814 parameters: found {}, expected {}",
4818 require_same_types(tcx,
4825 format!("intrinsic has wrong type: expected `{}`",
4826 ppaux::ty_to_str(ccx.tcx, fty))