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;
760 let m_body = ast_util::method_body(&*method);
762 let param_env = ty::construct_parameter_environment(ccx.tcx,
766 let fty = ty::node_id_to_type(ccx.tcx, method.id);
768 check_bare_fn(ccx, ast_util::method_fn_decl(&*method),
769 m_body, method.id, fty, param_env);
772 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
774 ast_trait_ref: &ast::TraitRef,
775 impl_trait_ref: &ty::TraitRef,
776 impl_methods: &[Gc<ast::Method>]) {
777 // Locate trait methods
779 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
781 // Check existing impl methods to see if they are both present in trait
782 // and compatible with trait signature
783 for impl_method in impl_methods.iter() {
784 let impl_method_def_id = local_def(impl_method.id);
785 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
787 // If this is an impl of a trait method, find the corresponding
788 // method definition in the trait.
789 let opt_trait_method_ty =
790 trait_methods.iter().
791 find(|tm| tm.ident.name == impl_method_ty.ident.name);
792 match opt_trait_method_ty {
793 Some(trait_method_ty) => {
794 compare_impl_method(ccx.tcx,
797 ast_util::method_body(&**impl_method).id,
799 &impl_trait_ref.substs);
802 // This is span_bug as it should have already been caught in resolve.
806 "method `{}` is not a member of trait `{}`",
807 token::get_ident(impl_method_ty.ident),
808 pprust::path_to_string(&ast_trait_ref.path)).as_slice());
813 // Check for missing methods from trait
814 let provided_methods = ty::provided_trait_methods(tcx,
815 impl_trait_ref.def_id);
816 let mut missing_methods = Vec::new();
817 for trait_method in trait_methods.iter() {
819 impl_methods.iter().any(
820 |m| ast_util::method_ident(&**m).name == trait_method.ident.name);
822 provided_methods.iter().any(
823 |m| m.ident.name == trait_method.ident.name);
824 if !is_implemented && !is_provided {
825 missing_methods.push(
826 format!("`{}`", token::get_ident(trait_method.ident)));
830 if !missing_methods.is_empty() {
833 format!("not all trait methods implemented, missing: {}",
834 missing_methods.connect(", ")).as_slice());
839 * Checks that a method from an impl/class conforms to the signature of
840 * the same method as declared in the trait.
844 * - impl_generics: the generics declared on the impl itself (not the method!)
845 * - impl_m: type of the method we are checking
846 * - impl_m_span: span to use for reporting errors
847 * - impl_m_body_id: id of the method body
848 * - trait_m: the method in the trait
849 * - trait_to_impl_substs: the substitutions used on the type of the trait
851 fn compare_impl_method(tcx: &ty::ctxt,
854 impl_m_body_id: ast::NodeId,
855 trait_m: &ty::Method,
856 trait_to_impl_substs: &subst::Substs) {
857 debug!("compare_impl_method()");
858 let infcx = infer::new_infer_ctxt(tcx);
860 // Try to give more informative error messages about self typing
861 // mismatches. Note that any mismatch will also be detected
862 // below, where we construct a canonical function type that
863 // includes the self parameter as a normal parameter. It's just
864 // that the error messages you get out of this code are a bit more
865 // inscrutable, particularly for cases where one method has no
867 match (&trait_m.explicit_self, &impl_m.explicit_self) {
868 (&ast::SelfStatic, &ast::SelfStatic) => {}
869 (&ast::SelfStatic, _) => {
872 format!("method `{}` has a `{}` declaration in the impl, \
873 but not in the trait",
874 token::get_ident(trait_m.ident),
875 pprust::explicit_self_to_string(
876 impl_m.explicit_self)).as_slice());
879 (_, &ast::SelfStatic) => {
882 format!("method `{}` has a `{}` declaration in the trait, \
883 but not in the impl",
884 token::get_ident(trait_m.ident),
885 pprust::explicit_self_to_string(
886 trait_m.explicit_self)).as_slice());
890 // Let the type checker catch other errors below
894 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
895 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
896 if num_impl_m_type_params != num_trait_m_type_params {
899 format!("method `{}` has {} type parameter{} \
900 but its trait declaration has {} type parameter{}",
901 token::get_ident(trait_m.ident),
902 num_impl_m_type_params,
903 if num_impl_m_type_params == 1 {""} else {"s"},
904 num_trait_m_type_params,
905 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
909 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
912 format!("method `{}` has {} parameter{} \
913 but the declaration in trait `{}` has {}",
914 token::get_ident(trait_m.ident),
915 impl_m.fty.sig.inputs.len(),
916 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
917 ty::item_path_str(tcx, trait_m.def_id),
918 trait_m.fty.sig.inputs.len()).as_slice());
922 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
923 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
925 // This code is best explained by example. Consider a trait:
928 // fn method<'a,M>(t: T, m: &'a M) -> Self;
933 // impl<'i, U> Trait<&'i U> for Foo {
934 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
937 // We wish to decide if those two method types are compatible.
939 // We start out with trait_to_impl_substs, that maps the trait type
940 // parameters to impl type parameters:
942 // trait_to_impl_substs = {T => &'i U, Self => Foo}
944 // We create a mapping `dummy_substs` that maps from the impl type
945 // parameters to fresh types and regions. For type parameters,
946 // this is the identity transform, but we could as well use any
947 // skolemized types. For regions, we convert from bound to free
948 // regions (Note: but only early-bound regions, i.e., those
949 // declared on the impl or used in type parameter bounds).
951 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
953 // Now we can apply skol_substs to the type of the impl method
954 // to yield a new function type in terms of our fresh, skolemized
957 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
959 // We now want to extract and substitute the type of the *trait*
960 // method and compare it. To do so, we must create a compound
961 // substitution by combining trait_to_impl_substs and
962 // impl_to_skol_substs, and also adding a mapping for the method
963 // type parameters. We extend the mapping to also include
964 // the method parameters.
966 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
968 // Applying this to the trait method type yields:
970 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
972 // This type is also the same but the name of the bound region ('a
973 // vs 'b). However, the normal subtyping rules on fn types handle
974 // this kind of equivalency just fine.
976 // Create mapping from impl to skolemized.
978 impl_m.generics.types.map(
979 |d| ty::mk_param_from_def(tcx, d));
981 impl_m.generics.regions.map(
982 |l| ty::free_region_from_def(impl_m_body_id, l));
983 let impl_to_skol_substs =
984 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
986 // Compute skolemized form of impl method ty.
987 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
988 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
990 // Compute skolemized form of trait method ty.
991 let trait_to_skol_substs =
993 .subst(tcx, &impl_to_skol_substs)
994 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
995 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
996 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
997 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1000 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1001 // Check that the impl does not require any builtin-bounds
1002 // that the trait does not guarantee:
1004 impl_param_def.bounds.builtin_bounds -
1005 trait_param_def.bounds.builtin_bounds;
1006 if !extra_bounds.is_empty() {
1009 format!("in method `{}`, \
1010 type parameter {} requires `{}`, \
1011 which is not required by \
1012 the corresponding type parameter \
1013 in the trait declaration",
1014 token::get_ident(trait_m.ident),
1016 extra_bounds.user_string(tcx)).as_slice());
1020 // Check that the trait bounds of the trait imply the bounds of its
1023 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1024 // traits, but I doubt that'll be wanted often, so meh.
1025 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1026 let impl_trait_bound =
1027 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1030 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1032 trait_bound.subst(tcx, &trait_to_skol_substs);
1033 let infcx = infer::new_infer_ctxt(tcx);
1034 match infer::mk_sub_trait_refs(&infcx,
1036 infer::Misc(impl_m_span),
1038 impl_trait_bound.clone()) {
1048 tcx.sess.span_err(impl_m_span,
1049 format!("in method `{}`, type parameter {} \
1050 requires bound `{}`, which is not \
1051 required by the corresponding \
1052 type parameter in the trait \
1054 token::get_ident(trait_m.ident),
1056 ppaux::trait_ref_to_string(
1058 &*impl_trait_bound)).as_slice())
1063 // Check the impl method type IM is a subtype of the trait method
1064 // type TM. To see why this makes sense, think of a vtable. The
1065 // expected type of the function pointers in the vtable is the
1066 // type TM of the trait method. The actual type will be the type
1067 // IM of the impl method. Because we know that IM <: TM, that
1068 // means that anywhere a TM is expected, a IM will do instead. In
1069 // other words, anyone expecting to call a method with the type
1070 // from the trait, can safely call a method with the type from the
1072 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1073 impl_fty, trait_fty) {
1078 format!("method `{}` has an incompatible type for trait: {}",
1079 token::get_ident(trait_m.ident),
1080 ty::type_err_to_str(tcx, terr)).as_slice());
1081 ty::note_and_explain_type_err(tcx, terr);
1086 fn check_cast(fcx: &FnCtxt,
1091 // Find the type of `e`. Supply hints based on the type we are casting to,
1093 let t_1 = fcx.to_ty(t);
1094 let t_1 = structurally_resolved_type(fcx, span, t_1);
1096 if ty::type_is_scalar(t_1) {
1097 // Supply the type as a hint so as to influence integer
1098 // literals and other things that might care.
1099 check_expr_with_hint(fcx, e, t_1)
1104 let t_e = fcx.expr_ty(e);
1106 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1107 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1109 if ty::type_is_error(t_e) {
1110 fcx.write_error(id);
1113 if ty::type_is_bot(t_e) {
1118 if ty::type_is_trait(t_1) {
1119 // This will be looked up later on.
1120 fcx.write_ty(id, t_1);
1124 let t_1 = structurally_resolved_type(fcx, span, t_1);
1125 let t_e = structurally_resolved_type(fcx, span, t_e);
1127 if ty::type_is_nil(t_e) {
1128 fcx.type_error_message(span, |actual| {
1129 format!("cast from nil: `{}` as `{}`",
1131 fcx.infcx().ty_to_string(t_1))
1133 } else if ty::type_is_nil(t_1) {
1134 fcx.type_error_message(span, |actual| {
1135 format!("cast to nil: `{}` as `{}`",
1137 fcx.infcx().ty_to_string(t_1))
1141 let t_1_is_scalar = ty::type_is_scalar(t_1);
1142 let t_1_is_char = ty::type_is_char(t_1);
1143 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1144 let t_1_is_float = ty::type_is_floating_point(t_1);
1146 // casts to scalars other than `char` and `bare fn` are trivial
1147 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1148 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1150 fcx.type_error_message(span, |actual| {
1151 format!("illegal cast; cast through an \
1152 integer first: `{}` as `{}`",
1154 fcx.infcx().ty_to_string(t_1))
1157 // casts from C-like enums are allowed
1158 } else if t_1_is_char {
1159 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1160 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1161 fcx.type_error_message(span, |actual| {
1162 format!("only `u8` can be cast as \
1163 `char`, not `{}`", actual)
1166 } else if ty::get(t_1).sty == ty::ty_bool {
1170 "cannot cast as `bool`, compare with zero instead");
1171 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1172 fn types_compatible(fcx: &FnCtxt, sp: Span,
1173 t1: ty::t, t2: ty::t) -> bool {
1174 if !ty::type_is_vec(t1) {
1175 // If the type being casted from is not a vector, this special
1176 // case does not apply.
1179 if ty::type_needs_infer(t2) {
1180 // This prevents this special case from going off when casting
1181 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1186 let el = ty::sequence_element_type(fcx.tcx(), t1);
1187 infer::mk_eqty(fcx.infcx(),
1194 // Due to the limitations of LLVM global constants,
1195 // region pointers end up pointing at copies of
1196 // vector elements instead of the original values.
1197 // To allow unsafe pointers to work correctly, we
1198 // need to special-case obtaining an unsafe pointer
1199 // from a region pointer to a vector.
1201 /* this cast is only allowed from &[T] to *T or
1203 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1204 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1205 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1206 if types_compatible(fcx, e.span, mt1, mt2) => {
1207 /* this case is allowed */
1210 demand::coerce(fcx, e.span, t_1, &*e);
1213 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1215 If more type combinations should be supported than are
1216 supported here, then file an enhancement issue and
1217 record the issue number in this comment.
1219 fcx.type_error_message(span, |actual| {
1220 format!("non-scalar cast: `{}` as `{}`",
1222 fcx.infcx().ty_to_string(t_1))
1224 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1225 fcx.type_error_message(span, |actual| {
1226 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1229 fcx.infcx().ty_to_string(t_1))
1233 fcx.write_ty(id, t_1);
1236 impl<'a> AstConv for FnCtxt<'a> {
1237 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1239 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1240 ty::lookup_item_type(self.tcx(), id)
1243 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1244 ty::lookup_trait_def(self.tcx(), id)
1247 fn ty_infer(&self, _span: Span) -> ty::t {
1248 self.infcx().next_ty_var()
1252 impl<'a> FnCtxt<'a> {
1253 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1257 pub fn err_count_since_creation(&self) -> uint {
1258 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1261 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1263 infcx: self.infcx(),
1264 param_env: &self.inh.param_env
1269 impl<'a> RegionScope for infer::InferCtxt<'a> {
1270 fn anon_regions(&self, span: Span, count: uint)
1271 -> Result<Vec<ty::Region> , ()> {
1272 Ok(Vec::from_fn(count, |_| {
1273 self.next_region_var(infer::MiscVariable(span))
1278 impl<'a> FnCtxt<'a> {
1279 pub fn tag(&self) -> String {
1280 format!("{}", self as *const FnCtxt)
1283 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1284 match self.inh.locals.borrow().find(&nid) {
1287 self.tcx().sess.span_bug(
1289 format!("no type for local variable {:?}",
1296 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1297 debug!("write_ty({}, {}) in fcx {}",
1298 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1299 self.inh.node_types.borrow_mut().insert(node_id, ty);
1302 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1303 if !substs.substs.is_noop() {
1304 debug!("write_substs({}, {}) in fcx {}",
1306 substs.repr(self.tcx()),
1309 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1313 pub fn write_ty_substs(&self,
1314 node_id: ast::NodeId,
1316 substs: ty::ItemSubsts) {
1317 let ty = ty.subst(self.tcx(), &substs.substs);
1318 self.write_ty(node_id, ty);
1319 self.write_substs(node_id, substs);
1322 pub fn write_autoderef_adjustment(&self,
1323 node_id: ast::NodeId,
1325 if derefs == 0 { return; }
1326 self.write_adjustment(
1328 ty::AutoDerefRef(ty::AutoDerefRef {
1334 pub fn write_adjustment(&self,
1335 node_id: ast::NodeId,
1336 adj: ty::AutoAdjustment) {
1337 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1338 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1341 pub fn write_nil(&self, node_id: ast::NodeId) {
1342 self.write_ty(node_id, ty::mk_nil());
1344 pub fn write_bot(&self, node_id: ast::NodeId) {
1345 self.write_ty(node_id, ty::mk_bot());
1347 pub fn write_error(&self, node_id: ast::NodeId) {
1348 self.write_ty(node_id, ty::mk_err());
1351 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1352 ast_ty_to_ty(self, self.infcx(), ast_t)
1355 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1356 pat.repr(self.tcx())
1359 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1360 match self.inh.node_types.borrow().find(&ex.id) {
1363 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1364 self.tag()).as_slice());
1369 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1370 match self.inh.node_types.borrow().find(&id) {
1373 self.tcx().sess.bug(
1374 format!("no type for node {}: {} in fcx {}",
1375 id, self.tcx().map.node_to_string(id),
1376 self.tag()).as_slice());
1381 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1382 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1383 Some(method) => method.substs.clone(),
1385 self.tcx().sess.bug(
1386 format!("no method entry for node {}: {} in fcx {}",
1387 id, self.tcx().map.node_to_string(id),
1388 self.tag()).as_slice());
1393 pub fn opt_node_ty_substs(&self,
1395 f: |&ty::ItemSubsts|) {
1396 match self.inh.item_substs.borrow().find(&id) {
1402 pub fn mk_subty(&self,
1403 a_is_expected: bool,
1404 origin: infer::TypeOrigin,
1407 -> Result<(), ty::type_err> {
1408 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1411 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1412 -> Result<(), ty::type_err> {
1413 infer::can_mk_subty(self.infcx(), sub, sup)
1416 pub fn mk_assignty(&self,
1420 -> Result<(), ty::type_err> {
1421 match infer::mk_coercety(self.infcx(),
1423 infer::ExprAssignable(expr.span),
1427 Err(ref e) => Err((*e)),
1428 Ok(Some(adjustment)) => {
1429 self.write_adjustment(expr.id, adjustment);
1435 pub fn mk_eqty(&self,
1436 a_is_expected: bool,
1437 origin: infer::TypeOrigin,
1440 -> Result<(), ty::type_err> {
1441 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1444 pub fn mk_subr(&self,
1445 a_is_expected: bool,
1446 origin: infer::SubregionOrigin,
1449 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1452 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1453 let old_region_lb = self.region_lb.get();
1454 self.region_lb.set(lb);
1456 self.region_lb.set(old_region_lb);
1460 pub fn type_error_message(&self,
1462 mk_msg: |String| -> String,
1464 err: Option<&ty::type_err>) {
1465 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1468 pub fn report_mismatched_return_types(&self,
1472 err: &ty::type_err) {
1474 if ty::type_is_error(e) || ty::type_is_error(a) {
1477 self.infcx().report_mismatched_types(sp, e, a, err)
1480 pub fn report_mismatched_types(&self,
1484 err: &ty::type_err) {
1485 self.infcx().report_mismatched_types(sp, e, a, err)
1489 pub enum LvaluePreference {
1494 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1495 expr_id: Option<ast::NodeId>,
1496 mut lvalue_pref: LvaluePreference,
1497 should_stop: |ty::t, uint| -> Option<T>)
1498 -> (ty::t, uint, Option<T>) {
1500 * Executes an autoderef loop for the type `t`. At each step, invokes
1501 * `should_stop` to decide whether to terminate the loop. Returns
1502 * the final type and number of derefs that it performed.
1504 * Note: this method does not modify the adjustments table. The caller is
1505 * responsible for inserting an AutoAdjustment record into the `fcx`
1506 * using one of the suitable methods.
1509 let mut t = base_ty;
1510 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1511 let resolved_t = structurally_resolved_type(fcx, sp, t);
1513 match should_stop(resolved_t, autoderefs) {
1514 Some(x) => return (resolved_t, autoderefs, Some(x)),
1518 // Otherwise, deref if type is derefable:
1519 let mt = match ty::deref(resolved_t, false) {
1520 Some(mt) => Some(mt),
1522 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1523 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1529 if mt.mutbl == ast::MutImmutable {
1530 lvalue_pref = NoPreference;
1533 None => return (resolved_t, autoderefs, None)
1537 // We've reached the recursion limit, error gracefully.
1538 fcx.tcx().sess.span_err(sp,
1539 format!("reached the recursion limit while auto-dereferencing {}",
1540 base_ty.repr(fcx.tcx())).as_slice());
1541 (ty::mk_err(), 0, None)
1544 /// Attempts to resolve a call expression as an overloaded call.
1545 fn try_overloaded_call(fcx: &FnCtxt,
1546 call_expression: &ast::Expr,
1547 callee: Gc<ast::Expr>,
1549 args: &[Gc<ast::Expr>])
1551 // Try `FnOnce`, then `FnMut`, then `Fn`.
1552 for &(maybe_function_trait, method_name) in [
1553 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1554 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1555 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1557 let function_trait = match maybe_function_trait {
1559 Some(function_trait) => function_trait,
1561 let method_callee = match method::lookup_in_trait(
1563 call_expression.span,
1569 DontAutoderefReceiver,
1570 IgnoreStaticMethods) {
1572 Some(method_callee) => method_callee,
1574 let method_call = MethodCall::expr(call_expression.id);
1575 let output_type = check_method_argument_types(fcx,
1576 call_expression.span,
1582 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1583 write_call(fcx, call_expression, output_type);
1585 if !fcx.tcx().sess.features.overloaded_calls.get() {
1586 fcx.tcx().sess.span_err(call_expression.span,
1587 "overloaded calls are experimental");
1588 fcx.tcx().sess.span_note(call_expression.span,
1589 "add `#[feature(overloaded_calls)]` to \
1590 the crate attributes to enable");
1599 fn try_overloaded_deref(fcx: &FnCtxt,
1601 method_call: Option<MethodCall>,
1602 base_expr: Option<&ast::Expr>,
1604 lvalue_pref: LvaluePreference)
1606 // Try DerefMut first, if preferred.
1607 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1608 (PreferMutLvalue, Some(trait_did)) => {
1609 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1610 token::intern("deref_mut"), trait_did,
1611 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1616 // Otherwise, fall back to Deref.
1617 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1618 (None, Some(trait_did)) => {
1619 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1620 token::intern("deref"), trait_did,
1621 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1623 (method, _) => method
1628 let ref_ty = ty::ty_fn_ret(method.ty);
1630 Some(method_call) => {
1631 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1635 ty::deref(ref_ty, true)
1641 fn try_overloaded_index(fcx: &FnCtxt,
1642 method_call: Option<MethodCall>,
1644 base_expr: Gc<ast::Expr>,
1646 index_expr: Gc<ast::Expr>,
1647 lvalue_pref: LvaluePreference)
1649 // Try `IndexMut` first, if preferred.
1650 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1651 (PreferMutLvalue, Some(trait_did)) => {
1652 method::lookup_in_trait(fcx,
1655 token::intern("index_mut"),
1659 DontAutoderefReceiver,
1660 IgnoreStaticMethods)
1665 // Otherwise, fall back to `Index`.
1666 let method = match (method, fcx.tcx().lang_items.index_trait()) {
1667 (None, Some(trait_did)) => {
1668 method::lookup_in_trait(fcx,
1671 token::intern("index"),
1675 DontAutoderefReceiver,
1676 IgnoreStaticMethods)
1678 (method, _) => method,
1681 // Regardless of whether the lookup succeeds, check the method arguments
1682 // so that we have *some* type for each argument.
1683 let method_type = match method {
1684 Some(ref method) => method.ty,
1685 None => ty::mk_err()
1687 check_method_argument_types(fcx,
1691 [base_expr, index_expr],
1693 DontTupleArguments);
1697 let ref_ty = ty::ty_fn_ret(method.ty);
1699 Some(method_call) => {
1700 fcx.inh.method_map.borrow_mut().insert(method_call,
1705 ty::deref(ref_ty, true)
1711 fn check_method_argument_types(fcx: &FnCtxt,
1713 method_fn_ty: ty::t,
1714 callee_expr: &ast::Expr,
1715 args: &[Gc<ast::Expr>],
1716 deref_args: DerefArgs,
1717 tuple_arguments: TupleArgumentsFlag)
1719 // HACK(eddyb) ignore provided self (it has special typeck rules).
1720 let args = if tuple_arguments == DontTupleArguments {
1725 if ty::type_is_error(method_fn_ty) {
1726 let err_inputs = err_args(args.len());
1727 check_argument_types(fcx,
1729 err_inputs.as_slice(),
1737 match ty::get(method_fn_ty).sty {
1738 ty::ty_bare_fn(ref fty) => {
1739 // HACK(eddyb) ignore self in the definition (see above).
1740 check_argument_types(fcx,
1742 fty.sig.inputs.slice_from(1),
1751 fcx.tcx().sess.span_bug(callee_expr.span,
1752 "method without bare fn type");
1758 fn check_argument_types(fcx: &FnCtxt,
1760 fn_inputs: &[ty::t],
1761 callee_expr: &ast::Expr,
1762 args: &[Gc<ast::Expr>],
1763 deref_args: DerefArgs,
1765 tuple_arguments: TupleArgumentsFlag) {
1768 * Generic function that factors out common logic from
1769 * function calls, method calls and overloaded operators.
1772 let tcx = fcx.ccx.tcx;
1774 // Grab the argument types, supplying fresh type variables
1775 // if the wrong number of arguments were supplied
1776 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1782 let expected_arg_count = fn_inputs.len();
1783 let formal_tys = if tuple_arguments == TupleArguments {
1784 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1785 match ty::get(tuple_type).sty {
1786 ty::ty_tup(ref arg_types) => {
1787 if arg_types.len() != args.len() {
1789 "this function takes {} parameter{} \
1790 but {} parameter{} supplied",
1792 if arg_types.len() == 1 {""} else {"s"},
1794 if args.len() == 1 {" was"} else {"s were"});
1795 tcx.sess.span_err(sp, msg.as_slice());
1796 err_args(args.len())
1798 (*arg_types).clone()
1802 if args.len() != 0 {
1804 "this function takes 0 parameters \
1805 but {} parameter{} supplied",
1807 if args.len() == 1 {" was"} else {"s were"});
1808 tcx.sess.span_err(sp, msg.as_slice());
1815 "cannot use call notation; the first type \
1816 parameter for the function trait is neither a \
1818 err_args(supplied_arg_count)
1821 } else if expected_arg_count == supplied_arg_count {
1822 fn_inputs.iter().map(|a| *a).collect()
1823 } else if variadic {
1824 if supplied_arg_count >= expected_arg_count {
1825 fn_inputs.iter().map(|a| *a).collect()
1828 "this function takes at least {} parameter{} \
1829 but {} parameter{} supplied",
1831 if expected_arg_count == 1 {""} else {"s"},
1833 if supplied_arg_count == 1 {" was"} else {"s were"});
1835 tcx.sess.span_err(sp, msg.as_slice());
1837 err_args(supplied_arg_count)
1841 "this function takes {} parameter{} \
1842 but {} parameter{} supplied",
1844 if expected_arg_count == 1 {""} else {"s"},
1846 if supplied_arg_count == 1 {" was"} else {"s were"});
1848 tcx.sess.span_err(sp, msg.as_slice());
1850 err_args(supplied_arg_count)
1853 debug!("check_argument_types: formal_tys={:?}",
1854 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
1856 // Check the arguments.
1857 // We do this in a pretty awful way: first we typecheck any arguments
1858 // that are not anonymous functions, then we typecheck the anonymous
1859 // functions. This is so that we have more information about the types
1860 // of arguments when we typecheck the functions. This isn't really the
1861 // right way to do this.
1862 let xs = [false, true];
1863 for check_blocks in xs.iter() {
1864 let check_blocks = *check_blocks;
1865 debug!("check_blocks={}", check_blocks);
1867 // More awful hacks: before we check the blocks, try to do
1868 // an "opportunistic" vtable resolution of any trait
1869 // bounds on the call.
1871 vtable::early_resolve_expr(callee_expr, fcx, true);
1874 // For variadic functions, we don't have a declared type for all of
1875 // the arguments hence we only do our usual type checking with
1876 // the arguments who's types we do know.
1877 let t = if variadic {
1879 } else if tuple_arguments == TupleArguments {
1884 for (i, arg) in args.iter().take(t).enumerate() {
1885 let is_block = match arg.node {
1886 ast::ExprFnBlock(..) |
1887 ast::ExprProc(..) => true,
1891 if is_block == check_blocks {
1892 debug!("checking the argument");
1893 let mut formal_ty = *formal_tys.get(i);
1897 match ty::get(formal_ty).sty {
1898 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1901 // So we hit this case when one implements the
1902 // operator traits but leaves an argument as
1903 // just T instead of &T. We'll catch it in the
1904 // mismatch impl/trait method phase no need to
1907 formal_ty = ty::mk_err();
1914 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1920 // We also need to make sure we at least write the ty of the other
1921 // arguments which we skipped above.
1923 for arg in args.iter().skip(expected_arg_count) {
1924 check_expr(fcx, &**arg);
1926 // There are a few types which get autopromoted when passed via varargs
1927 // in C but we just error out instead and require explicit casts.
1928 let arg_ty = structurally_resolved_type(fcx, arg.span,
1929 fcx.expr_ty(&**arg));
1930 match ty::get(arg_ty).sty {
1931 ty::ty_float(ast::TyF32) => {
1932 fcx.type_error_message(arg.span,
1934 format!("can't pass an {} to variadic \
1935 function, cast to c_double", t)
1938 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1939 fcx.type_error_message(arg.span, |t| {
1940 format!("can't pass {} to variadic \
1941 function, cast to c_int",
1945 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1946 fcx.type_error_message(arg.span, |t| {
1947 format!("can't pass {} to variadic \
1948 function, cast to c_uint",
1958 fn err_args(len: uint) -> Vec<ty::t> {
1959 Vec::from_fn(len, |_| ty::mk_err())
1962 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1963 fcx.write_ty(call_expr.id, output);
1966 // AST fragment checking
1967 fn check_lit(fcx: &FnCtxt,
1969 expected: Expectation)
1972 let tcx = fcx.ccx.tcx;
1975 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1976 ast::LitBinary(..) => {
1977 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1979 ast::LitByte(_) => ty::mk_u8(),
1980 ast::LitChar(_) => ty::mk_char(),
1981 ast::LitInt(_, t) => ty::mk_mach_int(t),
1982 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1983 ast::LitIntUnsuffixed(_) => {
1984 let opt_ty = expected.map_to_option(fcx, |sty| {
1986 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1987 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1988 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1989 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1990 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1994 opt_ty.unwrap_or_else(
1995 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1997 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1998 ast::LitFloatUnsuffixed(_) => {
1999 let opt_ty = expected.map_to_option(fcx, |sty| {
2001 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2005 opt_ty.unwrap_or_else(
2006 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2008 ast::LitNil => ty::mk_nil(),
2009 ast::LitBool(_) => ty::mk_bool()
2013 pub fn valid_range_bounds(ccx: &CrateCtxt,
2017 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2018 Some(val) => Some(val <= 0),
2023 pub fn check_expr_has_type(fcx: &FnCtxt,
2026 check_expr_with_unifier(
2027 fcx, expr, ExpectHasType(expected), NoPreference,
2028 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2031 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2034 check_expr_with_unifier(
2035 fcx, expr, ExpectHasType(expected), NoPreference,
2036 || demand::coerce(fcx, expr.span, expected, expr));
2039 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2040 check_expr_with_unifier(
2041 fcx, expr, ExpectHasType(expected), NoPreference,
2045 fn check_expr_with_expectation(fcx: &FnCtxt,
2047 expected: Expectation) {
2048 check_expr_with_unifier(
2049 fcx, expr, expected, NoPreference,
2053 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2055 expected: Expectation,
2056 lvalue_pref: LvaluePreference)
2058 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2061 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2062 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2065 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2066 lvalue_pref: LvaluePreference) {
2067 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2071 // determine the `self` type, using fresh variables for all variables
2072 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2073 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2075 pub fn impl_self_ty(vcx: &VtableContext,
2076 span: Span, // (potential) receiver for this impl
2079 let tcx = vcx.tcx();
2081 let ity = ty::lookup_item_type(tcx, did);
2082 let (n_tps, rps, raw_ty) =
2083 (ity.generics.types.len(subst::TypeSpace),
2084 ity.generics.regions.get_slice(subst::TypeSpace),
2087 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2088 let tps = vcx.infcx.next_ty_vars(n_tps);
2089 let substs = subst::Substs::new_type(tps, rps);
2090 let substd_ty = raw_ty.subst(tcx, &substs);
2092 TypeAndSubsts { substs: substs, ty: substd_ty }
2095 // Only for fields! Returns <none> for methods>
2096 // Indifferent to privacy flags
2097 pub fn lookup_field_ty(tcx: &ty::ctxt,
2098 class_id: ast::DefId,
2099 items: &[ty::field_ty],
2100 fieldname: ast::Name,
2101 substs: &subst::Substs) -> Option<ty::t> {
2103 let o_field = items.iter().find(|f| f.name == fieldname);
2104 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2107 // Controls whether the arguments are automatically referenced. This is useful
2108 // for overloaded binary and unary operators.
2109 pub enum DerefArgs {
2114 /// Controls whether the arguments are tupled. This is used for the call
2117 /// Tupling means that all call-side arguments are packed into a tuple and
2118 /// passed as a single parameter. For example, if tupling is enabled, this
2121 /// fn f(x: (int, int))
2123 /// Can be called as:
2130 #[deriving(Clone, Eq, PartialEq)]
2131 enum TupleArgumentsFlag {
2137 /// If an expression has any sub-expressions that result in a type error,
2138 /// inspecting that expression's type with `ty::type_is_error` will return
2139 /// true. Likewise, if an expression is known to diverge, inspecting its
2140 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2141 /// strict, _|_ can appear in the type of an expression that does not,
2142 /// itself, diverge: for example, fn() -> _|_.)
2143 /// Note that inspecting a type's structure *directly* may expose the fact
2144 /// that there are actually multiple representations for both `ty_err` and
2145 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2146 fn check_expr_with_unifier(fcx: &FnCtxt,
2148 expected: Expectation,
2149 lvalue_pref: LvaluePreference,
2152 debug!(">> typechecking");
2154 // A generic function for doing all of the checking for call expressions
2155 fn check_call(fcx: &FnCtxt,
2156 call_expr: &ast::Expr,
2158 args: &[Gc<ast::Expr>]) {
2159 // Store the type of `f` as the type of the callee
2160 let fn_ty = fcx.expr_ty(f);
2162 // Extract the function signature from `in_fty`.
2163 let fn_sty = structure_of(fcx, f.span, fn_ty);
2165 // This is the "default" function signature, used in case of error.
2166 // In that case, we check each argument against "error" in order to
2167 // set up all the node type bindings.
2168 let error_fn_sig = FnSig {
2169 binder_id: ast::CRATE_NODE_ID,
2170 inputs: err_args(args.len()),
2171 output: ty::mk_err(),
2175 let fn_sig = match *fn_sty {
2176 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2177 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2179 fcx.type_error_message(call_expr.span, |actual| {
2180 format!("expected function but found `{}`", actual)
2186 // Replace any bound regions that appear in the function
2187 // signature with region variables
2188 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2189 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2192 // Call the generic checker.
2193 check_argument_types(fcx,
2195 fn_sig.inputs.as_slice(),
2200 DontTupleArguments);
2202 write_call(fcx, call_expr, fn_sig.output);
2205 // Checks a method call.
2206 fn check_method_call(fcx: &FnCtxt,
2208 method_name: ast::SpannedIdent,
2209 args: &[Gc<ast::Expr>],
2210 tps: &[ast::P<ast::Ty>]) {
2211 let rcvr = args[0].clone();
2212 // We can't know if we need &mut self before we look up the method,
2213 // so treat the receiver as mutable just in case - only explicit
2214 // overloaded dereferences care about the distinction.
2215 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2217 // no need to check for bot/err -- callee does that
2218 let expr_t = structurally_resolved_type(fcx,
2220 fcx.expr_ty(&*rcvr));
2222 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2223 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2224 method_name.node.name,
2225 expr_t, tps.as_slice(),
2227 CheckTraitsAndInherentMethods,
2228 AutoderefReceiver, IgnoreStaticMethods) {
2230 let method_ty = method.ty;
2231 let method_call = MethodCall::expr(expr.id);
2232 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2236 debug!("(checking method call) failing expr is {}", expr.id);
2238 fcx.type_error_message(method_name.span,
2240 format!("type `{}` does not implement any \
2241 method in scope named `{}`",
2243 token::get_ident(method_name.node))
2248 // Add error type for the result
2249 fcx.write_error(expr.id);
2251 // Check for potential static matches (missing self parameters)
2255 method_name.node.name,
2259 CheckTraitsAndInherentMethods,
2260 DontAutoderefReceiver,
2261 ReportStaticMethods);
2267 // Call the generic checker.
2268 let ret_ty = check_method_argument_types(fcx,
2274 DontTupleArguments);
2276 write_call(fcx, expr, ret_ty);
2279 // A generic function for checking the then and else in an if
2281 fn check_then_else(fcx: &FnCtxt,
2282 cond_expr: &ast::Expr,
2283 then_blk: &ast::Block,
2284 opt_else_expr: Option<Gc<ast::Expr>>,
2287 expected: Expectation) {
2288 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2290 let branches_ty = match opt_else_expr {
2291 Some(ref else_expr) => {
2292 // Disregard "castable to" expectations because they
2293 // can lead us astray. Consider for example `if cond
2294 // {22} else {c} as u8` -- if we propagate the
2295 // "castable to u8" constraint to 22, it will pick the
2296 // type 22u8, which is overly constrained (c might not
2297 // be a u8). In effect, the problem is that the
2298 // "castable to" expectation is not the tightest thing
2299 // we can say, so we want to drop it in this case.
2300 // The tightest thing we can say is "must unify with
2301 // else branch". Note that in the case of a "has type"
2302 // constraint, this limitation does not hold.
2303 let expected = expected.only_has_type();
2305 check_block_with_expected(fcx, then_blk, expected);
2306 let then_ty = fcx.node_ty(then_blk.id);
2307 check_expr_with_expectation(fcx, &**else_expr, expected);
2308 let else_ty = fcx.expr_ty(&**else_expr);
2309 infer::common_supertype(fcx.infcx(),
2310 infer::IfExpression(sp),
2316 check_block_no_value(fcx, then_blk);
2321 let cond_ty = fcx.expr_ty(cond_expr);
2322 let if_ty = if ty::type_is_error(cond_ty) {
2324 } else if ty::type_is_bot(cond_ty) {
2330 fcx.write_ty(id, if_ty);
2333 fn lookup_op_method(fcx: &FnCtxt,
2337 trait_did: Option<ast::DefId>,
2338 args: &[Gc<ast::Expr>],
2339 autoderef_receiver: AutoderefReceiverFlag,
2340 unbound_method: ||) -> ty::t {
2341 let method = match trait_did {
2342 Some(trait_did) => {
2343 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2344 trait_did, self_t, [], autoderef_receiver,
2345 IgnoreStaticMethods)
2351 let method_ty = method.ty;
2352 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2353 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2354 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2355 check_method_argument_types(fcx,
2365 // Check the args anyway
2366 // so we get all the error messages
2367 let expected_ty = ty::mk_err();
2368 check_method_argument_types(fcx,
2374 DontTupleArguments);
2380 // could be either an expr_binop or an expr_assign_binop
2381 fn check_binop(fcx: &FnCtxt,
2386 is_binop_assignment: IsBinopAssignment) {
2387 let tcx = fcx.ccx.tcx;
2389 let lvalue_pref = match is_binop_assignment {
2390 BinopAssignment => PreferMutLvalue,
2391 SimpleBinop => NoPreference
2393 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2395 // Callee does bot / err checking
2396 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2397 fcx.expr_ty(&*lhs));
2399 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2400 // Shift is a special case: rhs must be uint, no matter what lhs is
2401 check_expr_has_type(fcx, rhs, ty::mk_uint());
2402 fcx.write_ty(expr.id, lhs_t);
2406 if ty::is_binopable(tcx, lhs_t, op) {
2407 let tvar = fcx.infcx().next_ty_var();
2408 demand::suptype(fcx, expr.span, tvar, lhs_t);
2409 check_expr_has_type(fcx, &*rhs, tvar);
2411 let result_t = match op {
2412 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2414 if ty::type_is_simd(tcx, lhs_t) {
2415 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2416 fcx.type_error_message(expr.span,
2418 format!("binary comparison \
2419 operation `{}` not \
2420 supported for floating \
2421 point SIMD vector `{}`",
2422 ast_util::binop_to_string(op),
2439 fcx.write_ty(expr.id, result_t);
2443 if op == ast::BiOr || op == ast::BiAnd {
2444 // This is an error; one of the operands must have the wrong
2446 fcx.write_error(expr.id);
2447 fcx.write_error(rhs.id);
2448 fcx.type_error_message(expr.span,
2450 format!("binary operation `{}` cannot be applied \
2452 ast_util::binop_to_string(op),
2459 // Check for overloaded operators if not an assignment.
2460 let result_t = if is_binop_assignment == SimpleBinop {
2461 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2463 fcx.type_error_message(expr.span,
2465 format!("binary assignment \
2467 cannot be applied to \
2469 ast_util::binop_to_string(op),
2474 check_expr(fcx, &*rhs);
2478 fcx.write_ty(expr.id, result_t);
2479 if ty::type_is_error(result_t) {
2480 fcx.write_ty(rhs.id, result_t);
2484 fn check_user_binop(fcx: &FnCtxt,
2486 lhs_expr: Gc<ast::Expr>,
2487 lhs_resolved_t: ty::t,
2489 rhs: Gc<ast::Expr>) -> ty::t {
2490 let tcx = fcx.ccx.tcx;
2491 let lang = &tcx.lang_items;
2492 let (name, trait_did) = match op {
2493 ast::BiAdd => ("add", lang.add_trait()),
2494 ast::BiSub => ("sub", lang.sub_trait()),
2495 ast::BiMul => ("mul", lang.mul_trait()),
2496 ast::BiDiv => ("div", lang.div_trait()),
2497 ast::BiRem => ("rem", lang.rem_trait()),
2498 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2499 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2500 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2501 ast::BiShl => ("shl", lang.shl_trait()),
2502 ast::BiShr => ("shr", lang.shr_trait()),
2503 ast::BiLt => ("lt", lang.ord_trait()),
2504 ast::BiLe => ("le", lang.ord_trait()),
2505 ast::BiGe => ("ge", lang.ord_trait()),
2506 ast::BiGt => ("gt", lang.ord_trait()),
2507 ast::BiEq => ("eq", lang.eq_trait()),
2508 ast::BiNe => ("ne", lang.eq_trait()),
2509 ast::BiAnd | ast::BiOr => {
2510 check_expr(fcx, &*rhs);
2511 return ty::mk_err();
2514 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2515 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2516 fcx.type_error_message(ex.span, |actual| {
2517 format!("binary operation `{}` cannot be applied to type `{}`",
2518 ast_util::binop_to_string(op),
2520 }, lhs_resolved_t, None)
2524 fn check_user_unop(fcx: &FnCtxt,
2527 trait_did: Option<ast::DefId>,
2529 rhs_expr: Gc<ast::Expr>,
2530 rhs_t: ty::t) -> ty::t {
2531 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2532 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2533 fcx.type_error_message(ex.span, |actual| {
2534 format!("cannot apply unary operator `{}` to type `{}`",
2540 fn check_expr_fn(fcx: &FnCtxt,
2542 store: ty::TraitStore,
2544 body: ast::P<ast::Block>,
2545 expected: Expectation) {
2546 let tcx = fcx.ccx.tcx;
2548 // Find the expected input/output types (if any). Substitute
2549 // fresh bound regions for any bound regions we find in the
2550 // expected types so as to avoid capture.
2551 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2554 expected_bounds) = {
2555 match expected_sty {
2556 Some(ty::ty_closure(ref cenv)) => {
2558 replace_late_bound_regions_in_fn_sig(
2560 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2561 let onceness = match (&store, &cenv.store) {
2562 // As the closure type and onceness go, only three
2563 // combinations are legit:
2567 // If the actual and expected closure type disagree with
2568 // each other, set expected onceness to be always Once or
2569 // Many according to the actual type. Otherwise, it will
2570 // yield either an illegal "many proc" or a less known
2571 // "once closure" in the error message.
2572 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2573 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2575 (&ty::UniqTraitStore, _) => ast::Once,
2576 (&ty::RegionTraitStore(..), _) => ast::Many,
2578 (Some(sig), onceness, cenv.bounds)
2581 // Not an error! Means we're inferring the closure type
2582 let mut bounds = ty::empty_builtin_bounds();
2583 let onceness = match expr.node {
2584 ast::ExprProc(..) => {
2585 bounds.add(ty::BoundSend);
2590 (None, onceness, bounds)
2595 // construct the function type
2596 let fn_ty = astconv::ty_of_closure(fcx,
2604 let fty_sig = fn_ty.sig.clone();
2605 let fty = ty::mk_closure(tcx, fn_ty);
2606 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
2608 fcx.write_ty(expr.id, fty);
2610 // If the closure is a stack closure and hasn't had some non-standard
2611 // style inferred for it, then check it under its parent's style.
2612 // Otherwise, use its own
2613 let (inherited_style, id) = match store {
2614 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2615 fcx.ps.borrow().def),
2616 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2619 check_fn(fcx.ccx, inherited_style, &fty_sig,
2620 &*decl, id, &*body, fcx.inh);
2624 // Check field access expressions
2625 fn check_field(fcx: &FnCtxt,
2627 lvalue_pref: LvaluePreference,
2629 field: &ast::SpannedIdent,
2630 tys: &[ast::P<ast::Ty>]) {
2631 let tcx = fcx.ccx.tcx;
2632 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2633 let expr_t = structurally_resolved_type(fcx, expr.span,
2635 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2636 let (_, autoderefs, field_ty) =
2637 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2638 match ty::get(base_t).sty {
2639 ty::ty_struct(base_id, ref substs) => {
2640 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2641 let fields = ty::lookup_struct_fields(tcx, base_id);
2642 lookup_field_ty(tcx, base_id, fields.as_slice(),
2643 field.node.name, &(*substs))
2650 fcx.write_ty(expr.id, field_ty);
2651 fcx.write_autoderef_adjustment(base.id, autoderefs);
2657 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2658 match method::lookup(fcx,
2665 CheckTraitsAndInherentMethods,
2667 IgnoreStaticMethods) {
2669 fcx.type_error_message(
2672 format!("attempted to take value of method `{}` on type \
2673 `{}`", token::get_ident(field.node), actual)
2677 tcx.sess.span_note(field.span,
2678 "maybe a missing `()` to call it? If not, try an anonymous function.");
2682 fcx.type_error_message(
2685 format!("attempted access of field `{}` on \
2686 type `{}`, but no field with that \
2688 token::get_ident(field.node),
2695 fcx.write_error(expr.id);
2698 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2701 class_id: ast::DefId,
2702 node_id: ast::NodeId,
2703 substitutions: subst::Substs,
2704 field_types: &[ty::field_ty],
2705 ast_fields: &[ast::Field],
2706 check_completeness: bool) {
2707 let tcx = fcx.ccx.tcx;
2709 let mut class_field_map = HashMap::new();
2710 let mut fields_found = 0;
2711 for field in field_types.iter() {
2712 class_field_map.insert(field.name, (field.id, false));
2715 let mut error_happened = false;
2717 // Typecheck each field.
2718 for field in ast_fields.iter() {
2719 let mut expected_field_type = ty::mk_err();
2721 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2724 fcx.type_error_message(
2727 format!("structure `{}` has no field named `{}`",
2728 actual, token::get_ident(field.ident.node))
2732 error_happened = true;
2734 Some((_, true)) => {
2737 format!("field `{}` specified more than once",
2738 token::get_ident(field.ident
2739 .node)).as_slice());
2740 error_happened = true;
2742 Some((field_id, false)) => {
2743 expected_field_type =
2744 ty::lookup_field_type(
2745 tcx, class_id, field_id, &substitutions);
2746 class_field_map.insert(
2747 field.ident.node.name, (field_id, true));
2751 // Make sure to give a type to the field even if there's
2752 // an error, so we can continue typechecking
2753 check_expr_coercable_to_type(
2756 expected_field_type);
2760 fcx.write_error(node_id);
2763 if check_completeness && !error_happened {
2764 // Make sure the programmer specified all the fields.
2765 assert!(fields_found <= field_types.len());
2766 if fields_found < field_types.len() {
2767 let mut missing_fields = Vec::new();
2768 for class_field in field_types.iter() {
2769 let name = class_field.name;
2770 let (_, seen) = *class_field_map.get(&name);
2772 missing_fields.push(
2773 format!("`{}`", token::get_name(name).get()))
2777 tcx.sess.span_err(span,
2779 "missing field{}: {fields}",
2780 if missing_fields.len() == 1 {""} else {"s"},
2781 fields = missing_fields.connect(", ")).as_slice());
2785 if !error_happened {
2786 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2787 class_id, substitutions));
2791 fn check_struct_constructor(fcx: &FnCtxt,
2793 span: codemap::Span,
2794 class_id: ast::DefId,
2795 fields: &[ast::Field],
2796 base_expr: Option<Gc<ast::Expr>>) {
2797 let tcx = fcx.ccx.tcx;
2799 // Look up the number of type parameters and the raw type, and
2800 // determine whether the class is region-parameterized.
2801 let item_type = ty::lookup_item_type(tcx, class_id);
2802 let raw_type = item_type.ty;
2804 // Generate the struct type.
2805 let substitutions = fcx.infcx().fresh_substs_for_type(
2806 span, &item_type.generics);
2807 let mut struct_type = raw_type.subst(tcx, &substitutions);
2809 // Look up and check the fields.
2810 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2811 check_struct_or_variant_fields(fcx,
2817 class_fields.as_slice(),
2819 base_expr.is_none());
2820 if ty::type_is_error(fcx.node_ty(id)) {
2821 struct_type = ty::mk_err();
2824 // Check the base expression if necessary.
2827 Some(base_expr) => {
2828 check_expr_has_type(fcx, &*base_expr, struct_type);
2829 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2830 struct_type = ty::mk_bot();
2835 // Write in the resulting type.
2836 fcx.write_ty(id, struct_type);
2839 fn check_struct_enum_variant(fcx: &FnCtxt,
2841 span: codemap::Span,
2842 enum_id: ast::DefId,
2843 variant_id: ast::DefId,
2844 fields: &[ast::Field]) {
2845 let tcx = fcx.ccx.tcx;
2847 // Look up the number of type parameters and the raw type, and
2848 // determine whether the enum is region-parameterized.
2849 let item_type = ty::lookup_item_type(tcx, enum_id);
2850 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2851 let enum_type = item_type.ty.subst(tcx, &substitutions);
2853 // Look up and check the enum variant fields.
2854 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2855 check_struct_or_variant_fields(fcx,
2861 variant_fields.as_slice(),
2864 fcx.write_ty(id, enum_type);
2867 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2869 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2870 expected: Expectation)
2871 -> (ExprCheckerWithTy, ty::t) {
2872 let tcx = fcx.ccx.tcx;
2873 let (coerce, t) = match expected {
2874 // If we're given an expected type, we can try to coerce to it
2875 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2876 // Otherwise we just leave the type to be resolved later
2877 _ => (false, fcx.infcx().next_ty_var())
2880 (check_expr_coercable_to_type, t)
2882 (check_expr_has_type, t)
2886 let tcx = fcx.ccx.tcx;
2889 ast::ExprVstore(ev, vst) => {
2890 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2891 let typ = match ev.node {
2892 ast::ExprVec(ref args) => {
2893 let mutability = match vst {
2894 ast::ExprVstoreMutSlice => ast::MutMutable,
2895 _ => ast::MutImmutable,
2897 let mut any_error = false;
2898 let mut any_bot = false;
2899 for e in args.iter() {
2900 check(fcx, &**e, t);
2901 let arg_t = fcx.expr_ty(&**e);
2902 if ty::type_is_error(arg_t) {
2905 else if ty::type_is_bot(arg_t) {
2914 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2915 ty::mt{ ty: ty::mk_vec(tcx,
2916 ty::mt {ty: t, mutbl: mutability},
2918 mutbl: mutability })
2921 ast::ExprRepeat(ref element, ref count_expr) => {
2922 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2923 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2924 let mutability = match vst {
2925 ast::ExprVstoreMutSlice => ast::MutMutable,
2926 _ => ast::MutImmutable,
2928 check(fcx, &**element, t);
2929 let arg_t = fcx.expr_ty(&**element);
2930 if ty::type_is_error(arg_t) {
2932 } else if ty::type_is_bot(arg_t) {
2935 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2936 ty::mt{ ty: ty::mk_vec(tcx,
2937 ty::mt {ty: t, mutbl: mutability},
2942 ast::ExprLit(_) => {
2943 let error = if vst == ast::ExprVstoreSlice {
2944 "`&\"string\"` has been removed; use `\"string\"` instead"
2946 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2948 tcx.sess.span_err(expr.span, error);
2951 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2953 fcx.write_ty(ev.id, typ);
2954 fcx.write_ty(id, typ);
2957 ast::ExprBox(ref place, ref subexpr) => {
2958 check_expr(fcx, &**place);
2959 check_expr(fcx, &**subexpr);
2961 let mut checked = false;
2963 ast::ExprPath(ref path) => {
2964 // FIXME(pcwalton): For now we hardcode the two permissible
2965 // places: the exchange heap and the managed heap.
2966 let definition = lookup_def(fcx, path.span, place.id);
2967 let def_id = definition.def_id();
2968 if tcx.lang_items.exchange_heap() == Some(def_id) {
2969 fcx.write_ty(id, ty::mk_uniq(tcx,
2970 fcx.expr_ty(&**subexpr)));
2972 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2973 fcx.write_ty(id, ty::mk_box(tcx,
2974 fcx.expr_ty(&**subexpr)));
2982 tcx.sess.span_err(expr.span,
2983 "only the managed heap and exchange heap are \
2984 currently supported");
2985 fcx.write_ty(id, ty::mk_err());
2989 ast::ExprLit(lit) => {
2990 let typ = check_lit(fcx, lit, expected);
2991 fcx.write_ty(id, typ);
2993 ast::ExprBinary(op, ref lhs, ref rhs) => {
2994 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2996 let lhs_ty = fcx.expr_ty(&**lhs);
2997 let rhs_ty = fcx.expr_ty(&**rhs);
2998 if ty::type_is_error(lhs_ty) ||
2999 ty::type_is_error(rhs_ty) {
3000 fcx.write_error(id);
3002 else if ty::type_is_bot(lhs_ty) ||
3003 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3007 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3008 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3010 let lhs_t = fcx.expr_ty(&**lhs);
3011 let result_t = fcx.expr_ty(expr);
3012 demand::suptype(fcx, expr.span, result_t, lhs_t);
3014 let tcx = fcx.tcx();
3015 if !ty::expr_is_lval(tcx, &**lhs) {
3016 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3019 // Overwrite result of check_binop...this preserves existing behavior
3020 // but seems quite dubious with regard to user-defined methods
3021 // and so forth. - Niko
3022 if !ty::type_is_error(result_t)
3023 && !ty::type_is_bot(result_t) {
3024 fcx.write_nil(expr.id);
3027 ast::ExprUnary(unop, ref oprnd) => {
3028 let expected = expected.only_has_type();
3029 let expected_inner = expected.map(fcx, |sty| {
3031 ast::UnBox | ast::UnUniq => match *sty {
3032 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3039 ast::UnNot | ast::UnNeg => {
3047 let lvalue_pref = match unop {
3048 ast::UnDeref => lvalue_pref,
3051 check_expr_with_expectation_and_lvalue_pref(
3052 fcx, &**oprnd, expected_inner, lvalue_pref);
3053 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3054 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3057 oprnd_t = ty::mk_box(tcx, oprnd_t)
3060 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3063 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3064 oprnd_t = match ty::deref(oprnd_t, true) {
3066 None => match try_overloaded_deref(fcx, expr.span,
3067 Some(MethodCall::expr(expr.id)),
3068 Some(&**oprnd), oprnd_t, lvalue_pref) {
3071 let is_newtype = match ty::get(oprnd_t).sty {
3072 ty::ty_struct(did, ref substs) => {
3073 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3075 && fields.get(0).ident ==
3076 token::special_idents::unnamed_field
3081 // This is an obsolete struct deref
3082 tcx.sess.span_err(expr.span,
3083 "single-field tuple-structs can \
3084 no longer be dereferenced");
3086 fcx.type_error_message(expr.span, |actual| {
3087 format!("type `{}` cannot be \
3088 dereferenced", actual)
3097 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3099 if !(ty::type_is_integral(oprnd_t) ||
3100 ty::get(oprnd_t).sty == ty::ty_bool) {
3101 oprnd_t = check_user_unop(fcx, "!", "not",
3102 tcx.lang_items.not_trait(),
3103 expr, oprnd.clone(), oprnd_t);
3107 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3109 if !(ty::type_is_integral(oprnd_t) ||
3110 ty::type_is_fp(oprnd_t)) {
3111 oprnd_t = check_user_unop(fcx, "-", "neg",
3112 tcx.lang_items.neg_trait(),
3113 expr, oprnd.clone(), oprnd_t);
3118 fcx.write_ty(id, oprnd_t);
3120 ast::ExprAddrOf(mutbl, ref oprnd) => {
3121 let expected = expected.only_has_type();
3122 let hint = expected.map(fcx, |sty| {
3123 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3124 _ => NoExpectation }
3126 let lvalue_pref = match mutbl {
3127 ast::MutMutable => PreferMutLvalue,
3128 ast::MutImmutable => NoPreference
3130 check_expr_with_expectation_and_lvalue_pref(fcx,
3135 // Note: at this point, we cannot say what the best lifetime
3136 // is to use for resulting pointer. We want to use the
3137 // shortest lifetime possible so as to avoid spurious borrowck
3138 // errors. Moreover, the longest lifetime will depend on the
3139 // precise details of the value whose address is being taken
3140 // (and how long it is valid), which we don't know yet until type
3141 // inference is complete.
3143 // Therefore, here we simply generate a region variable. The
3144 // region inferencer will then select the ultimate value.
3145 // Finally, borrowck is charged with guaranteeing that the
3146 // value whose address was taken can actually be made to live
3147 // as long as it needs to live.
3148 let region = fcx.infcx().next_region_var(
3149 infer::AddrOfRegion(expr.span));
3151 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3152 let oprnd_t = if ty::type_is_error(tm.ty) {
3154 } else if ty::type_is_bot(tm.ty) {
3158 ty::mk_rptr(tcx, region, tm)
3160 fcx.write_ty(id, oprnd_t);
3162 ast::ExprPath(ref pth) => {
3163 let defn = lookup_def(fcx, pth.span, id);
3164 let pty = polytype_for_def(fcx, expr.span, defn);
3165 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3167 ast::ExprInlineAsm(ref ia) => {
3168 for &(_, ref input) in ia.inputs.iter() {
3169 check_expr(fcx, &**input);
3171 for &(_, ref out) in ia.outputs.iter() {
3172 check_expr(fcx, &**out);
3176 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3177 ast::ExprBreak(_) => { fcx.write_bot(id); }
3178 ast::ExprAgain(_) => { fcx.write_bot(id); }
3179 ast::ExprRet(ref expr_opt) => {
3180 let ret_ty = fcx.ret_ty;
3182 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3183 ret_ty, ty::mk_nil()) {
3184 Ok(_) => { /* fall through */ }
3188 "`return;` in function returning non-nil");
3192 check_expr_has_type(fcx, &**e, ret_ty);
3197 ast::ExprParen(a) => {
3198 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3199 fcx.write_ty(id, fcx.expr_ty(a));
3201 ast::ExprAssign(ref lhs, ref rhs) => {
3202 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3204 let tcx = fcx.tcx();
3205 if !ty::expr_is_lval(tcx, &**lhs) {
3206 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3209 let lhs_ty = fcx.expr_ty(&**lhs);
3210 check_expr_has_type(fcx, &**rhs, lhs_ty);
3211 let rhs_ty = fcx.expr_ty(&**rhs);
3213 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3214 fcx.write_error(id);
3215 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3221 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3222 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3223 id, expr.span, expected);
3225 ast::ExprWhile(ref cond, ref body) => {
3226 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3227 check_block_no_value(fcx, &**body);
3228 let cond_ty = fcx.expr_ty(&**cond);
3229 let body_ty = fcx.node_ty(body.id);
3230 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3231 fcx.write_error(id);
3233 else if ty::type_is_bot(cond_ty) {
3240 ast::ExprForLoop(..) =>
3241 fail!("non-desugared expr_for_loop"),
3242 ast::ExprLoop(ref body, _) => {
3243 check_block_no_value(fcx, &**body);
3244 if !may_break(tcx, expr.id, body.clone()) {
3251 ast::ExprMatch(ref discrim, ref arms) => {
3252 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3254 ast::ExprFnBlock(ref decl, ref body) => {
3255 let region = astconv::opt_ast_region_to_region(fcx,
3261 ty::RegionTraitStore(region, ast::MutMutable),
3266 ast::ExprProc(ref decl, ref body) => {
3274 ast::ExprBlock(ref b) => {
3275 check_block_with_expected(fcx, &**b, expected);
3276 fcx.write_ty(id, fcx.node_ty(b.id));
3278 ast::ExprCall(ref f, ref args) => {
3279 // Index expressions need to be handled separately, to inform them
3280 // that they appear in call position.
3281 check_expr(fcx, &**f);
3282 let f_ty = fcx.expr_ty(&**f);
3284 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3285 check_call(fcx, expr, &**f, args.as_slice());
3286 let (args_bot, args_err) = args.iter().fold((false, false),
3287 |(rest_bot, rest_err), a| {
3288 // is this not working?
3289 let a_ty = fcx.expr_ty(&**a);
3290 (rest_bot || ty::type_is_bot(a_ty),
3291 rest_err || ty::type_is_error(a_ty))});
3292 if ty::type_is_error(f_ty) || args_err {
3293 fcx.write_error(id);
3295 else if ty::type_is_bot(f_ty) || args_bot {
3300 ast::ExprMethodCall(ident, ref tps, ref args) => {
3301 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3302 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3303 let (args_bot, args_err) = arg_tys.fold((false, false),
3304 |(rest_bot, rest_err), a| {
3305 (rest_bot || ty::type_is_bot(a),
3306 rest_err || ty::type_is_error(a))});
3308 fcx.write_error(id);
3309 } else if args_bot {
3313 ast::ExprCast(ref e, ref t) => {
3314 check_cast(fcx, &**e, &**t, id, expr.span);
3316 ast::ExprVec(ref args) => {
3317 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3318 for e in args.iter() {
3319 check(fcx, &**e, t);
3321 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3323 fcx.write_ty(id, typ);
3325 ast::ExprRepeat(ref element, ref count_expr) => {
3326 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3327 let count = ty::eval_repeat_count(fcx, &**count_expr);
3328 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3329 check(fcx, &**element, t);
3330 let element_ty = fcx.expr_ty(&**element);
3331 if ty::type_is_error(element_ty) {
3332 fcx.write_error(id);
3334 else if ty::type_is_bot(element_ty) {
3338 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3340 fcx.write_ty(id, t);
3343 ast::ExprTup(ref elts) => {
3344 let expected = expected.only_has_type();
3345 let flds = expected.map_to_option(fcx, |sty| {
3347 ty::ty_tup(ref flds) => Some((*flds).clone()),
3351 let mut bot_field = false;
3352 let mut err_field = false;
3354 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3355 let opt_hint = match flds {
3356 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3359 check_expr_with_expectation(fcx, *e, opt_hint);
3360 let t = fcx.expr_ty(*e);
3361 err_field = err_field || ty::type_is_error(t);
3362 bot_field = bot_field || ty::type_is_bot(t);
3367 } else if err_field {
3368 fcx.write_error(id);
3370 let typ = ty::mk_tup(tcx, elt_ts);
3371 fcx.write_ty(id, typ);
3374 ast::ExprStruct(ref path, ref fields, base_expr) => {
3375 // Resolve the path.
3376 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3378 Some(def::DefVariant(enum_id, variant_id, _)) => {
3379 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3380 variant_id, fields.as_slice());
3383 // Verify that this was actually a struct.
3384 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3385 match ty::get(typ.ty).sty {
3386 ty::ty_struct(struct_did, _) => {
3387 check_struct_constructor(fcx,
3396 .span_err(path.span,
3397 format!("`{}` does not name a structure",
3398 pprust::path_to_string(
3404 tcx.sess.span_bug(path.span,
3405 "structure constructor wasn't resolved")
3409 ast::ExprField(ref base, ref field, ref tys) => {
3410 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3412 ast::ExprIndex(ref base, ref idx) => {
3413 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3414 check_expr(fcx, &**idx);
3415 let raw_base_t = fcx.expr_ty(&**base);
3416 let idx_t = fcx.expr_ty(&**idx);
3417 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3418 fcx.write_ty(id, raw_base_t);
3419 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3420 fcx.write_ty(id, idx_t);
3422 let (_, autoderefs, field_ty) =
3423 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3424 lvalue_pref, |base_t, _| ty::index(base_t));
3427 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3428 fcx.write_ty(id, mt.ty);
3429 fcx.write_autoderef_adjustment(base.id, autoderefs);
3432 // This is an overloaded method.
3433 let base_t = structurally_resolved_type(fcx,
3436 let method_call = MethodCall::expr(expr.id);
3437 match try_overloaded_index(fcx,
3444 Some(mt) => fcx.write_ty(id, mt.ty),
3446 fcx.type_error_message(expr.span,
3456 fcx.write_ty(id, ty::mk_err())
3465 debug!("type of expr({}) {} is...", expr.id,
3466 syntax::print::pprust::expr_to_string(expr));
3467 debug!("... {}, expected is {}",
3468 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3469 expected.repr(tcx));
3475 fn only_has_type(self) -> Expectation {
3477 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3478 ExpectHasType(t) => ExpectHasType(t)
3482 // Resolves `expected` by a single level if it is a variable. If
3483 // there is no expected type or resolution is not possible (e.g.,
3484 // no constraints yet present), just returns `None`.
3485 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3490 ExpectCastableToType(t) => {
3491 ExpectCastableToType(
3492 fcx.infcx().resolve_type_vars_if_possible(t))
3494 ExpectHasType(t) => {
3496 fcx.infcx().resolve_type_vars_if_possible(t))
3501 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3502 match self.resolve(fcx) {
3503 NoExpectation => NoExpectation,
3504 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3508 fn map_to_option<O>(self,
3510 unpack: |&ty::sty| -> Option<O>)
3513 match self.resolve(fcx) {
3514 NoExpectation => None,
3515 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3520 impl Repr for Expectation {
3521 fn repr(&self, tcx: &ty::ctxt) -> String {
3523 NoExpectation => format!("NoExpectation"),
3524 ExpectHasType(t) => format!("ExpectHasType({})",
3526 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3532 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3533 if !type_is_uint(fcx, sp, t) {
3534 fcx.type_error_message(sp, |actual| {
3535 format!("mismatched types: expected `uint` type but found `{}`",
3541 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3542 if !type_is_integral(fcx, sp, t) {
3543 fcx.type_error_message(sp, |actual| {
3544 format!("mismatched types: expected integral type but found `{}`",
3550 pub fn check_decl_initializer(fcx: &FnCtxt,
3554 let local_ty = fcx.local_ty(init.span, nid);
3555 check_expr_coercable_to_type(fcx, init, local_ty)
3558 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3559 let tcx = fcx.ccx.tcx;
3561 let t = fcx.local_ty(local.span, local.id);
3562 fcx.write_ty(local.id, t);
3566 check_decl_initializer(fcx, local.id, &**init);
3567 let init_ty = fcx.expr_ty(&**init);
3568 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3569 fcx.write_ty(local.id, init_ty);
3575 let pcx = pat_ctxt {
3577 map: pat_id_map(&tcx.def_map, &*local.pat),
3579 _match::check_pat(&pcx, &*local.pat, t);
3580 let pat_ty = fcx.node_ty(local.pat.id);
3581 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3582 fcx.write_ty(local.id, pat_ty);
3586 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3588 let mut saw_bot = false;
3589 let mut saw_err = false;
3591 ast::StmtDecl(decl, id) => {
3594 ast::DeclLocal(ref l) => {
3595 check_decl_local(fcx, &**l);
3596 let l_t = fcx.node_ty(l.id);
3597 saw_bot = saw_bot || ty::type_is_bot(l_t);
3598 saw_err = saw_err || ty::type_is_error(l_t);
3600 ast::DeclItem(_) => {/* ignore for now */ }
3603 ast::StmtExpr(ref expr, id) => {
3605 // Check with expected type of ()
3606 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3607 let expr_ty = fcx.expr_ty(&**expr);
3608 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3609 saw_err = saw_err || ty::type_is_error(expr_ty);
3611 ast::StmtSemi(ref expr, id) => {
3613 check_expr(fcx, &**expr);
3614 let expr_ty = fcx.expr_ty(&**expr);
3615 saw_bot |= ty::type_is_bot(expr_ty);
3616 saw_err |= ty::type_is_error(expr_ty);
3618 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3621 fcx.write_bot(node_id);
3624 fcx.write_error(node_id);
3627 fcx.write_nil(node_id)
3631 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3632 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3633 let blkty = fcx.node_ty(blk.id);
3634 if ty::type_is_error(blkty) {
3635 fcx.write_error(blk.id);
3637 else if ty::type_is_bot(blkty) {
3638 fcx.write_bot(blk.id);
3641 let nilty = ty::mk_nil();
3642 demand::suptype(fcx, blk.span, nilty, blkty);
3646 fn check_block_with_expected(fcx: &FnCtxt,
3648 expected: Expectation) {
3650 let mut fcx_ps = fcx.ps.borrow_mut();
3651 let fn_style_state = fcx_ps.recurse(blk);
3652 replace(&mut *fcx_ps, fn_style_state)
3655 fcx.with_region_lb(blk.id, || {
3656 let mut warned = false;
3657 let mut last_was_bot = false;
3658 let mut any_bot = false;
3659 let mut any_err = false;
3660 for s in blk.stmts.iter() {
3661 check_stmt(fcx, &**s);
3662 let s_id = ast_util::stmt_id(&**s);
3663 let s_ty = fcx.node_ty(s_id);
3664 if last_was_bot && !warned && match s.node {
3665 ast::StmtDecl(decl, _) => {
3667 ast::DeclLocal(_) => true,
3671 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3677 .add_lint(lint::builtin::UNREACHABLE_CODE,
3680 "unreachable statement".to_string());
3683 if ty::type_is_bot(s_ty) {
3684 last_was_bot = true;
3686 any_bot = any_bot || ty::type_is_bot(s_ty);
3687 any_err = any_err || ty::type_is_error(s_ty);
3690 None => if any_err {
3691 fcx.write_error(blk.id);
3694 fcx.write_bot(blk.id);
3697 fcx.write_nil(blk.id);
3700 if any_bot && !warned {
3704 .add_lint(lint::builtin::UNREACHABLE_CODE,
3707 "unreachable expression".to_string());
3709 check_expr_with_expectation(fcx, e, expected);
3710 let ety = fcx.expr_ty(e);
3711 fcx.write_ty(blk.id, ety);
3713 fcx.write_error(blk.id);
3716 fcx.write_bot(blk.id);
3722 *fcx.ps.borrow_mut() = prev;
3725 pub fn check_const(ccx: &CrateCtxt,
3729 let inh = blank_inherited_fields(ccx);
3730 let rty = ty::node_id_to_type(ccx.tcx, id);
3731 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3732 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3733 check_const_with_ty(&fcx, sp, e, declty);
3736 pub fn check_const_with_ty(fcx: &FnCtxt,
3740 // Gather locals in statics (because of block expressions).
3741 // This is technically unnecessary because locals in static items are forbidden,
3742 // but prevents type checking from blowing up before const checking can properly
3744 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3747 let cty = fcx.expr_ty(e);
3748 demand::suptype(fcx, e.span, declty, cty);
3749 regionck::regionck_expr(fcx, e);
3750 writeback::resolve_type_vars_in_expr(fcx, e);
3753 /// Checks whether a type can be represented in memory. In particular, it
3754 /// identifies types that contain themselves without indirection through a
3755 /// pointer, which would mean their size is unbounded. This is different from
3756 /// the question of whether a type can be instantiated. See the definition of
3757 /// `check_instantiable`.
3758 pub fn check_representable(tcx: &ty::ctxt,
3760 item_id: ast::NodeId,
3761 designation: &str) -> bool {
3762 let rty = ty::node_id_to_type(tcx, item_id);
3764 // Check that it is possible to represent this type. This call identifies
3765 // (1) types that contain themselves and (2) types that contain a different
3766 // recursive type. It is only necessary to throw an error on those that
3767 // contain themselves. For case 2, there must be an inner type that will be
3768 // caught by case 1.
3769 match ty::is_type_representable(tcx, sp, rty) {
3770 ty::SelfRecursive => {
3772 sp, format!("illegal recursive {} type; \
3773 wrap the inner value in a box to make it representable",
3774 designation).as_slice());
3777 ty::Representable | ty::ContainsRecursive => (),
3782 /// Checks whether a type can be created without an instance of itself.
3783 /// This is similar but different from the question of whether a type
3784 /// can be represented. For example, the following type:
3786 /// enum foo { None, Some(foo) }
3788 /// is instantiable but is not representable. Similarly, the type
3790 /// enum foo { Some(@foo) }
3792 /// is representable, but not instantiable.
3793 pub fn check_instantiable(tcx: &ty::ctxt,
3795 item_id: ast::NodeId)
3797 let item_ty = ty::node_id_to_type(tcx, item_id);
3798 if !ty::is_instantiable(tcx, item_ty) {
3801 format!("this type cannot be instantiated without an \
3802 instance of itself; consider using \
3804 ppaux::ty_to_string(tcx, item_ty)).as_slice());
3811 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3812 let t = ty::node_id_to_type(tcx, id);
3813 if ty::type_needs_subst(t) {
3814 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3817 match ty::get(t).sty {
3818 ty::ty_struct(did, ref substs) => {
3819 let fields = ty::lookup_struct_fields(tcx, did);
3820 if fields.is_empty() {
3821 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3824 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3825 if !fields.iter().all(
3826 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3827 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3830 if !ty::type_is_machine(e) {
3831 tcx.sess.span_err(sp, "SIMD vector element type should be \
3840 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3841 vs: &[ast::P<ast::Variant>]) {
3842 for &v in vs.iter() {
3844 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3845 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3846 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3847 let len = arg_tys.len();
3851 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3852 // Allow the last field in an enum to be unsized.
3853 // We want to do this so that we can support smart pointers.
3854 // A struct value with an unsized final field is itself
3855 // unsized and we must track this in the type system.
3856 if !ty::type_is_sized(ccx.tcx, *t) {
3860 args.get(i).ty.span,
3861 format!("type `{}` is dynamically sized. \
3862 dynamically sized types may only \
3863 appear as the final type in a \
3865 ppaux::ty_to_string(ccx.tcx,
3870 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3876 pub fn check_enum_variants(ccx: &CrateCtxt,
3878 vs: &[ast::P<ast::Variant>],
3881 fn disr_in_range(ccx: &CrateCtxt,
3883 disr: ty::Disr) -> bool {
3884 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3886 ast::TyU8 => disr as u8 as Disr == disr,
3887 ast::TyU16 => disr as u16 as Disr == disr,
3888 ast::TyU32 => disr as u32 as Disr == disr,
3889 ast::TyU64 => disr as u64 as Disr == disr,
3890 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3893 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3895 ast::TyI8 => disr as i8 as Disr == disr,
3896 ast::TyI16 => disr as i16 as Disr == disr,
3897 ast::TyI32 => disr as i32 as Disr == disr,
3898 ast::TyI64 => disr as i64 as Disr == disr,
3899 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3903 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3904 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3908 fn do_check(ccx: &CrateCtxt,
3909 vs: &[ast::P<ast::Variant>],
3911 hint: attr::ReprAttr)
3912 -> Vec<Rc<ty::VariantInfo>> {
3914 let rty = ty::node_id_to_type(ccx.tcx, id);
3915 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3916 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3917 let mut prev_disr_val: Option<ty::Disr> = None;
3919 for &v in vs.iter() {
3921 // If the discriminant value is specified explicitly in the enum check whether the
3922 // initialization expression is valid, otherwise use the last value plus one.
3923 let mut current_disr_val = match prev_disr_val {
3924 Some(prev_disr_val) => prev_disr_val + 1,
3925 None => ty::INITIAL_DISCRIMINANT_VALUE
3928 match v.node.disr_expr {
3930 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
3932 let inh = blank_inherited_fields(ccx);
3933 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3934 let declty = match hint {
3935 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3936 attr::ReprInt(_, attr::SignedInt(ity)) => {
3937 ty::mk_mach_int(ity)
3939 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3940 ty::mk_mach_uint(ity)
3943 check_const_with_ty(&fcx, e.span, &*e, declty);
3944 // check_expr (from check_const pass) doesn't guarantee
3945 // that the expression is in a form that eval_const_expr can
3946 // handle, so we may still get an internal compiler error
3948 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3949 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3950 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3952 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3958 format!("expected constant: {}",
3966 // Check for duplicate discriminant values
3967 if disr_vals.contains(¤t_disr_val) {
3968 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3970 // Check for unrepresentable discriminant values
3972 attr::ReprAny | attr::ReprExtern => (),
3973 attr::ReprInt(sp, ity) => {
3974 if !disr_in_range(ccx, ity, current_disr_val) {
3975 ccx.tcx.sess.span_err(v.span,
3976 "discriminant value outside specified type");
3977 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3981 disr_vals.push(current_disr_val);
3983 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3985 prev_disr_val = Some(current_disr_val);
3987 variants.push(variant_info);
3993 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3994 if hint != attr::ReprAny && vs.len() <= 1 {
3995 let msg = if vs.len() == 1 {
3996 "unsupported representation for univariant enum"
3998 "unsupported representation for zero-variant enum"
4000 ccx.tcx.sess.span_err(sp, msg)
4003 let variants = do_check(ccx, vs, id, hint);
4005 // cache so that ty::enum_variants won't repeat this work
4006 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4008 check_representable(ccx.tcx, sp, id, "enum");
4010 // Check that it is possible to instantiate this enum:
4012 // This *sounds* like the same that as representable, but it's
4013 // not. See def'n of `check_instantiable()` for details.
4014 check_instantiable(ccx.tcx, sp, id);
4017 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4018 lookup_def_ccx(fcx.ccx, sp, id)
4021 // Returns the type parameter count and the type for the given definition.
4022 pub fn polytype_for_def(fcx: &FnCtxt,
4027 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4028 def::DefBinding(nid, _) => {
4029 let typ = fcx.local_ty(sp, nid);
4030 return no_params(typ);
4032 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4033 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4034 def::DefStruct(id) => {
4035 return ty::lookup_item_type(fcx.ccx.tcx, id);
4037 def::DefUpvar(_, inner, _, _) => {
4038 return polytype_for_def(fcx, sp, *inner);
4043 def::DefTyParam(..)=> {
4044 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4046 def::DefMod(..) | def::DefForeignMod(..) => {
4047 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4049 def::DefUse(..) => {
4050 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4052 def::DefRegion(..) => {
4053 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4055 def::DefTyParamBinder(..) => {
4056 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4058 def::DefLabel(..) => {
4059 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4061 def::DefSelfTy(..) => {
4062 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4064 def::DefMethod(..) => {
4065 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4070 // Instantiates the given path, which must refer to an item with the given
4071 // number of type parameters and type.
4072 pub fn instantiate_path(fcx: &FnCtxt,
4077 node_id: ast::NodeId) {
4078 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4079 path.repr(fcx.tcx()),
4080 def.repr(fcx.tcx()),
4082 polytype.repr(fcx.tcx()));
4084 // We need to extract the type parameters supplied by the user in
4085 // the path `path`. Due to the current setup, this is a bit of a
4086 // tricky-process; the problem is that resolve only tells us the
4087 // end-point of the path resolution, and not the intermediate steps.
4088 // Luckily, we can (at least for now) deduce the intermediate steps
4089 // just from the end-point.
4091 // There are basically three cases to consider:
4093 // 1. Reference to a *type*, such as a struct or enum:
4095 // mod a { struct Foo<T> { ... } }
4097 // Because we don't allow types to be declared within one
4098 // another, a path that leads to a type will always look like
4099 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4100 // that only the final segment can have type parameters, and
4101 // they are located in the TypeSpace.
4103 // *Note:* Generally speaking, references to types don't
4104 // actually pass through this function, but rather the
4105 // `ast_ty_to_ty` function in `astconv`. However, in the case
4106 // of struct patterns (and maybe literals) we do invoke
4107 // `instantiate_path` to get the general type of an instance of
4108 // a struct. (In these cases, there are actually no type
4109 // parameters permitted at present, but perhaps we will allow
4110 // them in the future.)
4112 // 1b. Reference to a enum variant or tuple-like struct:
4114 // struct foo<T>(...)
4115 // enum E<T> { foo(...) }
4117 // In these cases, the parameters are declared in the type
4120 // 2. Reference to a *fn item*:
4124 // In this case, the path will again always have the form
4125 // `a::b::foo::<T>` where only the final segment should have
4126 // type parameters. However, in this case, those parameters are
4127 // declared on a value, and hence are in the `FnSpace`.
4129 // 3. Reference to a *method*:
4131 // impl<A> SomeStruct<A> {
4135 // Here we can have a path like
4136 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4137 // may appear in two places. The penultimate segment,
4138 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4139 // final segment, `foo::<B>` contains parameters in fn space.
4141 // The first step then is to categorize the segments appropriately.
4143 assert!(path.segments.len() >= 1);
4144 let mut segment_spaces;
4146 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4147 def::DefSelfTy(..) |
4148 def::DefStruct(..) |
4149 def::DefVariant(..) |
4150 def::DefTyParamBinder(..) |
4153 def::DefPrimTy(..) |
4154 def::DefTyParam(..) => {
4155 // Everything but the final segment should have no
4156 // parameters at all.
4157 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4158 segment_spaces.push(Some(subst::TypeSpace));
4161 // Case 2. Reference to a top-level value.
4163 def::DefStatic(..) => {
4164 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4165 segment_spaces.push(Some(subst::FnSpace));
4168 // Case 3. Reference to a method.
4169 def::DefStaticMethod(..) => {
4170 assert!(path.segments.len() >= 2);
4171 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4172 segment_spaces.push(Some(subst::TypeSpace));
4173 segment_spaces.push(Some(subst::FnSpace));
4176 // Other cases. Various nonsense that really shouldn't show up
4177 // here. If they do, an error will have been reported
4178 // elsewhere. (I hope)
4180 def::DefForeignMod(..) |
4183 def::DefMethod(..) |
4184 def::DefBinding(..) |
4186 def::DefRegion(..) |
4188 def::DefUpvar(..) => {
4189 segment_spaces = Vec::from_elem(path.segments.len(), None);
4192 assert_eq!(segment_spaces.len(), path.segments.len());
4194 debug!("segment_spaces={}", segment_spaces);
4196 // Next, examine the definition, and determine how many type
4197 // parameters we expect from each space.
4198 let type_defs = &polytype.generics.types;
4199 let region_defs = &polytype.generics.regions;
4201 // Now that we have categorized what space the parameters for each
4202 // segment belong to, let's sort out the parameters that the user
4203 // provided (if any) into their appropriate spaces. We'll also report
4204 // errors if type parameters are provided in an inappropriate place.
4205 let mut substs = Substs::empty();
4206 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4209 report_error_if_segment_contains_type_parameters(fcx, segment);
4213 push_explicit_parameters_from_segment_to_substs(fcx,
4223 // Now we have to compare the types that the user *actually*
4224 // provided against the types that were *expected*. If the user
4225 // did not provide any types, then we want to substitute inference
4226 // variables. If the user provided some types, we may still need
4227 // to add defaults. If the user provided *too many* types, that's
4229 for &space in ParamSpace::all().iter() {
4230 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4231 assert_eq!(substs.types.len(space), type_defs.len(space));
4233 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4234 assert_eq!(substs.regions().len(space), region_defs.len(space));
4237 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4241 fn report_error_if_segment_contains_type_parameters(
4243 segment: &ast::PathSegment)
4245 for typ in segment.types.iter() {
4246 fcx.tcx().sess.span_err(
4248 "type parameters may not appear here");
4252 for lifetime in segment.lifetimes.iter() {
4253 fcx.tcx().sess.span_err(
4255 "lifetime parameters may not appear here");
4260 fn push_explicit_parameters_from_segment_to_substs(
4262 space: subst::ParamSpace,
4263 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4264 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4265 segment: &ast::PathSegment,
4266 substs: &mut Substs)
4269 * Finds the parameters that the user provided and adds them
4270 * to `substs`. If too many parameters are provided, then
4271 * reports an error and clears the output vector.
4273 * We clear the output vector because that will cause the
4274 * `adjust_XXX_parameters()` later to use inference
4275 * variables. This seems less likely to lead to derived
4278 * Note that we *do not* check for *too few* parameters here.
4279 * Due to the presence of defaults etc that is more
4280 * complicated. I wanted however to do the reporting of *too
4281 * many* parameters here because we can easily use the precise
4282 * span of the N+1'th parameter.
4286 let type_count = type_defs.len(space);
4287 assert_eq!(substs.types.len(space), 0);
4288 for (i, &typ) in segment.types.iter().enumerate() {
4289 let t = fcx.to_ty(&*typ);
4291 substs.types.push(space, t);
4292 } else if i == type_count {
4293 fcx.tcx().sess.span_err(
4296 "too many type parameters provided: \
4297 expected at most {} parameter(s) \
4298 but found {} parameter(s)",
4300 segment.types.len()).as_slice());
4301 substs.types.truncate(space, 0);
4307 let region_count = region_defs.len(space);
4308 assert_eq!(substs.regions().len(space), 0);
4309 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4310 let r = ast_region_to_region(fcx.tcx(), lifetime);
4311 if i < region_count {
4312 substs.mut_regions().push(space, r);
4313 } else if i == region_count {
4314 fcx.tcx().sess.span_err(
4317 "too many lifetime parameters provided: \
4318 expected {} parameter(s) but found {} parameter(s)",
4320 segment.lifetimes.len()).as_slice());
4321 substs.mut_regions().truncate(space, 0);
4327 fn adjust_type_parameters(
4331 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4332 substs: &mut Substs)
4334 let provided_len = substs.types.len(space);
4335 let desired = defs.get_slice(space);
4336 let required_len = desired.iter()
4337 .take_while(|d| d.default.is_none())
4340 debug!("adjust_type_parameters(space={}, \
4349 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4350 assert!(provided_len <= desired.len());
4352 // Nothing specified at all: supply inference variables for
4354 if provided_len == 0 {
4355 substs.types.replace(space,
4356 fcx.infcx().next_ty_vars(desired.len()));
4360 // Too few parameters specified: report an error and use Err
4362 if provided_len < required_len {
4364 if desired.len() != required_len { "at least " } else { "" };
4365 fcx.tcx().sess.span_err(
4367 format!("too few type parameters provided: \
4368 expected {}{} parameter(s) \
4369 but found {} parameter(s)",
4372 provided_len).as_slice());
4373 substs.types.replace(space,
4374 Vec::from_elem(desired.len(), ty::mk_err()));
4378 // Otherwise, add in any optional parameters that the user
4379 // omitted. The case of *too many* parameters is handled
4381 // push_explicit_parameters_from_segment_to_substs(). Note
4382 // that the *default* type are expressed in terms of all prior
4383 // parameters, so we have to substitute as we go with the
4384 // partial substitution that we have built up.
4385 for i in range(provided_len, desired.len()) {
4386 let default = desired[i].default.unwrap();
4387 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4388 substs.types.push(space, default);
4390 assert_eq!(substs.types.len(space), desired.len());
4392 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4395 fn adjust_region_parameters(
4399 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4400 substs: &mut Substs)
4402 let provided_len = substs.mut_regions().len(space);
4403 let desired = defs.get_slice(space);
4405 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4406 assert!(provided_len <= desired.len());
4408 // If nothing was provided, just use inference variables.
4409 if provided_len == 0 {
4410 substs.mut_regions().replace(
4412 fcx.infcx().region_vars_for_defs(span, desired));
4416 // If just the right number were provided, everybody is happy.
4417 if provided_len == desired.len() {
4421 // Otherwise, too few were provided. Report an error and then
4422 // use inference variables.
4423 fcx.tcx().sess.span_err(
4426 "too few lifetime parameters provided: \
4427 expected {} parameter(s) \
4428 but found {} parameter(s)",
4430 provided_len).as_slice());
4432 substs.mut_regions().replace(
4434 fcx.infcx().region_vars_for_defs(span, desired));
4438 // Resolves `typ` by a single level if `typ` is a type variable. If no
4439 // resolution is possible, then an error is reported.
4440 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4441 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4442 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4444 fcx.type_error_message(sp, |_actual| {
4445 "the type of this value must be known in this \
4446 context".to_string()
4448 demand::suptype(fcx, sp, ty::mk_err(), tp);
4454 // Returns the one-level-deep structure of the given type.
4455 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4457 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4460 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4461 let typ_s = structurally_resolved_type(fcx, sp, typ);
4462 return ty::type_is_integral(typ_s);
4465 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4466 let typ_s = structurally_resolved_type(fcx, sp, typ);
4467 return ty::type_is_uint(typ_s);
4470 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4473 mk_inner: || -> ty::mt)
4476 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4477 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4479 ast::ExprLit(..) => {
4480 // string literals and *empty slices* live in static memory
4481 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4483 ast::ExprVec(ref elements) if elements.len() == 0 => {
4484 // string literals and *empty slices* live in static memory
4485 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4487 ast::ExprRepeat(..) |
4488 ast::ExprVec(..) => {
4489 // vector literals are temporaries on the stack
4490 match fcx.tcx().region_maps.temporary_scope(e.id) {
4491 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4492 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4496 fcx.ccx.tcx.sess.span_bug(e.span,
4497 "vstore with unexpected \
4505 // Returns true if b contains a break that can exit from b
4506 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4507 // First: is there an unlabeled break immediately
4509 (loop_query(&*b, |e| {
4511 ast::ExprBreak(_) => true,
4515 // Second: is there a labeled break with label
4516 // <id> nested anywhere inside the loop?
4517 (block_query(b, |e| {
4519 ast::ExprBreak(Some(_)) => {
4520 match cx.def_map.borrow().find(&e.id) {
4521 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4529 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4531 tps: &OwnedSlice<ast::TyParam>,
4533 debug!("check_bounds_are_used(n_tps={}, ty={})",
4534 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4536 // make a vector of booleans initially false, set to true when used
4537 if tps.len() == 0u { return; }
4538 let mut tps_used = Vec::from_elem(tps.len(), false);
4540 ty::walk_ty(ty, |t| {
4541 match ty::get(t).sty {
4542 ty::ty_param(ParamTy {idx, ..}) => {
4543 debug!("Found use of ty param num {}", idx);
4544 *tps_used.get_mut(idx) = true;
4550 for (i, b) in tps_used.iter().enumerate() {
4552 ccx.tcx.sess.span_err(
4554 format!("type parameter `{}` is unused",
4555 token::get_ident(tps.get(i).ident)).as_slice());
4560 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4561 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4562 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4566 let name = token::get_ident(it.ident);
4567 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4568 let split : Vec<&str> = name.get().split('_').collect();
4569 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4571 //We only care about the operation here
4572 match *split.get(1) {
4573 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4577 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4579 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4582 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4583 "min" | "umax" | "umin" => {
4584 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4588 (0, Vec::new(), ty::mk_nil())
4591 tcx.sess.span_err(it.span,
4592 format!("unrecognized atomic operation \
4601 "abort" => (0, Vec::new(), ty::mk_bot()),
4602 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4604 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4605 "init" => (1u, Vec::new(), param(ccx, 0u)),
4606 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4607 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4608 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4609 "move_val_init" => {
4612 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4617 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4618 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4621 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4623 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4625 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4627 mutbl: ast::MutImmutable
4629 (1u, Vec::new(), td_ptr)
4632 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4636 ty::mk_struct(ccx.tcx, did,
4637 subst::Substs::empty())),
4639 tcx.sess.span_fatal(it.span, msg.as_slice());
4644 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4646 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4648 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4649 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4650 Ok((_, vot)) => vot,
4651 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4654 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4656 mutbl: ast::MutImmutable
4658 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4663 ty::mk_ptr(tcx, ty::mt {
4665 mutbl: ast::MutImmutable
4669 ty::mk_ptr(tcx, ty::mt {
4671 mutbl: ast::MutImmutable
4674 "copy_memory" | "copy_nonoverlapping_memory" |
4675 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4678 ty::mk_ptr(tcx, ty::mt {
4680 mutbl: ast::MutMutable
4682 ty::mk_ptr(tcx, ty::mt {
4684 mutbl: ast::MutImmutable
4690 "set_memory" | "volatile_set_memory" => {
4693 ty::mk_ptr(tcx, ty::mt {
4695 mutbl: ast::MutMutable
4702 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4703 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4706 vec!( ty::mk_f32(), ty::mk_i32() ),
4711 vec!( ty::mk_f64(), ty::mk_i32() ),
4714 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4715 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4716 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4717 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4720 vec!( ty::mk_f32(), ty::mk_f32() ),
4725 vec!( ty::mk_f64(), ty::mk_f64() ),
4728 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4729 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4730 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4731 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4732 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4733 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4734 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4735 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4736 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4737 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4740 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4745 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4748 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4749 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4750 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4751 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4752 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4753 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4754 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4755 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4756 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4757 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4758 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4759 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4760 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4761 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4762 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4763 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4764 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4765 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4766 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4767 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4768 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4769 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4770 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4771 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4772 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4773 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4774 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4775 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4776 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4777 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4778 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4781 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4783 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4785 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4786 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4787 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4789 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4790 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4791 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4793 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4794 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4795 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4797 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4798 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4799 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4801 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4802 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4803 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4805 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4806 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4807 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4809 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4810 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4811 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4813 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4814 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4815 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4818 tcx.sess.span_err(it.span,
4819 format!("unrecognized intrinsic function: `{}`",
4820 *other).as_slice());
4825 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4826 fn_style: ast::UnsafeFn,
4827 abi: abi::RustIntrinsic,
4835 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4836 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4837 if i_n_tps != n_tps {
4838 tcx.sess.span_err(it.span,
4839 format!("intrinsic has wrong number of type \
4840 parameters: found {}, expected {}",
4844 require_same_types(tcx,
4851 format!("intrinsic has wrong type: expected `{}`",
4852 ppaux::ty_to_string(ccx.tcx, fty))