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_string(&*local.pat),
401 self.fcx.infcx().ty_to_string(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
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_string(
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_string(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_string(&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_string(
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_string(
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_string(
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_string(t_1));
1105 debug!("t_e={}", fcx.infcx().ty_to_string(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_string(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_string(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_string(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_string(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_string(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_string(&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_string(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_string(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_string(*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_string(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_string(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_string(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_string(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_string(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_string(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::DefVariant(enum_id, variant_id, _)) => {
3370 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3371 variant_id, fields.as_slice());
3374 // Verify that this was actually a struct.
3375 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3376 match ty::get(typ.ty).sty {
3377 ty::ty_struct(struct_did, _) => {
3378 check_struct_constructor(fcx,
3387 .span_err(path.span,
3388 format!("`{}` does not name a structure",
3389 pprust::path_to_string(
3395 tcx.sess.span_bug(path.span,
3396 "structure constructor wasn't resolved")
3400 ast::ExprField(ref base, ref field, ref tys) => {
3401 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3403 ast::ExprIndex(ref base, ref idx) => {
3404 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3405 check_expr(fcx, &**idx);
3406 let raw_base_t = fcx.expr_ty(&**base);
3407 let idx_t = fcx.expr_ty(&**idx);
3408 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3409 fcx.write_ty(id, raw_base_t);
3410 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3411 fcx.write_ty(id, idx_t);
3413 let (_, autoderefs, field_ty) =
3414 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3415 lvalue_pref, |base_t, _| ty::index(base_t));
3418 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3419 fcx.write_ty(id, mt.ty);
3420 fcx.write_autoderef_adjustment(base.id, autoderefs);
3423 // This is an overloaded method.
3424 let base_t = structurally_resolved_type(fcx,
3427 let method_call = MethodCall::expr(expr.id);
3428 match try_overloaded_index(fcx,
3435 Some(mt) => fcx.write_ty(id, mt.ty),
3437 fcx.type_error_message(expr.span,
3447 fcx.write_ty(id, ty::mk_err())
3456 debug!("type of expr({}) {} is...", expr.id,
3457 syntax::print::pprust::expr_to_string(expr));
3458 debug!("... {}, expected is {}",
3459 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3460 expected.repr(tcx));
3466 fn only_has_type(self) -> Expectation {
3468 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3469 ExpectHasType(t) => ExpectHasType(t)
3473 // Resolves `expected` by a single level if it is a variable. If
3474 // there is no expected type or resolution is not possible (e.g.,
3475 // no constraints yet present), just returns `None`.
3476 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3481 ExpectCastableToType(t) => {
3482 ExpectCastableToType(
3483 fcx.infcx().resolve_type_vars_if_possible(t))
3485 ExpectHasType(t) => {
3487 fcx.infcx().resolve_type_vars_if_possible(t))
3492 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3493 match self.resolve(fcx) {
3494 NoExpectation => NoExpectation,
3495 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3499 fn map_to_option<O>(self,
3501 unpack: |&ty::sty| -> Option<O>)
3504 match self.resolve(fcx) {
3505 NoExpectation => None,
3506 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3511 impl Repr for Expectation {
3512 fn repr(&self, tcx: &ty::ctxt) -> String {
3514 NoExpectation => format!("NoExpectation"),
3515 ExpectHasType(t) => format!("ExpectHasType({})",
3517 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3523 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3524 if !type_is_uint(fcx, sp, t) {
3525 fcx.type_error_message(sp, |actual| {
3526 format!("mismatched types: expected `uint` type but found `{}`",
3532 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3533 if !type_is_integral(fcx, sp, t) {
3534 fcx.type_error_message(sp, |actual| {
3535 format!("mismatched types: expected integral type but found `{}`",
3541 pub fn check_decl_initializer(fcx: &FnCtxt,
3545 let local_ty = fcx.local_ty(init.span, nid);
3546 check_expr_coercable_to_type(fcx, init, local_ty)
3549 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3550 let tcx = fcx.ccx.tcx;
3552 let t = fcx.local_ty(local.span, local.id);
3553 fcx.write_ty(local.id, t);
3557 check_decl_initializer(fcx, local.id, &**init);
3558 let init_ty = fcx.expr_ty(&**init);
3559 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3560 fcx.write_ty(local.id, init_ty);
3566 let pcx = pat_ctxt {
3568 map: pat_id_map(&tcx.def_map, &*local.pat),
3570 _match::check_pat(&pcx, &*local.pat, t);
3571 let pat_ty = fcx.node_ty(local.pat.id);
3572 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3573 fcx.write_ty(local.id, pat_ty);
3577 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3579 let mut saw_bot = false;
3580 let mut saw_err = false;
3582 ast::StmtDecl(decl, id) => {
3585 ast::DeclLocal(ref l) => {
3586 check_decl_local(fcx, &**l);
3587 let l_t = fcx.node_ty(l.id);
3588 saw_bot = saw_bot || ty::type_is_bot(l_t);
3589 saw_err = saw_err || ty::type_is_error(l_t);
3591 ast::DeclItem(_) => {/* ignore for now */ }
3594 ast::StmtExpr(ref expr, id) => {
3596 // Check with expected type of ()
3597 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3598 let expr_ty = fcx.expr_ty(&**expr);
3599 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3600 saw_err = saw_err || ty::type_is_error(expr_ty);
3602 ast::StmtSemi(ref expr, id) => {
3604 check_expr(fcx, &**expr);
3605 let expr_ty = fcx.expr_ty(&**expr);
3606 saw_bot |= ty::type_is_bot(expr_ty);
3607 saw_err |= ty::type_is_error(expr_ty);
3609 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3612 fcx.write_bot(node_id);
3615 fcx.write_error(node_id);
3618 fcx.write_nil(node_id)
3622 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3623 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3624 let blkty = fcx.node_ty(blk.id);
3625 if ty::type_is_error(blkty) {
3626 fcx.write_error(blk.id);
3628 else if ty::type_is_bot(blkty) {
3629 fcx.write_bot(blk.id);
3632 let nilty = ty::mk_nil();
3633 demand::suptype(fcx, blk.span, nilty, blkty);
3637 fn check_block_with_expected(fcx: &FnCtxt,
3639 expected: Expectation) {
3641 let mut fcx_ps = fcx.ps.borrow_mut();
3642 let fn_style_state = fcx_ps.recurse(blk);
3643 replace(&mut *fcx_ps, fn_style_state)
3646 fcx.with_region_lb(blk.id, || {
3647 let mut warned = false;
3648 let mut last_was_bot = false;
3649 let mut any_bot = false;
3650 let mut any_err = false;
3651 for s in blk.stmts.iter() {
3652 check_stmt(fcx, &**s);
3653 let s_id = ast_util::stmt_id(&**s);
3654 let s_ty = fcx.node_ty(s_id);
3655 if last_was_bot && !warned && match s.node {
3656 ast::StmtDecl(decl, _) => {
3658 ast::DeclLocal(_) => true,
3662 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3668 .add_lint(lint::builtin::UNREACHABLE_CODE,
3671 "unreachable statement".to_string());
3674 if ty::type_is_bot(s_ty) {
3675 last_was_bot = true;
3677 any_bot = any_bot || ty::type_is_bot(s_ty);
3678 any_err = any_err || ty::type_is_error(s_ty);
3681 None => if any_err {
3682 fcx.write_error(blk.id);
3685 fcx.write_bot(blk.id);
3688 fcx.write_nil(blk.id);
3691 if any_bot && !warned {
3695 .add_lint(lint::builtin::UNREACHABLE_CODE,
3698 "unreachable expression".to_string());
3700 check_expr_with_expectation(fcx, e, expected);
3701 let ety = fcx.expr_ty(e);
3702 fcx.write_ty(blk.id, ety);
3704 fcx.write_error(blk.id);
3707 fcx.write_bot(blk.id);
3713 *fcx.ps.borrow_mut() = prev;
3716 pub fn check_const(ccx: &CrateCtxt,
3720 let inh = blank_inherited_fields(ccx);
3721 let rty = ty::node_id_to_type(ccx.tcx, id);
3722 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3723 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3724 check_const_with_ty(&fcx, sp, e, declty);
3727 pub fn check_const_with_ty(fcx: &FnCtxt,
3731 // Gather locals in statics (because of block expressions).
3732 // This is technically unnecessary because locals in static items are forbidden,
3733 // but prevents type checking from blowing up before const checking can properly
3735 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3738 let cty = fcx.expr_ty(e);
3739 demand::suptype(fcx, e.span, declty, cty);
3740 regionck::regionck_expr(fcx, e);
3741 writeback::resolve_type_vars_in_expr(fcx, e);
3744 /// Checks whether a type can be represented in memory. In particular, it
3745 /// identifies types that contain themselves without indirection through a
3746 /// pointer, which would mean their size is unbounded. This is different from
3747 /// the question of whether a type can be instantiated. See the definition of
3748 /// `check_instantiable`.
3749 pub fn check_representable(tcx: &ty::ctxt,
3751 item_id: ast::NodeId,
3752 designation: &str) -> bool {
3753 let rty = ty::node_id_to_type(tcx, item_id);
3755 // Check that it is possible to represent this type. This call identifies
3756 // (1) types that contain themselves and (2) types that contain a different
3757 // recursive type. It is only necessary to throw an error on those that
3758 // contain themselves. For case 2, there must be an inner type that will be
3759 // caught by case 1.
3760 match ty::is_type_representable(tcx, sp, rty) {
3761 ty::SelfRecursive => {
3763 sp, format!("illegal recursive {} type; \
3764 wrap the inner value in a box to make it representable",
3765 designation).as_slice());
3768 ty::Representable | ty::ContainsRecursive => (),
3773 /// Checks whether a type can be created without an instance of itself.
3774 /// This is similar but different from the question of whether a type
3775 /// can be represented. For example, the following type:
3777 /// enum foo { None, Some(foo) }
3779 /// is instantiable but is not representable. Similarly, the type
3781 /// enum foo { Some(@foo) }
3783 /// is representable, but not instantiable.
3784 pub fn check_instantiable(tcx: &ty::ctxt,
3786 item_id: ast::NodeId)
3788 let item_ty = ty::node_id_to_type(tcx, item_id);
3789 if !ty::is_instantiable(tcx, item_ty) {
3792 format!("this type cannot be instantiated without an \
3793 instance of itself; consider using \
3795 ppaux::ty_to_string(tcx, item_ty)).as_slice());
3802 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3803 let t = ty::node_id_to_type(tcx, id);
3804 if ty::type_needs_subst(t) {
3805 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3808 match ty::get(t).sty {
3809 ty::ty_struct(did, ref substs) => {
3810 let fields = ty::lookup_struct_fields(tcx, did);
3811 if fields.is_empty() {
3812 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3815 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3816 if !fields.iter().all(
3817 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3818 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3821 if !ty::type_is_machine(e) {
3822 tcx.sess.span_err(sp, "SIMD vector element type should be \
3831 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3832 vs: &[ast::P<ast::Variant>]) {
3833 for &v in vs.iter() {
3835 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3836 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3837 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3838 let len = arg_tys.len();
3842 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3843 // Allow the last field in an enum to be unsized.
3844 // We want to do this so that we can support smart pointers.
3845 // A struct value with an unsized final field is itself
3846 // unsized and we must track this in the type system.
3847 if !ty::type_is_sized(ccx.tcx, *t) {
3851 args.get(i).ty.span,
3852 format!("type `{}` is dynamically sized. \
3853 dynamically sized types may only \
3854 appear as the final type in a \
3856 ppaux::ty_to_string(ccx.tcx,
3861 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3867 pub fn check_enum_variants(ccx: &CrateCtxt,
3869 vs: &[ast::P<ast::Variant>],
3872 fn disr_in_range(ccx: &CrateCtxt,
3874 disr: ty::Disr) -> bool {
3875 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3877 ast::TyU8 => disr as u8 as Disr == disr,
3878 ast::TyU16 => disr as u16 as Disr == disr,
3879 ast::TyU32 => disr as u32 as Disr == disr,
3880 ast::TyU64 => disr as u64 as Disr == disr,
3881 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3884 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3886 ast::TyI8 => disr as i8 as Disr == disr,
3887 ast::TyI16 => disr as i16 as Disr == disr,
3888 ast::TyI32 => disr as i32 as Disr == disr,
3889 ast::TyI64 => disr as i64 as Disr == disr,
3890 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3894 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3895 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3899 fn do_check(ccx: &CrateCtxt,
3900 vs: &[ast::P<ast::Variant>],
3902 hint: attr::ReprAttr)
3903 -> Vec<Rc<ty::VariantInfo>> {
3905 let rty = ty::node_id_to_type(ccx.tcx, id);
3906 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3907 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3908 let mut prev_disr_val: Option<ty::Disr> = None;
3910 for &v in vs.iter() {
3912 // If the discriminant value is specified explicitly in the enum check whether the
3913 // initialization expression is valid, otherwise use the last value plus one.
3914 let mut current_disr_val = match prev_disr_val {
3915 Some(prev_disr_val) => prev_disr_val + 1,
3916 None => ty::INITIAL_DISCRIMINANT_VALUE
3919 match v.node.disr_expr {
3921 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
3923 let inh = blank_inherited_fields(ccx);
3924 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3925 let declty = match hint {
3926 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3927 attr::ReprInt(_, attr::SignedInt(ity)) => {
3928 ty::mk_mach_int(ity)
3930 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3931 ty::mk_mach_uint(ity)
3934 check_const_with_ty(&fcx, e.span, &*e, declty);
3935 // check_expr (from check_const pass) doesn't guarantee
3936 // that the expression is in a form that eval_const_expr can
3937 // handle, so we may still get an internal compiler error
3939 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3940 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3941 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3943 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3949 format!("expected constant: {}",
3957 // Check for duplicate discriminant values
3958 if disr_vals.contains(¤t_disr_val) {
3959 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3961 // Check for unrepresentable discriminant values
3963 attr::ReprAny | attr::ReprExtern => (),
3964 attr::ReprInt(sp, ity) => {
3965 if !disr_in_range(ccx, ity, current_disr_val) {
3966 ccx.tcx.sess.span_err(v.span,
3967 "discriminant value outside specified type");
3968 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3972 disr_vals.push(current_disr_val);
3974 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3976 prev_disr_val = Some(current_disr_val);
3978 variants.push(variant_info);
3984 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3985 if hint != attr::ReprAny && vs.len() <= 1 {
3986 let msg = if vs.len() == 1 {
3987 "unsupported representation for univariant enum"
3989 "unsupported representation for zero-variant enum"
3991 ccx.tcx.sess.span_err(sp, msg)
3994 let variants = do_check(ccx, vs, id, hint);
3996 // cache so that ty::enum_variants won't repeat this work
3997 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3999 check_representable(ccx.tcx, sp, id, "enum");
4001 // Check that it is possible to instantiate this enum:
4003 // This *sounds* like the same that as representable, but it's
4004 // not. See def'n of `check_instantiable()` for details.
4005 check_instantiable(ccx.tcx, sp, id);
4008 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4009 lookup_def_ccx(fcx.ccx, sp, id)
4012 // Returns the type parameter count and the type for the given definition.
4013 pub fn polytype_for_def(fcx: &FnCtxt,
4018 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4019 def::DefBinding(nid, _) => {
4020 let typ = fcx.local_ty(sp, nid);
4021 return no_params(typ);
4023 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4024 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4025 def::DefStruct(id) => {
4026 return ty::lookup_item_type(fcx.ccx.tcx, id);
4028 def::DefUpvar(_, inner, _, _) => {
4029 return polytype_for_def(fcx, sp, *inner);
4034 def::DefTyParam(..)=> {
4035 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4037 def::DefMod(..) | def::DefForeignMod(..) => {
4038 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4040 def::DefUse(..) => {
4041 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4043 def::DefRegion(..) => {
4044 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4046 def::DefTyParamBinder(..) => {
4047 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4049 def::DefLabel(..) => {
4050 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4052 def::DefSelfTy(..) => {
4053 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4055 def::DefMethod(..) => {
4056 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4061 // Instantiates the given path, which must refer to an item with the given
4062 // number of type parameters and type.
4063 pub fn instantiate_path(fcx: &FnCtxt,
4068 node_id: ast::NodeId) {
4069 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4070 path.repr(fcx.tcx()),
4071 def.repr(fcx.tcx()),
4073 polytype.repr(fcx.tcx()));
4075 // We need to extract the type parameters supplied by the user in
4076 // the path `path`. Due to the current setup, this is a bit of a
4077 // tricky-process; the problem is that resolve only tells us the
4078 // end-point of the path resolution, and not the intermediate steps.
4079 // Luckily, we can (at least for now) deduce the intermediate steps
4080 // just from the end-point.
4082 // There are basically three cases to consider:
4084 // 1. Reference to a *type*, such as a struct or enum:
4086 // mod a { struct Foo<T> { ... } }
4088 // Because we don't allow types to be declared within one
4089 // another, a path that leads to a type will always look like
4090 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4091 // that only the final segment can have type parameters, and
4092 // they are located in the TypeSpace.
4094 // *Note:* Generally speaking, references to types don't
4095 // actually pass through this function, but rather the
4096 // `ast_ty_to_ty` function in `astconv`. However, in the case
4097 // of struct patterns (and maybe literals) we do invoke
4098 // `instantiate_path` to get the general type of an instance of
4099 // a struct. (In these cases, there are actually no type
4100 // parameters permitted at present, but perhaps we will allow
4101 // them in the future.)
4103 // 1b. Reference to a enum variant or tuple-like struct:
4105 // struct foo<T>(...)
4106 // enum E<T> { foo(...) }
4108 // In these cases, the parameters are declared in the type
4111 // 2. Reference to a *fn item*:
4115 // In this case, the path will again always have the form
4116 // `a::b::foo::<T>` where only the final segment should have
4117 // type parameters. However, in this case, those parameters are
4118 // declared on a value, and hence are in the `FnSpace`.
4120 // 3. Reference to a *method*:
4122 // impl<A> SomeStruct<A> {
4126 // Here we can have a path like
4127 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4128 // may appear in two places. The penultimate segment,
4129 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4130 // final segment, `foo::<B>` contains parameters in fn space.
4132 // The first step then is to categorize the segments appropriately.
4134 assert!(path.segments.len() >= 1);
4135 let mut segment_spaces;
4137 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4138 def::DefSelfTy(..) |
4139 def::DefStruct(..) |
4140 def::DefVariant(..) |
4141 def::DefTyParamBinder(..) |
4144 def::DefPrimTy(..) |
4145 def::DefTyParam(..) => {
4146 // Everything but the final segment should have no
4147 // parameters at all.
4148 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4149 segment_spaces.push(Some(subst::TypeSpace));
4152 // Case 2. Reference to a top-level value.
4154 def::DefStatic(..) => {
4155 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4156 segment_spaces.push(Some(subst::FnSpace));
4159 // Case 3. Reference to a method.
4160 def::DefStaticMethod(..) => {
4161 assert!(path.segments.len() >= 2);
4162 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4163 segment_spaces.push(Some(subst::TypeSpace));
4164 segment_spaces.push(Some(subst::FnSpace));
4167 // Other cases. Various nonsense that really shouldn't show up
4168 // here. If they do, an error will have been reported
4169 // elsewhere. (I hope)
4171 def::DefForeignMod(..) |
4174 def::DefMethod(..) |
4175 def::DefBinding(..) |
4177 def::DefRegion(..) |
4179 def::DefUpvar(..) => {
4180 segment_spaces = Vec::from_elem(path.segments.len(), None);
4183 assert_eq!(segment_spaces.len(), path.segments.len());
4185 debug!("segment_spaces={}", segment_spaces);
4187 // Next, examine the definition, and determine how many type
4188 // parameters we expect from each space.
4189 let type_defs = &polytype.generics.types;
4190 let region_defs = &polytype.generics.regions;
4192 // Now that we have categorized what space the parameters for each
4193 // segment belong to, let's sort out the parameters that the user
4194 // provided (if any) into their appropriate spaces. We'll also report
4195 // errors if type parameters are provided in an inappropriate place.
4196 let mut substs = Substs::empty();
4197 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4200 report_error_if_segment_contains_type_parameters(fcx, segment);
4204 push_explicit_parameters_from_segment_to_substs(fcx,
4214 // Now we have to compare the types that the user *actually*
4215 // provided against the types that were *expected*. If the user
4216 // did not provide any types, then we want to substitute inference
4217 // variables. If the user provided some types, we may still need
4218 // to add defaults. If the user provided *too many* types, that's
4220 for &space in ParamSpace::all().iter() {
4221 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4222 assert_eq!(substs.types.len(space), type_defs.len(space));
4224 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4225 assert_eq!(substs.regions().len(space), region_defs.len(space));
4228 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4232 fn report_error_if_segment_contains_type_parameters(
4234 segment: &ast::PathSegment)
4236 for typ in segment.types.iter() {
4237 fcx.tcx().sess.span_err(
4239 "type parameters may not appear here");
4243 for lifetime in segment.lifetimes.iter() {
4244 fcx.tcx().sess.span_err(
4246 "lifetime parameters may not appear here");
4251 fn push_explicit_parameters_from_segment_to_substs(
4253 space: subst::ParamSpace,
4254 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4255 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4256 segment: &ast::PathSegment,
4257 substs: &mut Substs)
4260 * Finds the parameters that the user provided and adds them
4261 * to `substs`. If too many parameters are provided, then
4262 * reports an error and clears the output vector.
4264 * We clear the output vector because that will cause the
4265 * `adjust_XXX_parameters()` later to use inference
4266 * variables. This seems less likely to lead to derived
4269 * Note that we *do not* check for *too few* parameters here.
4270 * Due to the presence of defaults etc that is more
4271 * complicated. I wanted however to do the reporting of *too
4272 * many* parameters here because we can easily use the precise
4273 * span of the N+1'th parameter.
4277 let type_count = type_defs.len(space);
4278 assert_eq!(substs.types.len(space), 0);
4279 for (i, &typ) in segment.types.iter().enumerate() {
4280 let t = fcx.to_ty(&*typ);
4282 substs.types.push(space, t);
4283 } else if i == type_count {
4284 fcx.tcx().sess.span_err(
4287 "too many type parameters provided: \
4288 expected at most {} parameter(s) \
4289 but found {} parameter(s)",
4291 segment.types.len()).as_slice());
4292 substs.types.truncate(space, 0);
4298 let region_count = region_defs.len(space);
4299 assert_eq!(substs.regions().len(space), 0);
4300 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4301 let r = ast_region_to_region(fcx.tcx(), lifetime);
4302 if i < region_count {
4303 substs.mut_regions().push(space, r);
4304 } else if i == region_count {
4305 fcx.tcx().sess.span_err(
4308 "too many lifetime parameters provided: \
4309 expected {} parameter(s) but found {} parameter(s)",
4311 segment.lifetimes.len()).as_slice());
4312 substs.mut_regions().truncate(space, 0);
4318 fn adjust_type_parameters(
4322 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4323 substs: &mut Substs)
4325 let provided_len = substs.types.len(space);
4326 let desired = defs.get_slice(space);
4327 let required_len = desired.iter()
4328 .take_while(|d| d.default.is_none())
4331 debug!("adjust_type_parameters(space={}, \
4340 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4341 assert!(provided_len <= desired.len());
4343 // Nothing specified at all: supply inference variables for
4345 if provided_len == 0 {
4346 substs.types.replace(space,
4347 fcx.infcx().next_ty_vars(desired.len()));
4351 // Too few parameters specified: report an error and use Err
4353 if provided_len < required_len {
4355 if desired.len() != required_len { "at least " } else { "" };
4356 fcx.tcx().sess.span_err(
4358 format!("too few type parameters provided: \
4359 expected {}{} parameter(s) \
4360 but found {} parameter(s)",
4363 provided_len).as_slice());
4364 substs.types.replace(space,
4365 Vec::from_elem(desired.len(), ty::mk_err()));
4369 // Otherwise, add in any optional parameters that the user
4370 // omitted. The case of *too many* parameters is handled
4372 // push_explicit_parameters_from_segment_to_substs(). Note
4373 // that the *default* type are expressed in terms of all prior
4374 // parameters, so we have to substitute as we go with the
4375 // partial substitution that we have built up.
4376 for i in range(provided_len, desired.len()) {
4377 let default = desired[i].default.unwrap();
4378 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4379 substs.types.push(space, default);
4381 assert_eq!(substs.types.len(space), desired.len());
4383 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4386 fn adjust_region_parameters(
4390 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4391 substs: &mut Substs)
4393 let provided_len = substs.mut_regions().len(space);
4394 let desired = defs.get_slice(space);
4396 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4397 assert!(provided_len <= desired.len());
4399 // If nothing was provided, just use inference variables.
4400 if provided_len == 0 {
4401 substs.mut_regions().replace(
4403 fcx.infcx().region_vars_for_defs(span, desired));
4407 // If just the right number were provided, everybody is happy.
4408 if provided_len == desired.len() {
4412 // Otherwise, too few were provided. Report an error and then
4413 // use inference variables.
4414 fcx.tcx().sess.span_err(
4417 "too few lifetime parameters provided: \
4418 expected {} parameter(s) \
4419 but found {} parameter(s)",
4421 provided_len).as_slice());
4423 substs.mut_regions().replace(
4425 fcx.infcx().region_vars_for_defs(span, desired));
4429 // Resolves `typ` by a single level if `typ` is a type variable. If no
4430 // resolution is possible, then an error is reported.
4431 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4432 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4433 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4435 fcx.type_error_message(sp, |_actual| {
4436 "the type of this value must be known in this \
4437 context".to_string()
4439 demand::suptype(fcx, sp, ty::mk_err(), tp);
4445 // Returns the one-level-deep structure of the given type.
4446 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4448 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4451 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4452 let typ_s = structurally_resolved_type(fcx, sp, typ);
4453 return ty::type_is_integral(typ_s);
4456 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4457 let typ_s = structurally_resolved_type(fcx, sp, typ);
4458 return ty::type_is_uint(typ_s);
4461 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4464 mk_inner: || -> ty::mt)
4467 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4468 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4470 ast::ExprLit(..) => {
4471 // string literals and *empty slices* live in static memory
4472 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4474 ast::ExprVec(ref elements) if elements.len() == 0 => {
4475 // string literals and *empty slices* live in static memory
4476 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4478 ast::ExprRepeat(..) |
4479 ast::ExprVec(..) => {
4480 // vector literals are temporaries on the stack
4481 match fcx.tcx().region_maps.temporary_scope(e.id) {
4482 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4483 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4487 fcx.ccx.tcx.sess.span_bug(e.span,
4488 "vstore with unexpected \
4496 // Returns true if b contains a break that can exit from b
4497 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4498 // First: is there an unlabeled break immediately
4500 (loop_query(&*b, |e| {
4502 ast::ExprBreak(_) => true,
4506 // Second: is there a labeled break with label
4507 // <id> nested anywhere inside the loop?
4508 (block_query(b, |e| {
4510 ast::ExprBreak(Some(_)) => {
4511 match cx.def_map.borrow().find(&e.id) {
4512 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4520 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4522 tps: &OwnedSlice<ast::TyParam>,
4524 debug!("check_bounds_are_used(n_tps={}, ty={})",
4525 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4527 // make a vector of booleans initially false, set to true when used
4528 if tps.len() == 0u { return; }
4529 let mut tps_used = Vec::from_elem(tps.len(), false);
4531 ty::walk_ty(ty, |t| {
4532 match ty::get(t).sty {
4533 ty::ty_param(ParamTy {idx, ..}) => {
4534 debug!("Found use of ty param num {}", idx);
4535 *tps_used.get_mut(idx) = true;
4541 for (i, b) in tps_used.iter().enumerate() {
4543 ccx.tcx.sess.span_err(
4545 format!("type parameter `{}` is unused",
4546 token::get_ident(tps.get(i).ident)).as_slice());
4551 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4552 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4553 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4557 let name = token::get_ident(it.ident);
4558 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4559 let split : Vec<&str> = name.get().split('_').collect();
4560 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4562 //We only care about the operation here
4563 match *split.get(1) {
4564 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4568 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4570 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4573 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4574 "min" | "umax" | "umin" => {
4575 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4579 (0, Vec::new(), ty::mk_nil())
4582 tcx.sess.span_err(it.span,
4583 format!("unrecognized atomic operation \
4592 "abort" => (0, Vec::new(), ty::mk_bot()),
4593 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4595 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4596 "init" => (1u, Vec::new(), param(ccx, 0u)),
4597 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4598 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4599 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4600 "move_val_init" => {
4603 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4608 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4609 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4612 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4614 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4616 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4618 mutbl: ast::MutImmutable
4620 (1u, Vec::new(), td_ptr)
4623 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4627 ty::mk_struct(ccx.tcx, did,
4628 subst::Substs::empty())),
4630 tcx.sess.span_fatal(it.span, msg.as_slice());
4635 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4637 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4639 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4640 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4641 Ok((_, vot)) => vot,
4642 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4645 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4647 mutbl: ast::MutImmutable
4649 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4654 ty::mk_ptr(tcx, ty::mt {
4656 mutbl: ast::MutImmutable
4660 ty::mk_ptr(tcx, ty::mt {
4662 mutbl: ast::MutImmutable
4665 "copy_memory" | "copy_nonoverlapping_memory" |
4666 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4669 ty::mk_ptr(tcx, ty::mt {
4671 mutbl: ast::MutMutable
4673 ty::mk_ptr(tcx, ty::mt {
4675 mutbl: ast::MutImmutable
4681 "set_memory" | "volatile_set_memory" => {
4684 ty::mk_ptr(tcx, ty::mt {
4686 mutbl: ast::MutMutable
4693 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4694 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4697 vec!( ty::mk_f32(), ty::mk_i32() ),
4702 vec!( ty::mk_f64(), ty::mk_i32() ),
4705 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4706 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4707 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4708 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4711 vec!( ty::mk_f32(), ty::mk_f32() ),
4716 vec!( ty::mk_f64(), ty::mk_f64() ),
4719 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4720 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4721 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4722 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4723 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4724 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4725 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4726 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4727 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4728 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4731 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4736 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4739 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4740 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4741 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4742 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4743 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4744 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4745 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4746 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4747 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4748 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4749 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4750 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4751 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4752 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4753 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4754 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4755 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4756 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4757 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4758 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4759 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4760 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4761 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4762 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4763 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4764 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4765 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4766 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4767 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4768 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4769 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4772 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4774 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4776 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4777 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4778 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4780 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4781 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4782 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4784 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4785 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4786 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4788 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4789 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4790 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4792 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4793 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4794 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4796 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4797 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4798 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4800 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4801 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4802 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4804 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4805 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4806 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4809 tcx.sess.span_err(it.span,
4810 format!("unrecognized intrinsic function: `{}`",
4811 *other).as_slice());
4816 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4817 fn_style: ast::UnsafeFn,
4818 abi: abi::RustIntrinsic,
4826 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4827 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4828 if i_n_tps != n_tps {
4829 tcx.sess.span_err(it.span,
4830 format!("intrinsic has wrong number of type \
4831 parameters: found {}, expected {}",
4835 require_same_types(tcx,
4842 format!("intrinsic has wrong type: expected `{}`",
4843 ppaux::ty_to_string(ccx.tcx, fty))