1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function). Inference is used to supply types wherever they are
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
26 - main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `typeck::infer` module is in charge
35 of resolving those constraints.
37 - regionck: after main is complete, the regionck pass goes over all
38 types looking for regions and making sure that they did not escape
39 into places they are not in scope. This may also influence the
40 final assignments of the various region variables if there is some
43 - vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
46 - writeback: writes the final types within a function body, replacing
47 type variables with their final inferred types. These final types
48 are written into the `tcx.node_types` table, which should *never* contain
49 any reference to a type variable.
53 While type checking a function, the intermediate types for the
54 expressions, blocks, and so forth contained within the function are
55 stored in `fcx.node_types` and `fcx.item_substs`. These types
56 may contain unresolved type variables. After type checking is
57 complete, the functions in the writeback module are used to take the
58 types from this table, resolve them, and then write them into their
59 permanent home in the type context `ccx.tcx`.
61 This means that during inferencing you should use `fcx.write_ty()`
62 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63 nodes within the function.
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
68 n.b.: A type variable is not the same thing as a type parameter. A
69 type variable is rather an "instance" of a type parameter: that is,
70 given a generic function `fn foo<T>(t: T)`: while checking the
71 function `foo`, the type `ty_param(0)` refers to the type `T`, which
72 is treated in abstract. When `foo()` is called, however, `T` will be
73 substituted for a fresh type variable `N`. This variable will
74 eventually be resolved to some concrete type (which might itself be
80 use middle::const_eval;
82 use middle::pat_util::pat_id_map;
85 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
86 use middle::ty::{FnSig, VariantInfo};
87 use middle::ty::{Polytype};
88 use middle::ty::{ParamTy, Disr, ExprTyProvider};
90 use middle::ty_fold::TypeFolder;
91 use middle::typeck::astconv::AstConv;
92 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
93 use middle::typeck::astconv;
94 use middle::typeck::check::_match::pat_ctxt;
95 use middle::typeck::check::method::{AutoderefReceiver};
96 use middle::typeck::check::method::{AutoderefReceiverFlag};
97 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
98 use middle::typeck::check::method::{DontAutoderefReceiver};
99 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
100 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
101 use middle::typeck::check::regionmanip::relate_free_regions;
102 use middle::typeck::check::vtable::VtableContext;
103 use middle::typeck::CrateCtxt;
104 use middle::typeck::infer::{resolve_type, force_tvar};
105 use middle::typeck::infer;
106 use middle::typeck::rscope::RegionScope;
107 use middle::typeck::{lookup_def_ccx};
108 use middle::typeck::no_params;
109 use middle::typeck::{require_same_types, vtable_map};
110 use middle::typeck::{MethodCall, MethodMap};
111 use middle::typeck::{TypeAndSubsts};
112 use middle::lang_items::TypeIdLangItem;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159 infcx: infer::InferCtxt<'a>,
160 locals: RefCell<NodeMap<ty::t>>,
161 param_env: ty::ParameterEnvironment,
164 node_types: RefCell<NodeMap<ty::t>>,
165 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167 method_map: MethodMap,
168 vtable_map: vtable_map,
169 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(ty::t),
181 /// This expression will be cast to the `ty::t`
182 ExpectCastableToType(ty::t),
186 pub struct FnStyleState {
187 pub def: ast::NodeId,
188 pub fn_style: ast::FnStyle,
193 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
197 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
198 match self.fn_style {
199 // If this unsafe, then if the outer function was already marked as
200 // unsafe we shouldn't attribute the unsafe'ness to the block. This
201 // way the block can be warned about instead of ignoring this
202 // extraneous block (functions are never warned about).
203 ast::UnsafeFn if self.from_fn => *self,
206 let (fn_style, def) = match blk.rules {
207 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208 ast::DefaultBlock => (fn_style, self.def),
210 FnStyleState{ def: def,
218 /// Whether `check_binop` is part of an assignment or not.
219 /// Used to know whether we allow user overloads and to print
220 /// better messages on error.
221 #[deriving(PartialEq)]
222 enum IsBinopAssignment{
228 pub struct FnCtxt<'a> {
229 // This flag is set to true if, during the writeback phase, we encounter
230 // a type error in this function.
231 writeback_errors: Cell<bool>,
233 // Number of errors that had been reported when we started
234 // checking this function. On exit, if we find that *more* errors
235 // have been reported, we will skip regionck and other work that
236 // expects the types within the function to be consistent.
237 err_count_on_creation: uint,
240 ps: RefCell<FnStyleState>,
242 // Sometimes we generate region pointers where the precise region
243 // to use is not known. For example, an expression like `&x.f`
244 // where `x` is of type `@T`: in this case, we will be rooting
245 // `x` onto the stack frame, and we could choose to root it until
246 // the end of (almost) any enclosing block or expression. We
247 // want to pick the narrowest block that encompasses all uses.
249 // What we do in such cases is to generate a region variable with
250 // `region_lb` as a lower bound. The regionck pass then adds
251 // other constraints based on how the variable is used and region
252 // inference selects the ultimate value. Finally, borrowck is
253 // charged with guaranteeing that the value whose address was taken
254 // can actually be made to live as long as it needs to live.
255 region_lb: Cell<ast::NodeId>,
257 inh: &'a Inherited<'a>,
259 ccx: &'a CrateCtxt<'a>,
262 impl<'a> Inherited<'a> {
263 fn new(tcx: &'a ty::ctxt,
264 param_env: ty::ParameterEnvironment)
267 infcx: infer::new_infer_ctxt(tcx),
268 locals: RefCell::new(NodeMap::new()),
269 param_env: param_env,
270 node_types: RefCell::new(NodeMap::new()),
271 item_substs: RefCell::new(NodeMap::new()),
272 adjustments: RefCell::new(NodeMap::new()),
273 method_map: RefCell::new(FnvHashMap::new()),
274 vtable_map: RefCell::new(FnvHashMap::new()),
275 upvar_borrow_map: RefCell::new(HashMap::new()),
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282 inh: &'a Inherited<'a>,
284 region_bnd: ast::NodeId)
287 writeback_errors: Cell::new(false),
288 err_count_on_creation: ccx.tcx.sess.err_count(),
290 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291 region_lb: Cell::new(region_bnd),
297 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
298 // It's kind of a kludge to manufacture a fake function context
299 // and statement context, but we might as well do write the code only once
300 let param_env = ty::ParameterEnvironment {
301 free_substs: subst::Substs::empty(),
302 bounds: subst::VecPerParamSpace::empty()
304 Inherited::new(ccx.tcx, param_env)
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
312 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
319 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
320 fn visit_item(&mut self, i: &ast::Item, _: ()) {
321 check_item(self.ccx, i);
322 visit::walk_item(self, i, ());
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
328 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329 fn visit_item(&mut self, i: &ast::Item, _: ()) {
330 check_item_sized(self.ccx, i);
331 visit::walk_item(self, i, ());
335 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336 let mut visit = CheckItemTypesVisitor { ccx: ccx };
337 visit::walk_crate(&mut visit, krate, ());
339 ccx.tcx.sess.abort_if_errors();
341 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342 visit::walk_crate(&mut visit, krate, ());
345 fn check_bare_fn(ccx: &CrateCtxt,
350 param_env: ty::ParameterEnvironment) {
351 // Compute the fty from point of view of inside fn
352 // (replace any type-scheme with a type)
353 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
355 match ty::get(fty).sty {
356 ty::ty_bare_fn(ref fn_ty) => {
357 let inh = Inherited::new(ccx.tcx, param_env);
358 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
359 decl, id, body, &inh);
361 vtable::resolve_in_block(&fcx, body);
362 regionck::regionck_fn(&fcx, body);
363 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
365 _ => ccx.tcx.sess.impossible_case(body.span,
366 "check_bare_fn: function type expected")
370 struct GatherLocalsVisitor<'a> {
374 impl<'a> GatherLocalsVisitor<'a> {
375 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
378 // infer the variable's type
379 let var_id = self.fcx.infcx().next_ty_var_id();
380 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
381 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
384 // take type that the user specified
385 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
391 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392 // Add explicitly-declared locals.
393 fn visit_local(&mut self, local: &ast::Local, _: ()) {
394 let o_ty = match local.ty.node {
395 ast::TyInfer => None,
396 _ => Some(self.fcx.to_ty(&*local.ty))
398 self.assign(local.id, o_ty);
399 debug!("Local variable {} is assigned type {}",
400 self.fcx.pat_to_string(&*local.pat),
401 self.fcx.infcx().ty_to_string(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
406 // Add pattern bindings.
407 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
409 ast::PatIdent(_, ref path1, _)
410 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
411 self.assign(p.id, None);
412 debug!("Pattern binding {} is assigned to {}",
413 token::get_ident(path1.node),
414 self.fcx.infcx().ty_to_string(
415 self.fcx.inh.locals.borrow().get_copy(&p.id)));
419 visit::walk_pat(self, p, ());
423 fn visit_block(&mut self, b: &ast::Block, _: ()) {
424 // non-obvious: the `blk` variable maps to region lb, so
425 // we have to keep this up-to-date. This
426 // is... unfortunate. It'd be nice to not need this.
427 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
430 // Don't descend into fns and items
431 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
432 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
433 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438 fn_style: ast::FnStyle,
443 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
446 * Helper used by check_bare_fn and check_expr_fn. Does the
447 * grungy work of checking a function body and returns the
448 * function context used for that purpose, since in the case of a
449 * fn item there is still a bit more to do.
452 * - inherited: other fields inherited from the enclosing fn (if any)
456 let err_count_on_creation = tcx.sess.err_count();
458 // First, we have to replace any bound regions in the fn type with free ones.
459 // The free region references will be bound the node_id of the body block.
460 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
461 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
464 relate_free_regions(tcx, &fn_sig);
466 let arg_tys = fn_sig.inputs.as_slice();
467 let ret_ty = fn_sig.output;
469 debug!("check_fn(arg_tys={}, ret_ty={})",
473 // Create the function context. This is either derived from scratch or,
474 // in the case of function expressions, based on the outer context.
476 writeback_errors: Cell::new(false),
477 err_count_on_creation: err_count_on_creation,
479 ps: RefCell::new(FnStyleState::function(fn_style, id)),
480 region_lb: Cell::new(body.id),
487 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
488 // Add formal parameters.
489 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
490 // Create type variables for each argument.
491 pat_util::pat_bindings(&tcx.def_map,
493 |_bm, pat_id, _sp, _path| {
494 visit.assign(pat_id, None);
497 // Check the pattern.
500 map: pat_id_map(&tcx.def_map, &*input.pat),
502 _match::check_pat(&pcx, &*input.pat, *arg_ty);
505 visit.visit_block(body, ());
508 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
510 // We unify the tail expr's type with the
511 // function result type, if there is a tail expr.
513 Some(ref tail_expr) => {
514 // Special case: we print a special error if there appears
515 // to be do-block/for-loop confusion
516 demand::suptype_with_fn(&fcx, tail_expr.span, false,
517 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
519 fcx.report_mismatched_return_types(sp, e, a, s);
525 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526 fcx.write_ty(input.id, *arg);
532 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
533 assert!(field.id.krate == ast::LOCAL_CRATE);
534 let item = match tcx.map.find(struct_id.node) {
535 Some(ast_map::NodeItem(item)) => item,
536 None => fail!("node not in ast map: {}", struct_id.node),
537 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
541 ast::ItemStruct(struct_def, _) => {
542 match struct_def.fields.iter().find(|f| match f.node.kind {
543 ast::NamedField(ident, _) => ident.name == field.name,
549 .bug(format!("Could not find field {}",
550 token::get_name(field.name)).as_slice())
554 _ => tcx.sess.bug("Field found outside of a struct?"),
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
561 let struct_fields = tcx.struct_fields.borrow();
562 let fields = struct_fields.get(&id);
564 let superstructs = tcx.superstructs.borrow();
565 let super_struct = superstructs.get(&id);
566 match *super_struct {
568 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
569 for f in fields.iter() {
570 match super_fields.iter().find(|sf| f.name == sf.name) {
571 Some(prev_field) => {
572 tcx.sess.span_err(span_for_field(tcx, f, id),
573 format!("field `{}` hides field declared in \
575 token::get_name(f.name)).as_slice());
576 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
577 "previously declared here");
587 fn check_fields_sized(tcx: &ty::ctxt,
588 struct_def: &ast::StructDef) {
589 let len = struct_def.fields.len();
593 for f in struct_def.fields.slice_to(len - 1).iter() {
594 let t = ty::node_id_to_type(tcx, f.node.id);
595 if !ty::type_is_sized(tcx, t) {
597 ast::NamedField(ident, _) => {
600 format!("type `{}` is dynamically sized. \
601 dynamically sized types may only \
602 appear as the type of the final \
604 token::get_ident(ident)).as_slice());
606 ast::UnnamedField(_) => {
607 tcx.sess.span_err(f.span, "dynamically sized type in field");
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
617 check_representable(tcx, span, id, "struct");
618 check_instantiable(tcx, span, id);
620 // Check there are no overlapping fields in super-structs
621 check_for_field_shadowing(tcx, local_def(id));
623 if ty::lookup_simd(tcx, local_def(id)) {
624 check_simd(tcx, span, id);
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629 debug!("check_item(it.id={}, it.ident={})",
631 ty::item_path_str(ccx.tcx, local_def(it.id)));
632 let _indenter = indenter();
635 ast::ItemEnum(ref enum_definition, _) => {
636 check_enum_variants_sized(ccx,
637 enum_definition.variants.as_slice());
639 ast::ItemStruct(..) => {
640 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647 debug!("check_item(it.id={}, it.ident={})",
649 ty::item_path_str(ccx.tcx, local_def(it.id)));
650 let _indenter = indenter();
653 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654 ast::ItemEnum(ref enum_definition, _) => {
655 check_enum_variants(ccx,
657 enum_definition.variants.as_slice(),
660 ast::ItemFn(ref decl, _, _, _, ref body) => {
661 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
663 let param_env = ty::construct_parameter_environment(ccx.tcx,
667 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
669 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
672 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
674 check_method_body(ccx, &impl_pty.generics, &**m);
677 match *opt_trait_ref {
678 Some(ref ast_trait_ref) => {
680 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681 check_impl_methods_against_trait(ccx,
686 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
692 ast::ItemTrait(_, _, _, ref trait_methods) => {
693 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
694 for trait_method in (*trait_methods).iter() {
695 match *trait_method {
697 // Nothing to do, since required methods don't have
701 check_method_body(ccx, &trait_def.generics, &*m);
706 ast::ItemStruct(..) => {
707 check_struct(ccx, it.id, it.span);
709 ast::ItemTy(ref t, ref generics) => {
710 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
711 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
713 ast::ItemForeignMod(ref m) => {
714 if m.abi == abi::RustIntrinsic {
715 for item in m.items.iter() {
716 check_intrinsic_type(ccx, &**item);
719 for item in m.items.iter() {
720 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
721 if !pty.generics.types.is_empty() {
722 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
726 ast::ForeignItemFn(ref fn_decl, _) => {
727 if fn_decl.variadic && m.abi != abi::C {
728 ccx.tcx.sess.span_err(
729 item.span, "variadic function must have C calling convention");
737 _ => {/* nothing to do */ }
741 fn check_method_body(ccx: &CrateCtxt,
742 item_generics: &ty::Generics,
743 method: &ast::Method) {
745 * Type checks a method body.
748 * - `item_generics`: generics defined on the impl/trait that contains
750 * - `self_bound`: bound for the `Self` type parameter, if any
751 * - `method`: the method definition
754 debug!("check_method_body(item_generics={}, method.id={})",
755 item_generics.repr(ccx.tcx),
757 let method_def_id = local_def(method.id);
758 let method_ty = ty::method(ccx.tcx, method_def_id);
759 let method_generics = &method_ty.generics;
761 let param_env = ty::construct_parameter_environment(ccx.tcx,
765 let fty = ty::node_id_to_type(ccx.tcx, method.id);
767 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
772 ast_trait_ref: &ast::TraitRef,
773 impl_trait_ref: &ty::TraitRef,
774 impl_methods: &[Gc<ast::Method>]) {
775 // Locate trait methods
777 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
779 // Check existing impl methods to see if they are both present in trait
780 // and compatible with trait signature
781 for impl_method in impl_methods.iter() {
782 let impl_method_def_id = local_def(impl_method.id);
783 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
785 // If this is an impl of a trait method, find the corresponding
786 // method definition in the trait.
787 let opt_trait_method_ty =
788 trait_methods.iter().
789 find(|tm| tm.ident.name == impl_method_ty.ident.name);
790 match opt_trait_method_ty {
791 Some(trait_method_ty) => {
792 compare_impl_method(ccx.tcx,
797 &impl_trait_ref.substs);
800 // This is span_bug as it should have already been caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_ident(impl_method_ty.ident),
806 pprust::path_to_string(&ast_trait_ref.path)).as_slice());
811 // Check for missing methods from trait
812 let provided_methods = ty::provided_trait_methods(tcx,
813 impl_trait_ref.def_id);
814 let mut missing_methods = Vec::new();
815 for trait_method in trait_methods.iter() {
817 impl_methods.iter().any(
818 |m| m.ident.name == trait_method.ident.name);
820 provided_methods.iter().any(
821 |m| m.ident.name == trait_method.ident.name);
822 if !is_implemented && !is_provided {
823 missing_methods.push(
824 format!("`{}`", token::get_ident(trait_method.ident)));
828 if !missing_methods.is_empty() {
831 format!("not all trait methods implemented, missing: {}",
832 missing_methods.connect(", ")).as_slice());
837 * Checks that a method from an impl/class conforms to the signature of
838 * the same method as declared in the trait.
842 * - impl_generics: the generics declared on the impl itself (not the method!)
843 * - impl_m: type of the method we are checking
844 * - impl_m_span: span to use for reporting errors
845 * - impl_m_body_id: id of the method body
846 * - trait_m: the method in the trait
847 * - trait_to_impl_substs: the substitutions used on the type of the trait
849 fn compare_impl_method(tcx: &ty::ctxt,
852 impl_m_body_id: ast::NodeId,
853 trait_m: &ty::Method,
854 trait_to_impl_substs: &subst::Substs) {
855 debug!("compare_impl_method()");
856 let infcx = infer::new_infer_ctxt(tcx);
858 // Try to give more informative error messages about self typing
859 // mismatches. Note that any mismatch will also be detected
860 // below, where we construct a canonical function type that
861 // includes the self parameter as a normal parameter. It's just
862 // that the error messages you get out of this code are a bit more
863 // inscrutable, particularly for cases where one method has no
865 match (&trait_m.explicit_self, &impl_m.explicit_self) {
866 (&ast::SelfStatic, &ast::SelfStatic) => {}
867 (&ast::SelfStatic, _) => {
870 format!("method `{}` has a `{}` declaration in the impl, \
871 but not in the trait",
872 token::get_ident(trait_m.ident),
873 pprust::explicit_self_to_string(
874 impl_m.explicit_self)).as_slice());
877 (_, &ast::SelfStatic) => {
880 format!("method `{}` has a `{}` declaration in the trait, \
881 but not in the impl",
882 token::get_ident(trait_m.ident),
883 pprust::explicit_self_to_string(
884 trait_m.explicit_self)).as_slice());
888 // Let the type checker catch other errors below
892 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
893 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
894 if num_impl_m_type_params != num_trait_m_type_params {
897 format!("method `{}` has {} type parameter{} \
898 but its trait declaration has {} type parameter{}",
899 token::get_ident(trait_m.ident),
900 num_impl_m_type_params,
901 if num_impl_m_type_params == 1 {""} else {"s"},
902 num_trait_m_type_params,
903 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
907 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
910 format!("method `{}` has {} parameter{} \
911 but the declaration in trait `{}` has {}",
912 token::get_ident(trait_m.ident),
913 impl_m.fty.sig.inputs.len(),
914 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
915 ty::item_path_str(tcx, trait_m.def_id),
916 trait_m.fty.sig.inputs.len()).as_slice());
920 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
921 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
923 // This code is best explained by example. Consider a trait:
926 // fn method<'a,M>(t: T, m: &'a M) -> Self;
931 // impl<'i, U> Trait<&'i U> for Foo {
932 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
935 // We wish to decide if those two method types are compatible.
937 // We start out with trait_to_impl_substs, that maps the trait type
938 // parameters to impl type parameters:
940 // trait_to_impl_substs = {T => &'i U, Self => Foo}
942 // We create a mapping `dummy_substs` that maps from the impl type
943 // parameters to fresh types and regions. For type parameters,
944 // this is the identity transform, but we could as well use any
945 // skolemized types. For regions, we convert from bound to free
946 // regions (Note: but only early-bound regions, i.e., those
947 // declared on the impl or used in type parameter bounds).
949 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
951 // Now we can apply skol_substs to the type of the impl method
952 // to yield a new function type in terms of our fresh, skolemized
955 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
957 // We now want to extract and substitute the type of the *trait*
958 // method and compare it. To do so, we must create a compound
959 // substitution by combining trait_to_impl_substs and
960 // impl_to_skol_substs, and also adding a mapping for the method
961 // type parameters. We extend the mapping to also include
962 // the method parameters.
964 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
966 // Applying this to the trait method type yields:
968 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
970 // This type is also the same but the name of the bound region ('a
971 // vs 'b). However, the normal subtyping rules on fn types handle
972 // this kind of equivalency just fine.
974 // Create mapping from impl to skolemized.
976 impl_m.generics.types.map(
977 |d| ty::mk_param_from_def(tcx, d));
979 impl_m.generics.regions.map(
980 |l| ty::free_region_from_def(impl_m_body_id, l));
981 let impl_to_skol_substs =
982 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
984 // Compute skolemized form of impl method ty.
985 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
986 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
988 // Compute skolemized form of trait method ty.
989 let trait_to_skol_substs =
991 .subst(tcx, &impl_to_skol_substs)
992 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
993 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
994 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
995 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
998 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
999 // Check that the impl does not require any builtin-bounds
1000 // that the trait does not guarantee:
1002 impl_param_def.bounds.builtin_bounds -
1003 trait_param_def.bounds.builtin_bounds;
1004 if !extra_bounds.is_empty() {
1007 format!("in method `{}`, \
1008 type parameter {} requires `{}`, \
1009 which is not required by \
1010 the corresponding type parameter \
1011 in the trait declaration",
1012 token::get_ident(trait_m.ident),
1014 extra_bounds.user_string(tcx)).as_slice());
1018 // Check that the trait bounds of the trait imply the bounds of its
1021 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1022 // traits, but I doubt that'll be wanted often, so meh.
1023 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1024 let impl_trait_bound =
1025 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1028 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1030 trait_bound.subst(tcx, &trait_to_skol_substs);
1031 let infcx = infer::new_infer_ctxt(tcx);
1032 match infer::mk_sub_trait_refs(&infcx,
1034 infer::Misc(impl_m_span),
1036 impl_trait_bound.clone()) {
1046 tcx.sess.span_err(impl_m_span,
1047 format!("in method `{}`, type parameter {} \
1048 requires bound `{}`, which is not \
1049 required by the corresponding \
1050 type parameter in the trait \
1052 token::get_ident(trait_m.ident),
1054 ppaux::trait_ref_to_string(
1056 &*impl_trait_bound)).as_slice())
1061 // Check the impl method type IM is a subtype of the trait method
1062 // type TM. To see why this makes sense, think of a vtable. The
1063 // expected type of the function pointers in the vtable is the
1064 // type TM of the trait method. The actual type will be the type
1065 // IM of the impl method. Because we know that IM <: TM, that
1066 // means that anywhere a TM is expected, a IM will do instead. In
1067 // other words, anyone expecting to call a method with the type
1068 // from the trait, can safely call a method with the type from the
1070 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1071 impl_fty, trait_fty) {
1076 format!("method `{}` has an incompatible type for trait: {}",
1077 token::get_ident(trait_m.ident),
1078 ty::type_err_to_str(tcx, terr)).as_slice());
1079 ty::note_and_explain_type_err(tcx, terr);
1084 fn check_cast(fcx: &FnCtxt,
1089 // Find the type of `e`. Supply hints based on the type we are casting to,
1091 let t_1 = fcx.to_ty(t);
1092 let t_1 = structurally_resolved_type(fcx, span, t_1);
1094 if ty::type_is_scalar(t_1) {
1095 // Supply the type as a hint so as to influence integer
1096 // literals and other things that might care.
1097 check_expr_with_hint(fcx, e, t_1)
1102 let t_e = fcx.expr_ty(e);
1104 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1105 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1107 if ty::type_is_error(t_e) {
1108 fcx.write_error(id);
1111 if ty::type_is_bot(t_e) {
1116 if ty::type_is_trait(t_1) {
1117 // This will be looked up later on.
1118 fcx.write_ty(id, t_1);
1122 let t_1 = structurally_resolved_type(fcx, span, t_1);
1123 let t_e = structurally_resolved_type(fcx, span, t_e);
1125 if ty::type_is_nil(t_e) {
1126 fcx.type_error_message(span, |actual| {
1127 format!("cast from nil: `{}` as `{}`",
1129 fcx.infcx().ty_to_string(t_1))
1131 } else if ty::type_is_nil(t_1) {
1132 fcx.type_error_message(span, |actual| {
1133 format!("cast to nil: `{}` as `{}`",
1135 fcx.infcx().ty_to_string(t_1))
1139 let t_1_is_scalar = ty::type_is_scalar(t_1);
1140 let t_1_is_char = ty::type_is_char(t_1);
1141 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1142 let t_1_is_float = ty::type_is_floating_point(t_1);
1144 // casts to scalars other than `char` and `bare fn` are trivial
1145 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1146 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1148 fcx.type_error_message(span, |actual| {
1149 format!("illegal cast; cast through an \
1150 integer first: `{}` as `{}`",
1152 fcx.infcx().ty_to_string(t_1))
1155 // casts from C-like enums are allowed
1156 } else if t_1_is_char {
1157 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1158 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1159 fcx.type_error_message(span, |actual| {
1160 format!("only `u8` can be cast as \
1161 `char`, not `{}`", actual)
1164 } else if ty::get(t_1).sty == ty::ty_bool {
1168 "cannot cast as `bool`, compare with zero instead");
1169 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1170 fn types_compatible(fcx: &FnCtxt, sp: Span,
1171 t1: ty::t, t2: ty::t) -> bool {
1172 if !ty::type_is_vec(t1) {
1173 // If the type being casted from is not a vector, this special
1174 // case does not apply.
1177 if ty::type_needs_infer(t2) {
1178 // This prevents this special case from going off when casting
1179 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1184 let el = ty::sequence_element_type(fcx.tcx(), t1);
1185 infer::mk_eqty(fcx.infcx(),
1192 // Due to the limitations of LLVM global constants,
1193 // region pointers end up pointing at copies of
1194 // vector elements instead of the original values.
1195 // To allow unsafe pointers to work correctly, we
1196 // need to special-case obtaining an unsafe pointer
1197 // from a region pointer to a vector.
1199 /* this cast is only allowed from &[T] to *T or
1201 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1202 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1203 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1204 if types_compatible(fcx, e.span, mt1, mt2) => {
1205 /* this case is allowed */
1208 demand::coerce(fcx, e.span, t_1, &*e);
1211 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1213 If more type combinations should be supported than are
1214 supported here, then file an enhancement issue and
1215 record the issue number in this comment.
1217 fcx.type_error_message(span, |actual| {
1218 format!("non-scalar cast: `{}` as `{}`",
1220 fcx.infcx().ty_to_string(t_1))
1222 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1223 fcx.type_error_message(span, |actual| {
1224 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1227 fcx.infcx().ty_to_string(t_1))
1231 fcx.write_ty(id, t_1);
1234 impl<'a> AstConv for FnCtxt<'a> {
1235 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1237 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1238 ty::lookup_item_type(self.tcx(), id)
1241 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1242 ty::lookup_trait_def(self.tcx(), id)
1245 fn ty_infer(&self, _span: Span) -> ty::t {
1246 self.infcx().next_ty_var()
1250 impl<'a> FnCtxt<'a> {
1251 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1255 pub fn err_count_since_creation(&self) -> uint {
1256 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1259 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1261 infcx: self.infcx(),
1262 param_env: &self.inh.param_env
1267 impl<'a> RegionScope for infer::InferCtxt<'a> {
1268 fn anon_regions(&self, span: Span, count: uint)
1269 -> Result<Vec<ty::Region> , ()> {
1270 Ok(Vec::from_fn(count, |_| {
1271 self.next_region_var(infer::MiscVariable(span))
1276 impl<'a> FnCtxt<'a> {
1277 pub fn tag(&self) -> String {
1278 format!("{}", self as *const FnCtxt)
1281 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1282 match self.inh.locals.borrow().find(&nid) {
1285 self.tcx().sess.span_bug(
1287 format!("no type for local variable {:?}",
1294 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1295 debug!("write_ty({}, {}) in fcx {}",
1296 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1297 self.inh.node_types.borrow_mut().insert(node_id, ty);
1300 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1301 if !substs.substs.is_noop() {
1302 debug!("write_substs({}, {}) in fcx {}",
1304 substs.repr(self.tcx()),
1307 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1311 pub fn write_ty_substs(&self,
1312 node_id: ast::NodeId,
1314 substs: ty::ItemSubsts) {
1315 let ty = ty.subst(self.tcx(), &substs.substs);
1316 self.write_ty(node_id, ty);
1317 self.write_substs(node_id, substs);
1320 pub fn write_autoderef_adjustment(&self,
1321 node_id: ast::NodeId,
1323 if derefs == 0 { return; }
1324 self.write_adjustment(
1326 ty::AutoDerefRef(ty::AutoDerefRef {
1332 pub fn write_adjustment(&self,
1333 node_id: ast::NodeId,
1334 adj: ty::AutoAdjustment) {
1335 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1336 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1339 pub fn write_nil(&self, node_id: ast::NodeId) {
1340 self.write_ty(node_id, ty::mk_nil());
1342 pub fn write_bot(&self, node_id: ast::NodeId) {
1343 self.write_ty(node_id, ty::mk_bot());
1345 pub fn write_error(&self, node_id: ast::NodeId) {
1346 self.write_ty(node_id, ty::mk_err());
1349 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1350 ast_ty_to_ty(self, self.infcx(), ast_t)
1353 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1354 pat.repr(self.tcx())
1357 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1358 match self.inh.node_types.borrow().find(&ex.id) {
1361 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1362 self.tag()).as_slice());
1367 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1368 match self.inh.node_types.borrow().find(&id) {
1371 self.tcx().sess.bug(
1372 format!("no type for node {}: {} in fcx {}",
1373 id, self.tcx().map.node_to_string(id),
1374 self.tag()).as_slice());
1379 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1380 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1381 Some(method) => method.substs.clone(),
1383 self.tcx().sess.bug(
1384 format!("no method entry for node {}: {} in fcx {}",
1385 id, self.tcx().map.node_to_string(id),
1386 self.tag()).as_slice());
1391 pub fn opt_node_ty_substs(&self,
1393 f: |&ty::ItemSubsts|) {
1394 match self.inh.item_substs.borrow().find(&id) {
1400 pub fn mk_subty(&self,
1401 a_is_expected: bool,
1402 origin: infer::TypeOrigin,
1405 -> Result<(), ty::type_err> {
1406 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1409 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1410 -> Result<(), ty::type_err> {
1411 infer::can_mk_subty(self.infcx(), sub, sup)
1414 pub fn mk_assignty(&self,
1418 -> Result<(), ty::type_err> {
1419 match infer::mk_coercety(self.infcx(),
1421 infer::ExprAssignable(expr.span),
1425 Err(ref e) => Err((*e)),
1426 Ok(Some(adjustment)) => {
1427 self.write_adjustment(expr.id, adjustment);
1433 pub fn mk_eqty(&self,
1434 a_is_expected: bool,
1435 origin: infer::TypeOrigin,
1438 -> Result<(), ty::type_err> {
1439 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1442 pub fn mk_subr(&self,
1443 a_is_expected: bool,
1444 origin: infer::SubregionOrigin,
1447 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1450 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1451 let old_region_lb = self.region_lb.get();
1452 self.region_lb.set(lb);
1454 self.region_lb.set(old_region_lb);
1458 pub fn type_error_message(&self,
1460 mk_msg: |String| -> String,
1462 err: Option<&ty::type_err>) {
1463 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1466 pub fn report_mismatched_return_types(&self,
1470 err: &ty::type_err) {
1472 if ty::type_is_error(e) || ty::type_is_error(a) {
1475 self.infcx().report_mismatched_types(sp, e, a, err)
1478 pub fn report_mismatched_types(&self,
1482 err: &ty::type_err) {
1483 self.infcx().report_mismatched_types(sp, e, a, err)
1487 pub enum LvaluePreference {
1492 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1493 expr_id: Option<ast::NodeId>,
1494 mut lvalue_pref: LvaluePreference,
1495 should_stop: |ty::t, uint| -> Option<T>)
1496 -> (ty::t, uint, Option<T>) {
1498 * Executes an autoderef loop for the type `t`. At each step, invokes
1499 * `should_stop` to decide whether to terminate the loop. Returns
1500 * the final type and number of derefs that it performed.
1502 * Note: this method does not modify the adjustments table. The caller is
1503 * responsible for inserting an AutoAdjustment record into the `fcx`
1504 * using one of the suitable methods.
1507 let mut t = base_ty;
1508 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1509 let resolved_t = structurally_resolved_type(fcx, sp, t);
1511 match should_stop(resolved_t, autoderefs) {
1512 Some(x) => return (resolved_t, autoderefs, Some(x)),
1516 // Otherwise, deref if type is derefable:
1517 let mt = match ty::deref(resolved_t, false) {
1518 Some(mt) => Some(mt),
1520 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1521 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1527 if mt.mutbl == ast::MutImmutable {
1528 lvalue_pref = NoPreference;
1531 None => return (resolved_t, autoderefs, None)
1535 // We've reached the recursion limit, error gracefully.
1536 fcx.tcx().sess.span_err(sp,
1537 format!("reached the recursion limit while auto-dereferencing {}",
1538 base_ty.repr(fcx.tcx())).as_slice());
1539 (ty::mk_err(), 0, None)
1542 /// Attempts to resolve a call expression as an overloaded call.
1543 fn try_overloaded_call(fcx: &FnCtxt,
1544 call_expression: &ast::Expr,
1545 callee: Gc<ast::Expr>,
1547 args: &[Gc<ast::Expr>])
1549 // Try `FnOnce`, then `FnMut`, then `Fn`.
1550 for &(maybe_function_trait, method_name) in [
1551 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1552 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1553 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1555 let function_trait = match maybe_function_trait {
1557 Some(function_trait) => function_trait,
1559 let method_callee = match method::lookup_in_trait(
1561 call_expression.span,
1567 DontAutoderefReceiver,
1568 IgnoreStaticMethods) {
1570 Some(method_callee) => method_callee,
1572 let method_call = MethodCall::expr(call_expression.id);
1573 let output_type = check_method_argument_types(fcx,
1574 call_expression.span,
1580 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1581 write_call(fcx, call_expression, output_type);
1583 if !fcx.tcx().sess.features.overloaded_calls.get() {
1584 fcx.tcx().sess.span_err(call_expression.span,
1585 "overloaded calls are experimental");
1586 fcx.tcx().sess.span_note(call_expression.span,
1587 "add `#[feature(overloaded_calls)]` to \
1588 the crate attributes to enable");
1597 fn try_overloaded_deref(fcx: &FnCtxt,
1599 method_call: Option<MethodCall>,
1600 base_expr: Option<&ast::Expr>,
1602 lvalue_pref: LvaluePreference)
1604 // Try DerefMut first, if preferred.
1605 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1606 (PreferMutLvalue, Some(trait_did)) => {
1607 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1608 token::intern("deref_mut"), trait_did,
1609 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1614 // Otherwise, fall back to Deref.
1615 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1616 (None, Some(trait_did)) => {
1617 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1618 token::intern("deref"), trait_did,
1619 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1621 (method, _) => method
1626 let ref_ty = ty::ty_fn_ret(method.ty);
1628 Some(method_call) => {
1629 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1633 ty::deref(ref_ty, true)
1639 fn try_overloaded_index(fcx: &FnCtxt,
1640 method_call: Option<MethodCall>,
1642 base_expr: Gc<ast::Expr>,
1644 index_expr: Gc<ast::Expr>,
1645 lvalue_pref: LvaluePreference)
1647 // Try `IndexMut` first, if preferred.
1648 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1649 (PreferMutLvalue, Some(trait_did)) => {
1650 method::lookup_in_trait(fcx,
1653 token::intern("index_mut"),
1657 DontAutoderefReceiver,
1658 IgnoreStaticMethods)
1663 // Otherwise, fall back to `Index`.
1664 let method = match (method, fcx.tcx().lang_items.index_trait()) {
1665 (None, Some(trait_did)) => {
1666 method::lookup_in_trait(fcx,
1669 token::intern("index"),
1673 DontAutoderefReceiver,
1674 IgnoreStaticMethods)
1676 (method, _) => method,
1679 // Regardless of whether the lookup succeeds, check the method arguments
1680 // so that we have *some* type for each argument.
1681 let method_type = match method {
1682 Some(ref method) => method.ty,
1683 None => ty::mk_err()
1685 check_method_argument_types(fcx,
1689 [base_expr, index_expr],
1691 DontTupleArguments);
1695 let ref_ty = ty::ty_fn_ret(method.ty);
1697 Some(method_call) => {
1698 fcx.inh.method_map.borrow_mut().insert(method_call,
1703 ty::deref(ref_ty, true)
1709 fn check_method_argument_types(fcx: &FnCtxt,
1711 method_fn_ty: ty::t,
1712 callee_expr: &ast::Expr,
1713 args: &[Gc<ast::Expr>],
1714 deref_args: DerefArgs,
1715 tuple_arguments: TupleArgumentsFlag)
1717 // HACK(eddyb) ignore provided self (it has special typeck rules).
1718 let args = if tuple_arguments == DontTupleArguments {
1723 if ty::type_is_error(method_fn_ty) {
1724 let err_inputs = err_args(args.len());
1725 check_argument_types(fcx,
1727 err_inputs.as_slice(),
1735 match ty::get(method_fn_ty).sty {
1736 ty::ty_bare_fn(ref fty) => {
1737 // HACK(eddyb) ignore self in the definition (see above).
1738 check_argument_types(fcx,
1740 fty.sig.inputs.slice_from(1),
1749 fcx.tcx().sess.span_bug(callee_expr.span,
1750 "method without bare fn type");
1756 fn check_argument_types(fcx: &FnCtxt,
1758 fn_inputs: &[ty::t],
1759 callee_expr: &ast::Expr,
1760 args: &[Gc<ast::Expr>],
1761 deref_args: DerefArgs,
1763 tuple_arguments: TupleArgumentsFlag) {
1766 * Generic function that factors out common logic from
1767 * function calls, method calls and overloaded operators.
1770 let tcx = fcx.ccx.tcx;
1772 // Grab the argument types, supplying fresh type variables
1773 // if the wrong number of arguments were supplied
1774 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1780 let expected_arg_count = fn_inputs.len();
1781 let formal_tys = if tuple_arguments == TupleArguments {
1782 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1783 match ty::get(tuple_type).sty {
1784 ty::ty_tup(ref arg_types) => {
1785 if arg_types.len() != args.len() {
1787 "this function takes {} parameter{} \
1788 but {} parameter{} supplied",
1790 if arg_types.len() == 1 {""} else {"s"},
1792 if args.len() == 1 {" was"} else {"s were"});
1793 tcx.sess.span_err(sp, msg.as_slice());
1794 err_args(args.len())
1796 (*arg_types).clone()
1800 if args.len() != 0 {
1802 "this function takes 0 parameters \
1803 but {} parameter{} supplied",
1805 if args.len() == 1 {" was"} else {"s were"});
1806 tcx.sess.span_err(sp, msg.as_slice());
1813 "cannot use call notation; the first type \
1814 parameter for the function trait is neither a \
1816 err_args(supplied_arg_count)
1819 } else if expected_arg_count == supplied_arg_count {
1820 fn_inputs.iter().map(|a| *a).collect()
1821 } else if variadic {
1822 if supplied_arg_count >= expected_arg_count {
1823 fn_inputs.iter().map(|a| *a).collect()
1826 "this function takes at least {} parameter{} \
1827 but {} parameter{} supplied",
1829 if expected_arg_count == 1 {""} else {"s"},
1831 if supplied_arg_count == 1 {" was"} else {"s were"});
1833 tcx.sess.span_err(sp, msg.as_slice());
1835 err_args(supplied_arg_count)
1839 "this function takes {} parameter{} \
1840 but {} parameter{} supplied",
1842 if expected_arg_count == 1 {""} else {"s"},
1844 if supplied_arg_count == 1 {" was"} else {"s were"});
1846 tcx.sess.span_err(sp, msg.as_slice());
1848 err_args(supplied_arg_count)
1851 debug!("check_argument_types: formal_tys={:?}",
1852 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
1854 // Check the arguments.
1855 // We do this in a pretty awful way: first we typecheck any arguments
1856 // that are not anonymous functions, then we typecheck the anonymous
1857 // functions. This is so that we have more information about the types
1858 // of arguments when we typecheck the functions. This isn't really the
1859 // right way to do this.
1860 let xs = [false, true];
1861 for check_blocks in xs.iter() {
1862 let check_blocks = *check_blocks;
1863 debug!("check_blocks={}", check_blocks);
1865 // More awful hacks: before we check the blocks, try to do
1866 // an "opportunistic" vtable resolution of any trait
1867 // bounds on the call.
1869 vtable::early_resolve_expr(callee_expr, fcx, true);
1872 // For variadic functions, we don't have a declared type for all of
1873 // the arguments hence we only do our usual type checking with
1874 // the arguments who's types we do know.
1875 let t = if variadic {
1877 } else if tuple_arguments == TupleArguments {
1882 for (i, arg) in args.iter().take(t).enumerate() {
1883 let is_block = match arg.node {
1884 ast::ExprFnBlock(..) |
1885 ast::ExprProc(..) => true,
1889 if is_block == check_blocks {
1890 debug!("checking the argument");
1891 let mut formal_ty = *formal_tys.get(i);
1895 match ty::get(formal_ty).sty {
1896 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1899 // So we hit this case when one implements the
1900 // operator traits but leaves an argument as
1901 // just T instead of &T. We'll catch it in the
1902 // mismatch impl/trait method phase no need to
1905 formal_ty = ty::mk_err();
1912 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1918 // We also need to make sure we at least write the ty of the other
1919 // arguments which we skipped above.
1921 for arg in args.iter().skip(expected_arg_count) {
1922 check_expr(fcx, &**arg);
1924 // There are a few types which get autopromoted when passed via varargs
1925 // in C but we just error out instead and require explicit casts.
1926 let arg_ty = structurally_resolved_type(fcx, arg.span,
1927 fcx.expr_ty(&**arg));
1928 match ty::get(arg_ty).sty {
1929 ty::ty_float(ast::TyF32) => {
1930 fcx.type_error_message(arg.span,
1932 format!("can't pass an {} to variadic \
1933 function, cast to c_double", t)
1936 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1937 fcx.type_error_message(arg.span, |t| {
1938 format!("can't pass {} to variadic \
1939 function, cast to c_int",
1943 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1944 fcx.type_error_message(arg.span, |t| {
1945 format!("can't pass {} to variadic \
1946 function, cast to c_uint",
1956 fn err_args(len: uint) -> Vec<ty::t> {
1957 Vec::from_fn(len, |_| ty::mk_err())
1960 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1961 fcx.write_ty(call_expr.id, output);
1964 // AST fragment checking
1965 fn check_lit(fcx: &FnCtxt,
1967 expected: Expectation)
1970 let tcx = fcx.ccx.tcx;
1973 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1974 ast::LitBinary(..) => {
1975 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1977 ast::LitByte(_) => ty::mk_u8(),
1978 ast::LitChar(_) => ty::mk_char(),
1979 ast::LitInt(_, t) => ty::mk_mach_int(t),
1980 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1981 ast::LitIntUnsuffixed(_) => {
1982 let opt_ty = expected.map_to_option(fcx, |sty| {
1984 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1985 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1986 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1987 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1988 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1992 opt_ty.unwrap_or_else(
1993 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1995 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1996 ast::LitFloatUnsuffixed(_) => {
1997 let opt_ty = expected.map_to_option(fcx, |sty| {
1999 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2003 opt_ty.unwrap_or_else(
2004 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2006 ast::LitNil => ty::mk_nil(),
2007 ast::LitBool(_) => ty::mk_bool()
2011 pub fn valid_range_bounds(ccx: &CrateCtxt,
2015 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2016 Some(val) => Some(val <= 0),
2021 pub fn check_expr_has_type(fcx: &FnCtxt,
2024 check_expr_with_unifier(
2025 fcx, expr, ExpectHasType(expected), NoPreference,
2026 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2029 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2032 check_expr_with_unifier(
2033 fcx, expr, ExpectHasType(expected), NoPreference,
2034 || demand::coerce(fcx, expr.span, expected, expr));
2037 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2038 check_expr_with_unifier(
2039 fcx, expr, ExpectHasType(expected), NoPreference,
2043 fn check_expr_with_expectation(fcx: &FnCtxt,
2045 expected: Expectation) {
2046 check_expr_with_unifier(
2047 fcx, expr, expected, NoPreference,
2051 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2053 expected: Expectation,
2054 lvalue_pref: LvaluePreference)
2056 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2059 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2060 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2063 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2064 lvalue_pref: LvaluePreference) {
2065 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2069 // determine the `self` type, using fresh variables for all variables
2070 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2071 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2073 pub fn impl_self_ty(vcx: &VtableContext,
2074 span: Span, // (potential) receiver for this impl
2077 let tcx = vcx.tcx();
2079 let ity = ty::lookup_item_type(tcx, did);
2080 let (n_tps, rps, raw_ty) =
2081 (ity.generics.types.len(subst::TypeSpace),
2082 ity.generics.regions.get_slice(subst::TypeSpace),
2085 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2086 let tps = vcx.infcx.next_ty_vars(n_tps);
2087 let substs = subst::Substs::new_type(tps, rps);
2088 let substd_ty = raw_ty.subst(tcx, &substs);
2090 TypeAndSubsts { substs: substs, ty: substd_ty }
2093 // Only for fields! Returns <none> for methods>
2094 // Indifferent to privacy flags
2095 pub fn lookup_field_ty(tcx: &ty::ctxt,
2096 class_id: ast::DefId,
2097 items: &[ty::field_ty],
2098 fieldname: ast::Name,
2099 substs: &subst::Substs) -> Option<ty::t> {
2101 let o_field = items.iter().find(|f| f.name == fieldname);
2102 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2105 // Controls whether the arguments are automatically referenced. This is useful
2106 // for overloaded binary and unary operators.
2107 pub enum DerefArgs {
2112 /// Controls whether the arguments are tupled. This is used for the call
2115 /// Tupling means that all call-side arguments are packed into a tuple and
2116 /// passed as a single parameter. For example, if tupling is enabled, this
2119 /// fn f(x: (int, int))
2121 /// Can be called as:
2128 #[deriving(Clone, Eq, PartialEq)]
2129 enum TupleArgumentsFlag {
2135 /// If an expression has any sub-expressions that result in a type error,
2136 /// inspecting that expression's type with `ty::type_is_error` will return
2137 /// true. Likewise, if an expression is known to diverge, inspecting its
2138 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2139 /// strict, _|_ can appear in the type of an expression that does not,
2140 /// itself, diverge: for example, fn() -> _|_.)
2141 /// Note that inspecting a type's structure *directly* may expose the fact
2142 /// that there are actually multiple representations for both `ty_err` and
2143 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2144 fn check_expr_with_unifier(fcx: &FnCtxt,
2146 expected: Expectation,
2147 lvalue_pref: LvaluePreference,
2150 debug!(">> typechecking");
2152 // A generic function for doing all of the checking for call expressions
2153 fn check_call(fcx: &FnCtxt,
2154 call_expr: &ast::Expr,
2156 args: &[Gc<ast::Expr>]) {
2157 // Store the type of `f` as the type of the callee
2158 let fn_ty = fcx.expr_ty(f);
2160 // Extract the function signature from `in_fty`.
2161 let fn_sty = structure_of(fcx, f.span, fn_ty);
2163 // This is the "default" function signature, used in case of error.
2164 // In that case, we check each argument against "error" in order to
2165 // set up all the node type bindings.
2166 let error_fn_sig = FnSig {
2167 binder_id: ast::CRATE_NODE_ID,
2168 inputs: err_args(args.len()),
2169 output: ty::mk_err(),
2173 let fn_sig = match *fn_sty {
2174 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2175 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2177 fcx.type_error_message(call_expr.span, |actual| {
2178 format!("expected function but found `{}`", actual)
2184 // Replace any bound regions that appear in the function
2185 // signature with region variables
2186 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2187 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2190 // Call the generic checker.
2191 check_argument_types(fcx,
2193 fn_sig.inputs.as_slice(),
2198 DontTupleArguments);
2200 write_call(fcx, call_expr, fn_sig.output);
2203 // Checks a method call.
2204 fn check_method_call(fcx: &FnCtxt,
2206 method_name: ast::SpannedIdent,
2207 args: &[Gc<ast::Expr>],
2208 tps: &[ast::P<ast::Ty>]) {
2209 let rcvr = args[0].clone();
2210 // We can't know if we need &mut self before we look up the method,
2211 // so treat the receiver as mutable just in case - only explicit
2212 // overloaded dereferences care about the distinction.
2213 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2215 // no need to check for bot/err -- callee does that
2216 let expr_t = structurally_resolved_type(fcx,
2218 fcx.expr_ty(&*rcvr));
2220 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2221 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2222 method_name.node.name,
2223 expr_t, tps.as_slice(),
2225 CheckTraitsAndInherentMethods,
2226 AutoderefReceiver, IgnoreStaticMethods) {
2228 let method_ty = method.ty;
2229 let method_call = MethodCall::expr(expr.id);
2230 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2234 debug!("(checking method call) failing expr is {}", expr.id);
2236 fcx.type_error_message(method_name.span,
2238 format!("type `{}` does not implement any \
2239 method in scope named `{}`",
2241 token::get_ident(method_name.node))
2246 // Add error type for the result
2247 fcx.write_error(expr.id);
2249 // Check for potential static matches (missing self parameters)
2253 method_name.node.name,
2257 CheckTraitsAndInherentMethods,
2258 DontAutoderefReceiver,
2259 ReportStaticMethods);
2265 // Call the generic checker.
2266 let ret_ty = check_method_argument_types(fcx,
2272 DontTupleArguments);
2274 write_call(fcx, expr, ret_ty);
2277 // A generic function for checking the then and else in an if
2279 fn check_then_else(fcx: &FnCtxt,
2280 cond_expr: &ast::Expr,
2281 then_blk: &ast::Block,
2282 opt_else_expr: Option<Gc<ast::Expr>>,
2285 expected: Expectation) {
2286 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2288 let branches_ty = match opt_else_expr {
2289 Some(ref else_expr) => {
2290 // Disregard "castable to" expectations because they
2291 // can lead us astray. Consider for example `if cond
2292 // {22} else {c} as u8` -- if we propagate the
2293 // "castable to u8" constraint to 22, it will pick the
2294 // type 22u8, which is overly constrained (c might not
2295 // be a u8). In effect, the problem is that the
2296 // "castable to" expectation is not the tightest thing
2297 // we can say, so we want to drop it in this case.
2298 // The tightest thing we can say is "must unify with
2299 // else branch". Note that in the case of a "has type"
2300 // constraint, this limitation does not hold.
2301 let expected = expected.only_has_type();
2303 check_block_with_expected(fcx, then_blk, expected);
2304 let then_ty = fcx.node_ty(then_blk.id);
2305 check_expr_with_expectation(fcx, &**else_expr, expected);
2306 let else_ty = fcx.expr_ty(&**else_expr);
2307 infer::common_supertype(fcx.infcx(),
2308 infer::IfExpression(sp),
2314 check_block_no_value(fcx, then_blk);
2319 let cond_ty = fcx.expr_ty(cond_expr);
2320 let if_ty = if ty::type_is_error(cond_ty) {
2322 } else if ty::type_is_bot(cond_ty) {
2328 fcx.write_ty(id, if_ty);
2331 fn lookup_op_method(fcx: &FnCtxt,
2335 trait_did: Option<ast::DefId>,
2336 args: &[Gc<ast::Expr>],
2337 autoderef_receiver: AutoderefReceiverFlag,
2338 unbound_method: ||) -> ty::t {
2339 let method = match trait_did {
2340 Some(trait_did) => {
2341 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2342 trait_did, self_t, [], autoderef_receiver,
2343 IgnoreStaticMethods)
2349 let method_ty = method.ty;
2350 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2351 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2352 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2353 check_method_argument_types(fcx,
2363 // Check the args anyway
2364 // so we get all the error messages
2365 let expected_ty = ty::mk_err();
2366 check_method_argument_types(fcx,
2372 DontTupleArguments);
2378 // could be either an expr_binop or an expr_assign_binop
2379 fn check_binop(fcx: &FnCtxt,
2384 is_binop_assignment: IsBinopAssignment) {
2385 let tcx = fcx.ccx.tcx;
2387 let lvalue_pref = match is_binop_assignment {
2388 BinopAssignment => PreferMutLvalue,
2389 SimpleBinop => NoPreference
2391 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2393 // Callee does bot / err checking
2394 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2395 fcx.expr_ty(&*lhs));
2397 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2398 // Shift is a special case: rhs must be uint, no matter what lhs is
2399 check_expr_has_type(fcx, rhs, ty::mk_uint());
2400 fcx.write_ty(expr.id, lhs_t);
2404 if ty::is_binopable(tcx, lhs_t, op) {
2405 let tvar = fcx.infcx().next_ty_var();
2406 demand::suptype(fcx, expr.span, tvar, lhs_t);
2407 check_expr_has_type(fcx, &*rhs, tvar);
2409 let result_t = match op {
2410 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2412 if ty::type_is_simd(tcx, lhs_t) {
2413 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2414 fcx.type_error_message(expr.span,
2416 format!("binary comparison \
2417 operation `{}` not \
2418 supported for floating \
2419 point SIMD vector `{}`",
2420 ast_util::binop_to_string(op),
2437 fcx.write_ty(expr.id, result_t);
2441 if op == ast::BiOr || op == ast::BiAnd {
2442 // This is an error; one of the operands must have the wrong
2444 fcx.write_error(expr.id);
2445 fcx.write_error(rhs.id);
2446 fcx.type_error_message(expr.span,
2448 format!("binary operation `{}` cannot be applied \
2450 ast_util::binop_to_string(op),
2457 // Check for overloaded operators if not an assignment.
2458 let result_t = if is_binop_assignment == SimpleBinop {
2459 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2461 fcx.type_error_message(expr.span,
2463 format!("binary assignment \
2465 cannot be applied to \
2467 ast_util::binop_to_string(op),
2472 check_expr(fcx, &*rhs);
2476 fcx.write_ty(expr.id, result_t);
2477 if ty::type_is_error(result_t) {
2478 fcx.write_ty(rhs.id, result_t);
2482 fn check_user_binop(fcx: &FnCtxt,
2484 lhs_expr: Gc<ast::Expr>,
2485 lhs_resolved_t: ty::t,
2487 rhs: Gc<ast::Expr>) -> ty::t {
2488 let tcx = fcx.ccx.tcx;
2489 let lang = &tcx.lang_items;
2490 let (name, trait_did) = match op {
2491 ast::BiAdd => ("add", lang.add_trait()),
2492 ast::BiSub => ("sub", lang.sub_trait()),
2493 ast::BiMul => ("mul", lang.mul_trait()),
2494 ast::BiDiv => ("div", lang.div_trait()),
2495 ast::BiRem => ("rem", lang.rem_trait()),
2496 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2497 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2498 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2499 ast::BiShl => ("shl", lang.shl_trait()),
2500 ast::BiShr => ("shr", lang.shr_trait()),
2501 ast::BiLt => ("lt", lang.ord_trait()),
2502 ast::BiLe => ("le", lang.ord_trait()),
2503 ast::BiGe => ("ge", lang.ord_trait()),
2504 ast::BiGt => ("gt", lang.ord_trait()),
2505 ast::BiEq => ("eq", lang.eq_trait()),
2506 ast::BiNe => ("ne", lang.eq_trait()),
2507 ast::BiAnd | ast::BiOr => {
2508 check_expr(fcx, &*rhs);
2509 return ty::mk_err();
2512 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2513 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2514 fcx.type_error_message(ex.span, |actual| {
2515 format!("binary operation `{}` cannot be applied to type `{}`",
2516 ast_util::binop_to_string(op),
2518 }, lhs_resolved_t, None)
2522 fn check_user_unop(fcx: &FnCtxt,
2525 trait_did: Option<ast::DefId>,
2527 rhs_expr: Gc<ast::Expr>,
2528 rhs_t: ty::t) -> ty::t {
2529 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2530 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2531 fcx.type_error_message(ex.span, |actual| {
2532 format!("cannot apply unary operator `{}` to type `{}`",
2538 fn check_expr_fn(fcx: &FnCtxt,
2540 store: ty::TraitStore,
2542 body: ast::P<ast::Block>,
2543 expected: Expectation) {
2544 let tcx = fcx.ccx.tcx;
2546 // Find the expected input/output types (if any). Substitute
2547 // fresh bound regions for any bound regions we find in the
2548 // expected types so as to avoid capture.
2549 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2552 expected_bounds) = {
2553 match expected_sty {
2554 Some(ty::ty_closure(ref cenv)) => {
2556 replace_late_bound_regions_in_fn_sig(
2558 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2559 let onceness = match (&store, &cenv.store) {
2560 // As the closure type and onceness go, only three
2561 // combinations are legit:
2565 // If the actual and expected closure type disagree with
2566 // each other, set expected onceness to be always Once or
2567 // Many according to the actual type. Otherwise, it will
2568 // yield either an illegal "many proc" or a less known
2569 // "once closure" in the error message.
2570 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2571 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2573 (&ty::UniqTraitStore, _) => ast::Once,
2574 (&ty::RegionTraitStore(..), _) => ast::Many,
2576 (Some(sig), onceness, cenv.bounds)
2579 // Not an error! Means we're inferring the closure type
2580 let mut bounds = ty::empty_builtin_bounds();
2581 let onceness = match expr.node {
2582 ast::ExprProc(..) => {
2583 bounds.add(ty::BoundSend);
2588 (None, onceness, bounds)
2593 // construct the function type
2594 let fn_ty = astconv::ty_of_closure(fcx,
2602 let fty_sig = fn_ty.sig.clone();
2603 let fty = ty::mk_closure(tcx, fn_ty);
2604 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
2606 fcx.write_ty(expr.id, fty);
2608 // If the closure is a stack closure and hasn't had some non-standard
2609 // style inferred for it, then check it under its parent's style.
2610 // Otherwise, use its own
2611 let (inherited_style, id) = match store {
2612 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2613 fcx.ps.borrow().def),
2614 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2617 check_fn(fcx.ccx, inherited_style, &fty_sig,
2618 &*decl, id, &*body, fcx.inh);
2622 // Check field access expressions
2623 fn check_field(fcx: &FnCtxt,
2625 lvalue_pref: LvaluePreference,
2627 field: &ast::SpannedIdent,
2628 tys: &[ast::P<ast::Ty>]) {
2629 let tcx = fcx.ccx.tcx;
2630 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2631 let expr_t = structurally_resolved_type(fcx, expr.span,
2633 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2634 let (_, autoderefs, field_ty) =
2635 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2636 match ty::get(base_t).sty {
2637 ty::ty_struct(base_id, ref substs) => {
2638 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2639 let fields = ty::lookup_struct_fields(tcx, base_id);
2640 lookup_field_ty(tcx, base_id, fields.as_slice(),
2641 field.node.name, &(*substs))
2648 fcx.write_ty(expr.id, field_ty);
2649 fcx.write_autoderef_adjustment(base.id, autoderefs);
2655 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2656 match method::lookup(fcx,
2663 CheckTraitsAndInherentMethods,
2665 IgnoreStaticMethods) {
2667 fcx.type_error_message(
2670 format!("attempted to take value of method `{}` on type \
2671 `{}`", token::get_ident(field.node), actual)
2675 tcx.sess.span_note(field.span,
2676 "maybe a missing `()` to call it? If not, try an anonymous function.");
2680 fcx.type_error_message(
2683 format!("attempted access of field `{}` on \
2684 type `{}`, but no field with that \
2686 token::get_ident(field.node),
2693 fcx.write_error(expr.id);
2696 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2699 class_id: ast::DefId,
2700 node_id: ast::NodeId,
2701 substitutions: subst::Substs,
2702 field_types: &[ty::field_ty],
2703 ast_fields: &[ast::Field],
2704 check_completeness: bool) {
2705 let tcx = fcx.ccx.tcx;
2707 let mut class_field_map = HashMap::new();
2708 let mut fields_found = 0;
2709 for field in field_types.iter() {
2710 class_field_map.insert(field.name, (field.id, false));
2713 let mut error_happened = false;
2715 // Typecheck each field.
2716 for field in ast_fields.iter() {
2717 let mut expected_field_type = ty::mk_err();
2719 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2722 fcx.type_error_message(
2725 format!("structure `{}` has no field named `{}`",
2726 actual, token::get_ident(field.ident.node))
2730 error_happened = true;
2732 Some((_, true)) => {
2735 format!("field `{}` specified more than once",
2736 token::get_ident(field.ident
2737 .node)).as_slice());
2738 error_happened = true;
2740 Some((field_id, false)) => {
2741 expected_field_type =
2742 ty::lookup_field_type(
2743 tcx, class_id, field_id, &substitutions);
2744 class_field_map.insert(
2745 field.ident.node.name, (field_id, true));
2749 // Make sure to give a type to the field even if there's
2750 // an error, so we can continue typechecking
2751 check_expr_coercable_to_type(
2754 expected_field_type);
2758 fcx.write_error(node_id);
2761 if check_completeness && !error_happened {
2762 // Make sure the programmer specified all the fields.
2763 assert!(fields_found <= field_types.len());
2764 if fields_found < field_types.len() {
2765 let mut missing_fields = Vec::new();
2766 for class_field in field_types.iter() {
2767 let name = class_field.name;
2768 let (_, seen) = *class_field_map.get(&name);
2770 missing_fields.push(
2771 format!("`{}`", token::get_name(name).get()))
2775 tcx.sess.span_err(span,
2777 "missing field{}: {fields}",
2778 if missing_fields.len() == 1 {""} else {"s"},
2779 fields = missing_fields.connect(", ")).as_slice());
2783 if !error_happened {
2784 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2785 class_id, substitutions));
2789 fn check_struct_constructor(fcx: &FnCtxt,
2791 span: codemap::Span,
2792 class_id: ast::DefId,
2793 fields: &[ast::Field],
2794 base_expr: Option<Gc<ast::Expr>>) {
2795 let tcx = fcx.ccx.tcx;
2797 // Look up the number of type parameters and the raw type, and
2798 // determine whether the class is region-parameterized.
2799 let item_type = ty::lookup_item_type(tcx, class_id);
2800 let raw_type = item_type.ty;
2802 // Generate the struct type.
2803 let substitutions = fcx.infcx().fresh_substs_for_type(
2804 span, &item_type.generics);
2805 let mut struct_type = raw_type.subst(tcx, &substitutions);
2807 // Look up and check the fields.
2808 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2809 check_struct_or_variant_fields(fcx,
2815 class_fields.as_slice(),
2817 base_expr.is_none());
2818 if ty::type_is_error(fcx.node_ty(id)) {
2819 struct_type = ty::mk_err();
2822 // Check the base expression if necessary.
2825 Some(base_expr) => {
2826 check_expr_has_type(fcx, &*base_expr, struct_type);
2827 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2828 struct_type = ty::mk_bot();
2833 // Write in the resulting type.
2834 fcx.write_ty(id, struct_type);
2837 fn check_struct_enum_variant(fcx: &FnCtxt,
2839 span: codemap::Span,
2840 enum_id: ast::DefId,
2841 variant_id: ast::DefId,
2842 fields: &[ast::Field]) {
2843 let tcx = fcx.ccx.tcx;
2845 // Look up the number of type parameters and the raw type, and
2846 // determine whether the enum is region-parameterized.
2847 let item_type = ty::lookup_item_type(tcx, enum_id);
2848 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2849 let enum_type = item_type.ty.subst(tcx, &substitutions);
2851 // Look up and check the enum variant fields.
2852 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2853 check_struct_or_variant_fields(fcx,
2859 variant_fields.as_slice(),
2862 fcx.write_ty(id, enum_type);
2865 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2867 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2868 expected: Expectation)
2869 -> (ExprCheckerWithTy, ty::t) {
2870 let tcx = fcx.ccx.tcx;
2871 let (coerce, t) = match expected {
2872 // If we're given an expected type, we can try to coerce to it
2873 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2874 // Otherwise we just leave the type to be resolved later
2875 _ => (false, fcx.infcx().next_ty_var())
2878 (check_expr_coercable_to_type, t)
2880 (check_expr_has_type, t)
2884 let tcx = fcx.ccx.tcx;
2887 ast::ExprVstore(ev, vst) => {
2888 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2889 let typ = match ev.node {
2890 ast::ExprVec(ref args) => {
2891 let mutability = match vst {
2892 ast::ExprVstoreMutSlice => ast::MutMutable,
2893 _ => ast::MutImmutable,
2895 let mut any_error = false;
2896 let mut any_bot = false;
2897 for e in args.iter() {
2898 check(fcx, &**e, t);
2899 let arg_t = fcx.expr_ty(&**e);
2900 if ty::type_is_error(arg_t) {
2903 else if ty::type_is_bot(arg_t) {
2912 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2913 ty::mt{ ty: ty::mk_vec(tcx,
2914 ty::mt {ty: t, mutbl: mutability},
2916 mutbl: mutability })
2919 ast::ExprRepeat(ref element, ref count_expr) => {
2920 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2921 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2922 let mutability = match vst {
2923 ast::ExprVstoreMutSlice => ast::MutMutable,
2924 _ => ast::MutImmutable,
2926 check(fcx, &**element, t);
2927 let arg_t = fcx.expr_ty(&**element);
2928 if ty::type_is_error(arg_t) {
2930 } else if ty::type_is_bot(arg_t) {
2933 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2934 ty::mt{ ty: ty::mk_vec(tcx,
2935 ty::mt {ty: t, mutbl: mutability},
2940 ast::ExprLit(_) => {
2941 let error = if vst == ast::ExprVstoreSlice {
2942 "`&\"string\"` has been removed; use `\"string\"` instead"
2944 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2946 tcx.sess.span_err(expr.span, error);
2949 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2951 fcx.write_ty(ev.id, typ);
2952 fcx.write_ty(id, typ);
2955 ast::ExprBox(ref place, ref subexpr) => {
2956 check_expr(fcx, &**place);
2957 check_expr(fcx, &**subexpr);
2959 let mut checked = false;
2961 ast::ExprPath(ref path) => {
2962 // FIXME(pcwalton): For now we hardcode the two permissible
2963 // places: the exchange heap and the managed heap.
2964 let definition = lookup_def(fcx, path.span, place.id);
2965 let def_id = definition.def_id();
2966 if tcx.lang_items.exchange_heap() == Some(def_id) {
2967 fcx.write_ty(id, ty::mk_uniq(tcx,
2968 fcx.expr_ty(&**subexpr)));
2970 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2971 fcx.write_ty(id, ty::mk_box(tcx,
2972 fcx.expr_ty(&**subexpr)));
2980 tcx.sess.span_err(expr.span,
2981 "only the managed heap and exchange heap are \
2982 currently supported");
2983 fcx.write_ty(id, ty::mk_err());
2987 ast::ExprLit(lit) => {
2988 let typ = check_lit(fcx, lit, expected);
2989 fcx.write_ty(id, typ);
2991 ast::ExprBinary(op, ref lhs, ref rhs) => {
2992 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2994 let lhs_ty = fcx.expr_ty(&**lhs);
2995 let rhs_ty = fcx.expr_ty(&**rhs);
2996 if ty::type_is_error(lhs_ty) ||
2997 ty::type_is_error(rhs_ty) {
2998 fcx.write_error(id);
3000 else if ty::type_is_bot(lhs_ty) ||
3001 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3005 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3006 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3008 let lhs_t = fcx.expr_ty(&**lhs);
3009 let result_t = fcx.expr_ty(expr);
3010 demand::suptype(fcx, expr.span, result_t, lhs_t);
3012 let tcx = fcx.tcx();
3013 if !ty::expr_is_lval(tcx, &**lhs) {
3014 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3017 // Overwrite result of check_binop...this preserves existing behavior
3018 // but seems quite dubious with regard to user-defined methods
3019 // and so forth. - Niko
3020 if !ty::type_is_error(result_t)
3021 && !ty::type_is_bot(result_t) {
3022 fcx.write_nil(expr.id);
3025 ast::ExprUnary(unop, ref oprnd) => {
3026 let expected = expected.only_has_type();
3027 let expected_inner = expected.map(fcx, |sty| {
3029 ast::UnBox | ast::UnUniq => match *sty {
3030 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3037 ast::UnNot | ast::UnNeg => {
3045 let lvalue_pref = match unop {
3046 ast::UnDeref => lvalue_pref,
3049 check_expr_with_expectation_and_lvalue_pref(
3050 fcx, &**oprnd, expected_inner, lvalue_pref);
3051 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3052 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3055 oprnd_t = ty::mk_box(tcx, oprnd_t)
3058 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3061 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3062 oprnd_t = match ty::deref(oprnd_t, true) {
3064 None => match try_overloaded_deref(fcx, expr.span,
3065 Some(MethodCall::expr(expr.id)),
3066 Some(&**oprnd), oprnd_t, lvalue_pref) {
3069 let is_newtype = match ty::get(oprnd_t).sty {
3070 ty::ty_struct(did, ref substs) => {
3071 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3073 && fields.get(0).ident ==
3074 token::special_idents::unnamed_field
3079 // This is an obsolete struct deref
3080 tcx.sess.span_err(expr.span,
3081 "single-field tuple-structs can \
3082 no longer be dereferenced");
3084 fcx.type_error_message(expr.span, |actual| {
3085 format!("type `{}` cannot be \
3086 dereferenced", actual)
3095 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3097 if !(ty::type_is_integral(oprnd_t) ||
3098 ty::get(oprnd_t).sty == ty::ty_bool) {
3099 oprnd_t = check_user_unop(fcx, "!", "not",
3100 tcx.lang_items.not_trait(),
3101 expr, oprnd.clone(), oprnd_t);
3105 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3107 if !(ty::type_is_integral(oprnd_t) ||
3108 ty::type_is_fp(oprnd_t)) {
3109 oprnd_t = check_user_unop(fcx, "-", "neg",
3110 tcx.lang_items.neg_trait(),
3111 expr, oprnd.clone(), oprnd_t);
3116 fcx.write_ty(id, oprnd_t);
3118 ast::ExprAddrOf(mutbl, ref oprnd) => {
3119 let expected = expected.only_has_type();
3120 let hint = expected.map(fcx, |sty| {
3121 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3122 _ => NoExpectation }
3124 let lvalue_pref = match mutbl {
3125 ast::MutMutable => PreferMutLvalue,
3126 ast::MutImmutable => NoPreference
3128 check_expr_with_expectation_and_lvalue_pref(fcx,
3133 // Note: at this point, we cannot say what the best lifetime
3134 // is to use for resulting pointer. We want to use the
3135 // shortest lifetime possible so as to avoid spurious borrowck
3136 // errors. Moreover, the longest lifetime will depend on the
3137 // precise details of the value whose address is being taken
3138 // (and how long it is valid), which we don't know yet until type
3139 // inference is complete.
3141 // Therefore, here we simply generate a region variable. The
3142 // region inferencer will then select the ultimate value.
3143 // Finally, borrowck is charged with guaranteeing that the
3144 // value whose address was taken can actually be made to live
3145 // as long as it needs to live.
3146 let region = fcx.infcx().next_region_var(
3147 infer::AddrOfRegion(expr.span));
3149 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3150 let oprnd_t = if ty::type_is_error(tm.ty) {
3152 } else if ty::type_is_bot(tm.ty) {
3156 ty::mk_rptr(tcx, region, tm)
3158 fcx.write_ty(id, oprnd_t);
3160 ast::ExprPath(ref pth) => {
3161 let defn = lookup_def(fcx, pth.span, id);
3162 let pty = polytype_for_def(fcx, expr.span, defn);
3163 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3165 ast::ExprInlineAsm(ref ia) => {
3166 for &(_, ref input) in ia.inputs.iter() {
3167 check_expr(fcx, &**input);
3169 for &(_, ref out) in ia.outputs.iter() {
3170 check_expr(fcx, &**out);
3174 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3175 ast::ExprBreak(_) => { fcx.write_bot(id); }
3176 ast::ExprAgain(_) => { fcx.write_bot(id); }
3177 ast::ExprRet(ref expr_opt) => {
3178 let ret_ty = fcx.ret_ty;
3180 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3181 ret_ty, ty::mk_nil()) {
3182 Ok(_) => { /* fall through */ }
3186 "`return;` in function returning non-nil");
3190 check_expr_has_type(fcx, &**e, ret_ty);
3195 ast::ExprParen(a) => {
3196 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3197 fcx.write_ty(id, fcx.expr_ty(a));
3199 ast::ExprAssign(ref lhs, ref rhs) => {
3200 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3202 let tcx = fcx.tcx();
3203 if !ty::expr_is_lval(tcx, &**lhs) {
3204 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3207 let lhs_ty = fcx.expr_ty(&**lhs);
3208 check_expr_has_type(fcx, &**rhs, lhs_ty);
3209 let rhs_ty = fcx.expr_ty(&**rhs);
3211 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3212 fcx.write_error(id);
3213 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3219 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3220 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3221 id, expr.span, expected);
3223 ast::ExprWhile(ref cond, ref body) => {
3224 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3225 check_block_no_value(fcx, &**body);
3226 let cond_ty = fcx.expr_ty(&**cond);
3227 let body_ty = fcx.node_ty(body.id);
3228 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3229 fcx.write_error(id);
3231 else if ty::type_is_bot(cond_ty) {
3238 ast::ExprForLoop(..) =>
3239 fail!("non-desugared expr_for_loop"),
3240 ast::ExprLoop(ref body, _) => {
3241 check_block_no_value(fcx, &**body);
3242 if !may_break(tcx, expr.id, body.clone()) {
3249 ast::ExprMatch(ref discrim, ref arms) => {
3250 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3252 ast::ExprFnBlock(ref decl, ref body) => {
3253 let region = astconv::opt_ast_region_to_region(fcx,
3259 ty::RegionTraitStore(region, ast::MutMutable),
3264 ast::ExprProc(ref decl, ref body) => {
3272 ast::ExprBlock(ref b) => {
3273 check_block_with_expected(fcx, &**b, expected);
3274 fcx.write_ty(id, fcx.node_ty(b.id));
3276 ast::ExprCall(ref f, ref args) => {
3277 // Index expressions need to be handled separately, to inform them
3278 // that they appear in call position.
3279 check_expr(fcx, &**f);
3280 let f_ty = fcx.expr_ty(&**f);
3282 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3283 check_call(fcx, expr, &**f, args.as_slice());
3284 let (args_bot, args_err) = args.iter().fold((false, false),
3285 |(rest_bot, rest_err), a| {
3286 // is this not working?
3287 let a_ty = fcx.expr_ty(&**a);
3288 (rest_bot || ty::type_is_bot(a_ty),
3289 rest_err || ty::type_is_error(a_ty))});
3290 if ty::type_is_error(f_ty) || args_err {
3291 fcx.write_error(id);
3293 else if ty::type_is_bot(f_ty) || args_bot {
3298 ast::ExprMethodCall(ident, ref tps, ref args) => {
3299 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3300 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3301 let (args_bot, args_err) = arg_tys.fold((false, false),
3302 |(rest_bot, rest_err), a| {
3303 (rest_bot || ty::type_is_bot(a),
3304 rest_err || ty::type_is_error(a))});
3306 fcx.write_error(id);
3307 } else if args_bot {
3311 ast::ExprCast(ref e, ref t) => {
3312 check_cast(fcx, &**e, &**t, id, expr.span);
3314 ast::ExprVec(ref args) => {
3315 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3316 for e in args.iter() {
3317 check(fcx, &**e, t);
3319 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3321 fcx.write_ty(id, typ);
3323 ast::ExprRepeat(ref element, ref count_expr) => {
3324 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3325 let count = ty::eval_repeat_count(fcx, &**count_expr);
3326 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3327 check(fcx, &**element, t);
3328 let element_ty = fcx.expr_ty(&**element);
3329 if ty::type_is_error(element_ty) {
3330 fcx.write_error(id);
3332 else if ty::type_is_bot(element_ty) {
3336 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3338 fcx.write_ty(id, t);
3341 ast::ExprTup(ref elts) => {
3342 let expected = expected.only_has_type();
3343 let flds = expected.map_to_option(fcx, |sty| {
3345 ty::ty_tup(ref flds) => Some((*flds).clone()),
3349 let mut bot_field = false;
3350 let mut err_field = false;
3352 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3353 let opt_hint = match flds {
3354 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3357 check_expr_with_expectation(fcx, *e, opt_hint);
3358 let t = fcx.expr_ty(*e);
3359 err_field = err_field || ty::type_is_error(t);
3360 bot_field = bot_field || ty::type_is_bot(t);
3365 } else if err_field {
3366 fcx.write_error(id);
3368 let typ = ty::mk_tup(tcx, elt_ts);
3369 fcx.write_ty(id, typ);
3372 ast::ExprStruct(ref path, ref fields, base_expr) => {
3373 // Resolve the path.
3374 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3376 Some(def::DefVariant(enum_id, variant_id, _)) => {
3377 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3378 variant_id, fields.as_slice());
3381 // Verify that this was actually a struct.
3382 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3383 match ty::get(typ.ty).sty {
3384 ty::ty_struct(struct_did, _) => {
3385 check_struct_constructor(fcx,
3394 .span_err(path.span,
3395 format!("`{}` does not name a structure",
3396 pprust::path_to_string(
3402 tcx.sess.span_bug(path.span,
3403 "structure constructor wasn't resolved")
3407 ast::ExprField(ref base, ref field, ref tys) => {
3408 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3410 ast::ExprIndex(ref base, ref idx) => {
3411 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3412 check_expr(fcx, &**idx);
3413 let raw_base_t = fcx.expr_ty(&**base);
3414 let idx_t = fcx.expr_ty(&**idx);
3415 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3416 fcx.write_ty(id, raw_base_t);
3417 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3418 fcx.write_ty(id, idx_t);
3420 let (_, autoderefs, field_ty) =
3421 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3422 lvalue_pref, |base_t, _| ty::index(base_t));
3425 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3426 fcx.write_ty(id, mt.ty);
3427 fcx.write_autoderef_adjustment(base.id, autoderefs);
3430 // This is an overloaded method.
3431 let base_t = structurally_resolved_type(fcx,
3434 let method_call = MethodCall::expr(expr.id);
3435 match try_overloaded_index(fcx,
3442 Some(mt) => fcx.write_ty(id, mt.ty),
3444 fcx.type_error_message(expr.span,
3454 fcx.write_ty(id, ty::mk_err())
3463 debug!("type of expr({}) {} is...", expr.id,
3464 syntax::print::pprust::expr_to_string(expr));
3465 debug!("... {}, expected is {}",
3466 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3467 expected.repr(tcx));
3473 fn only_has_type(self) -> Expectation {
3475 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3476 ExpectHasType(t) => ExpectHasType(t)
3480 // Resolves `expected` by a single level if it is a variable. If
3481 // there is no expected type or resolution is not possible (e.g.,
3482 // no constraints yet present), just returns `None`.
3483 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3488 ExpectCastableToType(t) => {
3489 ExpectCastableToType(
3490 fcx.infcx().resolve_type_vars_if_possible(t))
3492 ExpectHasType(t) => {
3494 fcx.infcx().resolve_type_vars_if_possible(t))
3499 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3500 match self.resolve(fcx) {
3501 NoExpectation => NoExpectation,
3502 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3506 fn map_to_option<O>(self,
3508 unpack: |&ty::sty| -> Option<O>)
3511 match self.resolve(fcx) {
3512 NoExpectation => None,
3513 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3518 impl Repr for Expectation {
3519 fn repr(&self, tcx: &ty::ctxt) -> String {
3521 NoExpectation => format!("NoExpectation"),
3522 ExpectHasType(t) => format!("ExpectHasType({})",
3524 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3530 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3531 if !type_is_uint(fcx, sp, t) {
3532 fcx.type_error_message(sp, |actual| {
3533 format!("mismatched types: expected `uint` type but found `{}`",
3539 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3540 if !type_is_integral(fcx, sp, t) {
3541 fcx.type_error_message(sp, |actual| {
3542 format!("mismatched types: expected integral type but found `{}`",
3548 pub fn check_decl_initializer(fcx: &FnCtxt,
3552 let local_ty = fcx.local_ty(init.span, nid);
3553 check_expr_coercable_to_type(fcx, init, local_ty)
3556 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3557 let tcx = fcx.ccx.tcx;
3559 let t = fcx.local_ty(local.span, local.id);
3560 fcx.write_ty(local.id, t);
3564 check_decl_initializer(fcx, local.id, &**init);
3565 let init_ty = fcx.expr_ty(&**init);
3566 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3567 fcx.write_ty(local.id, init_ty);
3573 let pcx = pat_ctxt {
3575 map: pat_id_map(&tcx.def_map, &*local.pat),
3577 _match::check_pat(&pcx, &*local.pat, t);
3578 let pat_ty = fcx.node_ty(local.pat.id);
3579 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3580 fcx.write_ty(local.id, pat_ty);
3584 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3586 let mut saw_bot = false;
3587 let mut saw_err = false;
3589 ast::StmtDecl(decl, id) => {
3592 ast::DeclLocal(ref l) => {
3593 check_decl_local(fcx, &**l);
3594 let l_t = fcx.node_ty(l.id);
3595 saw_bot = saw_bot || ty::type_is_bot(l_t);
3596 saw_err = saw_err || ty::type_is_error(l_t);
3598 ast::DeclItem(_) => {/* ignore for now */ }
3601 ast::StmtExpr(ref expr, id) => {
3603 // Check with expected type of ()
3604 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3605 let expr_ty = fcx.expr_ty(&**expr);
3606 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3607 saw_err = saw_err || ty::type_is_error(expr_ty);
3609 ast::StmtSemi(ref expr, id) => {
3611 check_expr(fcx, &**expr);
3612 let expr_ty = fcx.expr_ty(&**expr);
3613 saw_bot |= ty::type_is_bot(expr_ty);
3614 saw_err |= ty::type_is_error(expr_ty);
3616 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3619 fcx.write_bot(node_id);
3622 fcx.write_error(node_id);
3625 fcx.write_nil(node_id)
3629 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3630 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3631 let blkty = fcx.node_ty(blk.id);
3632 if ty::type_is_error(blkty) {
3633 fcx.write_error(blk.id);
3635 else if ty::type_is_bot(blkty) {
3636 fcx.write_bot(blk.id);
3639 let nilty = ty::mk_nil();
3640 demand::suptype(fcx, blk.span, nilty, blkty);
3644 fn check_block_with_expected(fcx: &FnCtxt,
3646 expected: Expectation) {
3648 let mut fcx_ps = fcx.ps.borrow_mut();
3649 let fn_style_state = fcx_ps.recurse(blk);
3650 replace(&mut *fcx_ps, fn_style_state)
3653 fcx.with_region_lb(blk.id, || {
3654 let mut warned = false;
3655 let mut last_was_bot = false;
3656 let mut any_bot = false;
3657 let mut any_err = false;
3658 for s in blk.stmts.iter() {
3659 check_stmt(fcx, &**s);
3660 let s_id = ast_util::stmt_id(&**s);
3661 let s_ty = fcx.node_ty(s_id);
3662 if last_was_bot && !warned && match s.node {
3663 ast::StmtDecl(decl, _) => {
3665 ast::DeclLocal(_) => true,
3669 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3675 .add_lint(lint::builtin::UNREACHABLE_CODE,
3678 "unreachable statement".to_string());
3681 if ty::type_is_bot(s_ty) {
3682 last_was_bot = true;
3684 any_bot = any_bot || ty::type_is_bot(s_ty);
3685 any_err = any_err || ty::type_is_error(s_ty);
3688 None => if any_err {
3689 fcx.write_error(blk.id);
3692 fcx.write_bot(blk.id);
3695 fcx.write_nil(blk.id);
3698 if any_bot && !warned {
3702 .add_lint(lint::builtin::UNREACHABLE_CODE,
3705 "unreachable expression".to_string());
3707 check_expr_with_expectation(fcx, e, expected);
3708 let ety = fcx.expr_ty(e);
3709 fcx.write_ty(blk.id, ety);
3711 fcx.write_error(blk.id);
3714 fcx.write_bot(blk.id);
3720 *fcx.ps.borrow_mut() = prev;
3723 pub fn check_const(ccx: &CrateCtxt,
3727 let inh = blank_inherited_fields(ccx);
3728 let rty = ty::node_id_to_type(ccx.tcx, id);
3729 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3730 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3731 check_const_with_ty(&fcx, sp, e, declty);
3734 pub fn check_const_with_ty(fcx: &FnCtxt,
3738 // Gather locals in statics (because of block expressions).
3739 // This is technically unnecessary because locals in static items are forbidden,
3740 // but prevents type checking from blowing up before const checking can properly
3742 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3745 let cty = fcx.expr_ty(e);
3746 demand::suptype(fcx, e.span, declty, cty);
3747 regionck::regionck_expr(fcx, e);
3748 writeback::resolve_type_vars_in_expr(fcx, e);
3751 /// Checks whether a type can be represented in memory. In particular, it
3752 /// identifies types that contain themselves without indirection through a
3753 /// pointer, which would mean their size is unbounded. This is different from
3754 /// the question of whether a type can be instantiated. See the definition of
3755 /// `check_instantiable`.
3756 pub fn check_representable(tcx: &ty::ctxt,
3758 item_id: ast::NodeId,
3759 designation: &str) -> bool {
3760 let rty = ty::node_id_to_type(tcx, item_id);
3762 // Check that it is possible to represent this type. This call identifies
3763 // (1) types that contain themselves and (2) types that contain a different
3764 // recursive type. It is only necessary to throw an error on those that
3765 // contain themselves. For case 2, there must be an inner type that will be
3766 // caught by case 1.
3767 match ty::is_type_representable(tcx, sp, rty) {
3768 ty::SelfRecursive => {
3770 sp, format!("illegal recursive {} type; \
3771 wrap the inner value in a box to make it representable",
3772 designation).as_slice());
3775 ty::Representable | ty::ContainsRecursive => (),
3780 /// Checks whether a type can be created without an instance of itself.
3781 /// This is similar but different from the question of whether a type
3782 /// can be represented. For example, the following type:
3784 /// enum foo { None, Some(foo) }
3786 /// is instantiable but is not representable. Similarly, the type
3788 /// enum foo { Some(@foo) }
3790 /// is representable, but not instantiable.
3791 pub fn check_instantiable(tcx: &ty::ctxt,
3793 item_id: ast::NodeId)
3795 let item_ty = ty::node_id_to_type(tcx, item_id);
3796 if !ty::is_instantiable(tcx, item_ty) {
3799 format!("this type cannot be instantiated without an \
3800 instance of itself; consider using \
3802 ppaux::ty_to_string(tcx, item_ty)).as_slice());
3809 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3810 let t = ty::node_id_to_type(tcx, id);
3811 if ty::type_needs_subst(t) {
3812 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3815 match ty::get(t).sty {
3816 ty::ty_struct(did, ref substs) => {
3817 let fields = ty::lookup_struct_fields(tcx, did);
3818 if fields.is_empty() {
3819 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3822 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3823 if !fields.iter().all(
3824 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3825 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3828 if !ty::type_is_machine(e) {
3829 tcx.sess.span_err(sp, "SIMD vector element type should be \
3838 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3839 vs: &[ast::P<ast::Variant>]) {
3840 for &v in vs.iter() {
3842 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3843 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3844 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3845 let len = arg_tys.len();
3849 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3850 // Allow the last field in an enum to be unsized.
3851 // We want to do this so that we can support smart pointers.
3852 // A struct value with an unsized final field is itself
3853 // unsized and we must track this in the type system.
3854 if !ty::type_is_sized(ccx.tcx, *t) {
3858 args.get(i).ty.span,
3859 format!("type `{}` is dynamically sized. \
3860 dynamically sized types may only \
3861 appear as the final type in a \
3863 ppaux::ty_to_string(ccx.tcx,
3868 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3874 pub fn check_enum_variants(ccx: &CrateCtxt,
3876 vs: &[ast::P<ast::Variant>],
3879 fn disr_in_range(ccx: &CrateCtxt,
3881 disr: ty::Disr) -> bool {
3882 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3884 ast::TyU8 => disr as u8 as Disr == disr,
3885 ast::TyU16 => disr as u16 as Disr == disr,
3886 ast::TyU32 => disr as u32 as Disr == disr,
3887 ast::TyU64 => disr as u64 as Disr == disr,
3888 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3891 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3893 ast::TyI8 => disr as i8 as Disr == disr,
3894 ast::TyI16 => disr as i16 as Disr == disr,
3895 ast::TyI32 => disr as i32 as Disr == disr,
3896 ast::TyI64 => disr as i64 as Disr == disr,
3897 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3901 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3902 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3906 fn do_check(ccx: &CrateCtxt,
3907 vs: &[ast::P<ast::Variant>],
3909 hint: attr::ReprAttr)
3910 -> Vec<Rc<ty::VariantInfo>> {
3912 let rty = ty::node_id_to_type(ccx.tcx, id);
3913 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3914 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3915 let mut prev_disr_val: Option<ty::Disr> = None;
3917 for &v in vs.iter() {
3919 // If the discriminant value is specified explicitly in the enum check whether the
3920 // initialization expression is valid, otherwise use the last value plus one.
3921 let mut current_disr_val = match prev_disr_val {
3922 Some(prev_disr_val) => prev_disr_val + 1,
3923 None => ty::INITIAL_DISCRIMINANT_VALUE
3926 match v.node.disr_expr {
3928 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
3930 let inh = blank_inherited_fields(ccx);
3931 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3932 let declty = match hint {
3933 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3934 attr::ReprInt(_, attr::SignedInt(ity)) => {
3935 ty::mk_mach_int(ity)
3937 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3938 ty::mk_mach_uint(ity)
3941 check_const_with_ty(&fcx, e.span, &*e, declty);
3942 // check_expr (from check_const pass) doesn't guarantee
3943 // that the expression is in a form that eval_const_expr can
3944 // handle, so we may still get an internal compiler error
3946 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3947 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3948 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3950 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3956 format!("expected constant: {}",
3964 // Check for duplicate discriminant values
3965 if disr_vals.contains(¤t_disr_val) {
3966 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3968 // Check for unrepresentable discriminant values
3970 attr::ReprAny | attr::ReprExtern => (),
3971 attr::ReprInt(sp, ity) => {
3972 if !disr_in_range(ccx, ity, current_disr_val) {
3973 ccx.tcx.sess.span_err(v.span,
3974 "discriminant value outside specified type");
3975 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3979 disr_vals.push(current_disr_val);
3981 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3983 prev_disr_val = Some(current_disr_val);
3985 variants.push(variant_info);
3991 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3992 if hint != attr::ReprAny && vs.len() <= 1 {
3993 let msg = if vs.len() == 1 {
3994 "unsupported representation for univariant enum"
3996 "unsupported representation for zero-variant enum"
3998 ccx.tcx.sess.span_err(sp, msg)
4001 let variants = do_check(ccx, vs, id, hint);
4003 // cache so that ty::enum_variants won't repeat this work
4004 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4006 check_representable(ccx.tcx, sp, id, "enum");
4008 // Check that it is possible to instantiate this enum:
4010 // This *sounds* like the same that as representable, but it's
4011 // not. See def'n of `check_instantiable()` for details.
4012 check_instantiable(ccx.tcx, sp, id);
4015 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4016 lookup_def_ccx(fcx.ccx, sp, id)
4019 // Returns the type parameter count and the type for the given definition.
4020 pub fn polytype_for_def(fcx: &FnCtxt,
4025 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4026 def::DefBinding(nid, _) => {
4027 let typ = fcx.local_ty(sp, nid);
4028 return no_params(typ);
4030 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4031 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4032 def::DefStruct(id) => {
4033 return ty::lookup_item_type(fcx.ccx.tcx, id);
4035 def::DefUpvar(_, inner, _, _) => {
4036 return polytype_for_def(fcx, sp, *inner);
4041 def::DefTyParam(..)=> {
4042 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4044 def::DefMod(..) | def::DefForeignMod(..) => {
4045 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4047 def::DefUse(..) => {
4048 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4050 def::DefRegion(..) => {
4051 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4053 def::DefTyParamBinder(..) => {
4054 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4056 def::DefLabel(..) => {
4057 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4059 def::DefSelfTy(..) => {
4060 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4062 def::DefMethod(..) => {
4063 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4068 // Instantiates the given path, which must refer to an item with the given
4069 // number of type parameters and type.
4070 pub fn instantiate_path(fcx: &FnCtxt,
4075 node_id: ast::NodeId) {
4076 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4077 path.repr(fcx.tcx()),
4078 def.repr(fcx.tcx()),
4080 polytype.repr(fcx.tcx()));
4082 // We need to extract the type parameters supplied by the user in
4083 // the path `path`. Due to the current setup, this is a bit of a
4084 // tricky-process; the problem is that resolve only tells us the
4085 // end-point of the path resolution, and not the intermediate steps.
4086 // Luckily, we can (at least for now) deduce the intermediate steps
4087 // just from the end-point.
4089 // There are basically three cases to consider:
4091 // 1. Reference to a *type*, such as a struct or enum:
4093 // mod a { struct Foo<T> { ... } }
4095 // Because we don't allow types to be declared within one
4096 // another, a path that leads to a type will always look like
4097 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4098 // that only the final segment can have type parameters, and
4099 // they are located in the TypeSpace.
4101 // *Note:* Generally speaking, references to types don't
4102 // actually pass through this function, but rather the
4103 // `ast_ty_to_ty` function in `astconv`. However, in the case
4104 // of struct patterns (and maybe literals) we do invoke
4105 // `instantiate_path` to get the general type of an instance of
4106 // a struct. (In these cases, there are actually no type
4107 // parameters permitted at present, but perhaps we will allow
4108 // them in the future.)
4110 // 1b. Reference to a enum variant or tuple-like struct:
4112 // struct foo<T>(...)
4113 // enum E<T> { foo(...) }
4115 // In these cases, the parameters are declared in the type
4118 // 2. Reference to a *fn item*:
4122 // In this case, the path will again always have the form
4123 // `a::b::foo::<T>` where only the final segment should have
4124 // type parameters. However, in this case, those parameters are
4125 // declared on a value, and hence are in the `FnSpace`.
4127 // 3. Reference to a *method*:
4129 // impl<A> SomeStruct<A> {
4133 // Here we can have a path like
4134 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4135 // may appear in two places. The penultimate segment,
4136 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4137 // final segment, `foo::<B>` contains parameters in fn space.
4139 // The first step then is to categorize the segments appropriately.
4141 assert!(path.segments.len() >= 1);
4142 let mut segment_spaces;
4144 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4145 def::DefSelfTy(..) |
4146 def::DefStruct(..) |
4147 def::DefVariant(..) |
4148 def::DefTyParamBinder(..) |
4151 def::DefPrimTy(..) |
4152 def::DefTyParam(..) => {
4153 // Everything but the final segment should have no
4154 // parameters at all.
4155 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4156 segment_spaces.push(Some(subst::TypeSpace));
4159 // Case 2. Reference to a top-level value.
4161 def::DefStatic(..) => {
4162 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4163 segment_spaces.push(Some(subst::FnSpace));
4166 // Case 3. Reference to a method.
4167 def::DefStaticMethod(..) => {
4168 assert!(path.segments.len() >= 2);
4169 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4170 segment_spaces.push(Some(subst::TypeSpace));
4171 segment_spaces.push(Some(subst::FnSpace));
4174 // Other cases. Various nonsense that really shouldn't show up
4175 // here. If they do, an error will have been reported
4176 // elsewhere. (I hope)
4178 def::DefForeignMod(..) |
4181 def::DefMethod(..) |
4182 def::DefBinding(..) |
4184 def::DefRegion(..) |
4186 def::DefUpvar(..) => {
4187 segment_spaces = Vec::from_elem(path.segments.len(), None);
4190 assert_eq!(segment_spaces.len(), path.segments.len());
4192 debug!("segment_spaces={}", segment_spaces);
4194 // Next, examine the definition, and determine how many type
4195 // parameters we expect from each space.
4196 let type_defs = &polytype.generics.types;
4197 let region_defs = &polytype.generics.regions;
4199 // Now that we have categorized what space the parameters for each
4200 // segment belong to, let's sort out the parameters that the user
4201 // provided (if any) into their appropriate spaces. We'll also report
4202 // errors if type parameters are provided in an inappropriate place.
4203 let mut substs = Substs::empty();
4204 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4207 report_error_if_segment_contains_type_parameters(fcx, segment);
4211 push_explicit_parameters_from_segment_to_substs(fcx,
4221 // Now we have to compare the types that the user *actually*
4222 // provided against the types that were *expected*. If the user
4223 // did not provide any types, then we want to substitute inference
4224 // variables. If the user provided some types, we may still need
4225 // to add defaults. If the user provided *too many* types, that's
4227 for &space in ParamSpace::all().iter() {
4228 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4229 assert_eq!(substs.types.len(space), type_defs.len(space));
4231 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4232 assert_eq!(substs.regions().len(space), region_defs.len(space));
4235 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4239 fn report_error_if_segment_contains_type_parameters(
4241 segment: &ast::PathSegment)
4243 for typ in segment.types.iter() {
4244 fcx.tcx().sess.span_err(
4246 "type parameters may not appear here");
4250 for lifetime in segment.lifetimes.iter() {
4251 fcx.tcx().sess.span_err(
4253 "lifetime parameters may not appear here");
4258 fn push_explicit_parameters_from_segment_to_substs(
4260 space: subst::ParamSpace,
4261 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4262 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4263 segment: &ast::PathSegment,
4264 substs: &mut Substs)
4267 * Finds the parameters that the user provided and adds them
4268 * to `substs`. If too many parameters are provided, then
4269 * reports an error and clears the output vector.
4271 * We clear the output vector because that will cause the
4272 * `adjust_XXX_parameters()` later to use inference
4273 * variables. This seems less likely to lead to derived
4276 * Note that we *do not* check for *too few* parameters here.
4277 * Due to the presence of defaults etc that is more
4278 * complicated. I wanted however to do the reporting of *too
4279 * many* parameters here because we can easily use the precise
4280 * span of the N+1'th parameter.
4284 let type_count = type_defs.len(space);
4285 assert_eq!(substs.types.len(space), 0);
4286 for (i, &typ) in segment.types.iter().enumerate() {
4287 let t = fcx.to_ty(&*typ);
4289 substs.types.push(space, t);
4290 } else if i == type_count {
4291 fcx.tcx().sess.span_err(
4294 "too many type parameters provided: \
4295 expected at most {} parameter(s) \
4296 but found {} parameter(s)",
4298 segment.types.len()).as_slice());
4299 substs.types.truncate(space, 0);
4305 let region_count = region_defs.len(space);
4306 assert_eq!(substs.regions().len(space), 0);
4307 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4308 let r = ast_region_to_region(fcx.tcx(), lifetime);
4309 if i < region_count {
4310 substs.mut_regions().push(space, r);
4311 } else if i == region_count {
4312 fcx.tcx().sess.span_err(
4315 "too many lifetime parameters provided: \
4316 expected {} parameter(s) but found {} parameter(s)",
4318 segment.lifetimes.len()).as_slice());
4319 substs.mut_regions().truncate(space, 0);
4325 fn adjust_type_parameters(
4329 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4330 substs: &mut Substs)
4332 let provided_len = substs.types.len(space);
4333 let desired = defs.get_slice(space);
4334 let required_len = desired.iter()
4335 .take_while(|d| d.default.is_none())
4338 debug!("adjust_type_parameters(space={}, \
4347 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4348 assert!(provided_len <= desired.len());
4350 // Nothing specified at all: supply inference variables for
4352 if provided_len == 0 {
4353 substs.types.replace(space,
4354 fcx.infcx().next_ty_vars(desired.len()));
4358 // Too few parameters specified: report an error and use Err
4360 if provided_len < required_len {
4362 if desired.len() != required_len { "at least " } else { "" };
4363 fcx.tcx().sess.span_err(
4365 format!("too few type parameters provided: \
4366 expected {}{} parameter(s) \
4367 but found {} parameter(s)",
4370 provided_len).as_slice());
4371 substs.types.replace(space,
4372 Vec::from_elem(desired.len(), ty::mk_err()));
4376 // Otherwise, add in any optional parameters that the user
4377 // omitted. The case of *too many* parameters is handled
4379 // push_explicit_parameters_from_segment_to_substs(). Note
4380 // that the *default* type are expressed in terms of all prior
4381 // parameters, so we have to substitute as we go with the
4382 // partial substitution that we have built up.
4383 for i in range(provided_len, desired.len()) {
4384 let default = desired[i].default.unwrap();
4385 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4386 substs.types.push(space, default);
4388 assert_eq!(substs.types.len(space), desired.len());
4390 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4393 fn adjust_region_parameters(
4397 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4398 substs: &mut Substs)
4400 let provided_len = substs.mut_regions().len(space);
4401 let desired = defs.get_slice(space);
4403 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4404 assert!(provided_len <= desired.len());
4406 // If nothing was provided, just use inference variables.
4407 if provided_len == 0 {
4408 substs.mut_regions().replace(
4410 fcx.infcx().region_vars_for_defs(span, desired));
4414 // If just the right number were provided, everybody is happy.
4415 if provided_len == desired.len() {
4419 // Otherwise, too few were provided. Report an error and then
4420 // use inference variables.
4421 fcx.tcx().sess.span_err(
4424 "too few lifetime parameters provided: \
4425 expected {} parameter(s) \
4426 but found {} parameter(s)",
4428 provided_len).as_slice());
4430 substs.mut_regions().replace(
4432 fcx.infcx().region_vars_for_defs(span, desired));
4436 // Resolves `typ` by a single level if `typ` is a type variable. If no
4437 // resolution is possible, then an error is reported.
4438 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4439 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4440 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4442 fcx.type_error_message(sp, |_actual| {
4443 "the type of this value must be known in this \
4444 context".to_string()
4446 demand::suptype(fcx, sp, ty::mk_err(), tp);
4452 // Returns the one-level-deep structure of the given type.
4453 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4455 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4458 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4459 let typ_s = structurally_resolved_type(fcx, sp, typ);
4460 return ty::type_is_integral(typ_s);
4463 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4464 let typ_s = structurally_resolved_type(fcx, sp, typ);
4465 return ty::type_is_uint(typ_s);
4468 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4471 mk_inner: || -> ty::mt)
4474 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4475 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4477 ast::ExprLit(..) => {
4478 // string literals and *empty slices* live in static memory
4479 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4481 ast::ExprVec(ref elements) if elements.len() == 0 => {
4482 // string literals and *empty slices* live in static memory
4483 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4485 ast::ExprRepeat(..) |
4486 ast::ExprVec(..) => {
4487 // vector literals are temporaries on the stack
4488 match fcx.tcx().region_maps.temporary_scope(e.id) {
4489 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4490 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4494 fcx.ccx.tcx.sess.span_bug(e.span,
4495 "vstore with unexpected \
4503 // Returns true if b contains a break that can exit from b
4504 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4505 // First: is there an unlabeled break immediately
4507 (loop_query(&*b, |e| {
4509 ast::ExprBreak(_) => true,
4513 // Second: is there a labeled break with label
4514 // <id> nested anywhere inside the loop?
4515 (block_query(b, |e| {
4517 ast::ExprBreak(Some(_)) => {
4518 match cx.def_map.borrow().find(&e.id) {
4519 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4527 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4529 tps: &OwnedSlice<ast::TyParam>,
4531 debug!("check_bounds_are_used(n_tps={}, ty={})",
4532 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4534 // make a vector of booleans initially false, set to true when used
4535 if tps.len() == 0u { return; }
4536 let mut tps_used = Vec::from_elem(tps.len(), false);
4538 ty::walk_ty(ty, |t| {
4539 match ty::get(t).sty {
4540 ty::ty_param(ParamTy {idx, ..}) => {
4541 debug!("Found use of ty param num {}", idx);
4542 *tps_used.get_mut(idx) = true;
4548 for (i, b) in tps_used.iter().enumerate() {
4550 ccx.tcx.sess.span_err(
4552 format!("type parameter `{}` is unused",
4553 token::get_ident(tps.get(i).ident)).as_slice());
4558 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4559 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4560 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4564 let name = token::get_ident(it.ident);
4565 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4566 let split : Vec<&str> = name.get().split('_').collect();
4567 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4569 //We only care about the operation here
4570 match *split.get(1) {
4571 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4575 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4577 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4580 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4581 "min" | "umax" | "umin" => {
4582 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4586 (0, Vec::new(), ty::mk_nil())
4589 tcx.sess.span_err(it.span,
4590 format!("unrecognized atomic operation \
4599 "abort" => (0, Vec::new(), ty::mk_bot()),
4600 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4602 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4603 "init" => (1u, Vec::new(), param(ccx, 0u)),
4604 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4605 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4606 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4607 "move_val_init" => {
4610 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4615 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4616 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4619 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4621 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4623 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4625 mutbl: ast::MutImmutable
4627 (1u, Vec::new(), td_ptr)
4630 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4634 ty::mk_struct(ccx.tcx, did,
4635 subst::Substs::empty())),
4637 tcx.sess.span_fatal(it.span, msg.as_slice());
4642 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4644 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4646 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4647 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4648 Ok((_, vot)) => vot,
4649 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4652 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4654 mutbl: ast::MutImmutable
4656 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4661 ty::mk_ptr(tcx, ty::mt {
4663 mutbl: ast::MutImmutable
4667 ty::mk_ptr(tcx, ty::mt {
4669 mutbl: ast::MutImmutable
4672 "copy_memory" | "copy_nonoverlapping_memory" |
4673 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4676 ty::mk_ptr(tcx, ty::mt {
4678 mutbl: ast::MutMutable
4680 ty::mk_ptr(tcx, ty::mt {
4682 mutbl: ast::MutImmutable
4688 "set_memory" | "volatile_set_memory" => {
4691 ty::mk_ptr(tcx, ty::mt {
4693 mutbl: ast::MutMutable
4700 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4701 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4704 vec!( ty::mk_f32(), ty::mk_i32() ),
4709 vec!( ty::mk_f64(), ty::mk_i32() ),
4712 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4713 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4714 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4715 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4718 vec!( ty::mk_f32(), ty::mk_f32() ),
4723 vec!( ty::mk_f64(), ty::mk_f64() ),
4726 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4727 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4728 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4729 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4730 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4731 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4732 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4733 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4734 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4735 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4738 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4743 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4746 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4747 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4748 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4749 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4750 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4751 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4752 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4753 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4754 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4755 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4756 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4757 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4758 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4759 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4760 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4761 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4762 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4763 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4764 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4765 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4766 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4767 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4768 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4769 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4770 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4771 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4772 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4773 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4774 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4775 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4776 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4779 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4781 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4783 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4784 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4785 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4787 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4788 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4789 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4791 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4792 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4793 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4795 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4796 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4797 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4799 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4800 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4801 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4803 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4804 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4805 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4807 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4808 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4809 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4811 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4812 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4813 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4816 tcx.sess.span_err(it.span,
4817 format!("unrecognized intrinsic function: `{}`",
4818 *other).as_slice());
4823 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4824 fn_style: ast::UnsafeFn,
4825 abi: abi::RustIntrinsic,
4833 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4834 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4835 if i_n_tps != n_tps {
4836 tcx.sess.span_err(it.span,
4837 format!("intrinsic has wrong number of type \
4838 parameters: found {}, expected {}",
4842 require_same_types(tcx,
4849 format!("intrinsic has wrong type: expected `{}`",
4850 ppaux::ty_to_string(ccx.tcx, fty))