1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function). Inference is used to supply types wherever they are
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
26 - main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `typeck::infer` module is in charge
35 of resolving those constraints.
37 - regionck: after main is complete, the regionck pass goes over all
38 types looking for regions and making sure that they did not escape
39 into places they are not in scope. This may also influence the
40 final assignments of the various region variables if there is some
43 - vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
46 - writeback: writes the final types within a function body, replacing
47 type variables with their final inferred types. These final types
48 are written into the `tcx.node_types` table, which should *never* contain
49 any reference to a type variable.
53 While type checking a function, the intermediate types for the
54 expressions, blocks, and so forth contained within the function are
55 stored in `fcx.node_types` and `fcx.item_substs`. These types
56 may contain unresolved type variables. After type checking is
57 complete, the functions in the writeback module are used to take the
58 types from this table, resolve them, and then write them into their
59 permanent home in the type context `ccx.tcx`.
61 This means that during inferencing you should use `fcx.write_ty()`
62 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63 nodes within the function.
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
68 n.b.: A type variable is not the same thing as a type parameter. A
69 type variable is rather an "instance" of a type parameter: that is,
70 given a generic function `fn foo<T>(t: T)`: while checking the
71 function `foo`, the type `ty_param(0)` refers to the type `T`, which
72 is treated in abstract. When `foo()` is called, however, `T` will be
73 substituted for a fresh type variable `N`. This variable will
74 eventually be resolved to some concrete type (which might itself be
80 use middle::const_eval;
82 use middle::pat_util::pat_id_map;
85 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
86 use middle::ty::{FnSig, VariantInfo};
87 use middle::ty::{Polytype};
88 use middle::ty::{ParamTy, Disr, ExprTyProvider};
90 use middle::ty_fold::TypeFolder;
91 use middle::typeck::astconv::AstConv;
92 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
93 use middle::typeck::astconv;
94 use middle::typeck::check::_match::pat_ctxt;
95 use middle::typeck::check::method::{AutoderefReceiver};
96 use middle::typeck::check::method::{AutoderefReceiverFlag};
97 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
98 use middle::typeck::check::method::{DontAutoderefReceiver};
99 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
100 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
101 use middle::typeck::check::regionmanip::relate_free_regions;
102 use middle::typeck::check::vtable::VtableContext;
103 use middle::typeck::CrateCtxt;
104 use middle::typeck::infer::{resolve_type, force_tvar};
105 use middle::typeck::infer;
106 use middle::typeck::rscope::RegionScope;
107 use middle::typeck::{lookup_def_ccx};
108 use middle::typeck::no_params;
109 use middle::typeck::{require_same_types, vtable_map};
110 use middle::typeck::{MethodCall, MethodMap};
111 use middle::typeck::{TypeAndSubsts};
112 use middle::lang_items::TypeIdLangItem;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159 infcx: infer::InferCtxt<'a>,
160 locals: RefCell<NodeMap<ty::t>>,
161 param_env: ty::ParameterEnvironment,
164 node_types: RefCell<NodeMap<ty::t>>,
165 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167 method_map: MethodMap,
168 vtable_map: vtable_map,
169 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(ty::t),
181 /// This expression will be cast to the `ty::t`
182 ExpectCastableToType(ty::t),
186 pub struct FnStyleState {
187 pub def: ast::NodeId,
188 pub fn_style: ast::FnStyle,
193 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
197 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
198 match self.fn_style {
199 // If this unsafe, then if the outer function was already marked as
200 // unsafe we shouldn't attribute the unsafe'ness to the block. This
201 // way the block can be warned about instead of ignoring this
202 // extraneous block (functions are never warned about).
203 ast::UnsafeFn if self.from_fn => *self,
206 let (fn_style, def) = match blk.rules {
207 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208 ast::DefaultBlock => (fn_style, self.def),
210 FnStyleState{ def: def,
218 /// Whether `check_binop` is part of an assignment or not.
219 /// Used to know whether we allow user overloads and to print
220 /// better messages on error.
221 #[deriving(PartialEq)]
222 enum IsBinopAssignment{
228 pub struct FnCtxt<'a> {
229 // This flag is set to true if, during the writeback phase, we encounter
230 // a type error in this function.
231 writeback_errors: Cell<bool>,
233 // Number of errors that had been reported when we started
234 // checking this function. On exit, if we find that *more* errors
235 // have been reported, we will skip regionck and other work that
236 // expects the types within the function to be consistent.
237 err_count_on_creation: uint,
240 ps: RefCell<FnStyleState>,
242 // Sometimes we generate region pointers where the precise region
243 // to use is not known. For example, an expression like `&x.f`
244 // where `x` is of type `@T`: in this case, we will be rooting
245 // `x` onto the stack frame, and we could choose to root it until
246 // the end of (almost) any enclosing block or expression. We
247 // want to pick the narrowest block that encompasses all uses.
249 // What we do in such cases is to generate a region variable with
250 // `region_lb` as a lower bound. The regionck pass then adds
251 // other constraints based on how the variable is used and region
252 // inference selects the ultimate value. Finally, borrowck is
253 // charged with guaranteeing that the value whose address was taken
254 // can actually be made to live as long as it needs to live.
255 region_lb: Cell<ast::NodeId>,
257 inh: &'a Inherited<'a>,
259 ccx: &'a CrateCtxt<'a>,
262 impl<'a> Inherited<'a> {
263 fn new(tcx: &'a ty::ctxt,
264 param_env: ty::ParameterEnvironment)
267 infcx: infer::new_infer_ctxt(tcx),
268 locals: RefCell::new(NodeMap::new()),
269 param_env: param_env,
270 node_types: RefCell::new(NodeMap::new()),
271 item_substs: RefCell::new(NodeMap::new()),
272 adjustments: RefCell::new(NodeMap::new()),
273 method_map: RefCell::new(FnvHashMap::new()),
274 vtable_map: RefCell::new(FnvHashMap::new()),
275 upvar_borrow_map: RefCell::new(HashMap::new()),
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282 inh: &'a Inherited<'a>,
284 region_bnd: ast::NodeId)
287 writeback_errors: Cell::new(false),
288 err_count_on_creation: ccx.tcx.sess.err_count(),
290 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291 region_lb: Cell::new(region_bnd),
297 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
298 // It's kind of a kludge to manufacture a fake function context
299 // and statement context, but we might as well do write the code only once
300 let param_env = ty::ParameterEnvironment {
301 free_substs: subst::Substs::empty(),
302 bounds: subst::VecPerParamSpace::empty()
304 Inherited::new(ccx.tcx, param_env)
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
312 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
319 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
320 fn visit_item(&mut self, i: &ast::Item, _: ()) {
321 check_item(self.ccx, i);
322 visit::walk_item(self, i, ());
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
328 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329 fn visit_item(&mut self, i: &ast::Item, _: ()) {
330 check_item_sized(self.ccx, i);
331 visit::walk_item(self, i, ());
335 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336 let mut visit = CheckItemTypesVisitor { ccx: ccx };
337 visit::walk_crate(&mut visit, krate, ());
339 ccx.tcx.sess.abort_if_errors();
341 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342 visit::walk_crate(&mut visit, krate, ());
345 fn check_bare_fn(ccx: &CrateCtxt,
350 param_env: ty::ParameterEnvironment) {
351 // Compute the fty from point of view of inside fn
352 // (replace any type-scheme with a type)
353 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
355 match ty::get(fty).sty {
356 ty::ty_bare_fn(ref fn_ty) => {
357 let inh = Inherited::new(ccx.tcx, param_env);
358 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
359 decl, id, body, &inh);
361 vtable::resolve_in_block(&fcx, body);
362 regionck::regionck_fn(&fcx, body);
363 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
365 _ => ccx.tcx.sess.impossible_case(body.span,
366 "check_bare_fn: function type expected")
370 struct GatherLocalsVisitor<'a> {
374 impl<'a> GatherLocalsVisitor<'a> {
375 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
378 // infer the variable's type
379 let var_id = self.fcx.infcx().next_ty_var_id();
380 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
381 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
384 // take type that the user specified
385 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
391 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392 // Add explicitly-declared locals.
393 fn visit_local(&mut self, local: &ast::Local, _: ()) {
394 let o_ty = match local.ty.node {
395 ast::TyInfer => None,
396 _ => Some(self.fcx.to_ty(&*local.ty))
398 self.assign(local.id, o_ty);
399 debug!("Local variable {} is assigned type {}",
400 self.fcx.pat_to_str(&*local.pat),
401 self.fcx.infcx().ty_to_str(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
406 // Add pattern bindings.
407 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
409 ast::PatIdent(_, ref path, _)
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(path.segments.get(0).identifier),
414 self.fcx.infcx().ty_to_str(
415 self.fcx.inh.locals.borrow().get_copy(&p.id)));
419 visit::walk_pat(self, p, ());
423 fn visit_block(&mut self, b: &ast::Block, _: ()) {
424 // non-obvious: the `blk` variable maps to region lb, so
425 // we have to keep this up-to-date. This
426 // is... unfortunate. It'd be nice to not need this.
427 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
430 // Don't descend into fns and items
431 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
432 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
433 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438 fn_style: ast::FnStyle,
443 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
446 * Helper used by check_bare_fn and check_expr_fn. Does the
447 * grungy work of checking a function body and returns the
448 * function context used for that purpose, since in the case of a
449 * fn item there is still a bit more to do.
452 * - inherited: other fields inherited from the enclosing fn (if any)
456 let err_count_on_creation = tcx.sess.err_count();
458 // First, we have to replace any bound regions in the fn type with free ones.
459 // The free region references will be bound the node_id of the body block.
460 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
461 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
464 relate_free_regions(tcx, &fn_sig);
466 let arg_tys = fn_sig.inputs.as_slice();
467 let ret_ty = fn_sig.output;
469 debug!("check_fn(arg_tys={}, ret_ty={})",
473 // Create the function context. This is either derived from scratch or,
474 // in the case of function expressions, based on the outer context.
476 writeback_errors: Cell::new(false),
477 err_count_on_creation: err_count_on_creation,
479 ps: RefCell::new(FnStyleState::function(fn_style, id)),
480 region_lb: Cell::new(body.id),
487 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
488 // Add formal parameters.
489 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
490 // Create type variables for each argument.
491 pat_util::pat_bindings(&tcx.def_map,
493 |_bm, pat_id, _sp, _path| {
494 visit.assign(pat_id, None);
497 // Check the pattern.
500 map: pat_id_map(&tcx.def_map, &*input.pat),
502 _match::check_pat(&pcx, &*input.pat, *arg_ty);
505 visit.visit_block(body, ());
508 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
510 // We unify the tail expr's type with the
511 // function result type, if there is a tail expr.
513 Some(ref tail_expr) => {
514 // Special case: we print a special error if there appears
515 // to be do-block/for-loop confusion
516 demand::suptype_with_fn(&fcx, tail_expr.span, false,
517 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
519 fcx.report_mismatched_return_types(sp, e, a, s);
525 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526 fcx.write_ty(input.id, *arg);
532 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
533 assert!(field.id.krate == ast::LOCAL_CRATE);
534 let item = match tcx.map.find(struct_id.node) {
535 Some(ast_map::NodeItem(item)) => item,
536 None => fail!("node not in ast map: {}", struct_id.node),
537 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
541 ast::ItemStruct(struct_def, _) => {
542 match struct_def.fields.iter().find(|f| match f.node.kind {
543 ast::NamedField(ident, _) => ident.name == field.name,
549 .bug(format!("Could not find field {}",
550 token::get_name(field.name)).as_slice())
554 _ => tcx.sess.bug("Field found outside of a struct?"),
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
561 let struct_fields = tcx.struct_fields.borrow();
562 let fields = struct_fields.get(&id);
564 let superstructs = tcx.superstructs.borrow();
565 let super_struct = superstructs.get(&id);
566 match *super_struct {
568 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
569 for f in fields.iter() {
570 match super_fields.iter().find(|sf| f.name == sf.name) {
571 Some(prev_field) => {
572 tcx.sess.span_err(span_for_field(tcx, f, id),
573 format!("field `{}` hides field declared in \
575 token::get_name(f.name)).as_slice());
576 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
577 "previously declared here");
587 fn check_fields_sized(tcx: &ty::ctxt,
588 struct_def: &ast::StructDef) {
589 let len = struct_def.fields.len();
593 for f in struct_def.fields.slice_to(len - 1).iter() {
594 let t = ty::node_id_to_type(tcx, f.node.id);
595 if !ty::type_is_sized(tcx, t) {
597 ast::NamedField(ident, _) => {
600 format!("type `{}` is dynamically sized. \
601 dynamically sized types may only \
602 appear as the type of the final \
604 token::get_ident(ident)).as_slice());
606 ast::UnnamedField(_) => {
607 tcx.sess.span_err(f.span, "dynamically sized type in field");
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
617 check_representable(tcx, span, id, "struct");
618 check_instantiable(tcx, span, id);
620 // Check there are no overlapping fields in super-structs
621 check_for_field_shadowing(tcx, local_def(id));
623 if ty::lookup_simd(tcx, local_def(id)) {
624 check_simd(tcx, span, id);
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629 debug!("check_item(it.id={}, it.ident={})",
631 ty::item_path_str(ccx.tcx, local_def(it.id)));
632 let _indenter = indenter();
635 ast::ItemEnum(ref enum_definition, _) => {
636 check_enum_variants_sized(ccx,
637 enum_definition.variants.as_slice());
639 ast::ItemStruct(..) => {
640 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647 debug!("check_item(it.id={}, it.ident={})",
649 ty::item_path_str(ccx.tcx, local_def(it.id)));
650 let _indenter = indenter();
653 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654 ast::ItemEnum(ref enum_definition, _) => {
655 check_enum_variants(ccx,
657 enum_definition.variants.as_slice(),
660 ast::ItemFn(ref decl, _, _, _, ref body) => {
661 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
663 let param_env = ty::construct_parameter_environment(ccx.tcx,
667 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
669 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
672 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
674 check_method_body(ccx, &impl_pty.generics, &**m);
677 match *opt_trait_ref {
678 Some(ref ast_trait_ref) => {
680 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681 check_impl_methods_against_trait(ccx,
686 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
692 ast::ItemTrait(_, _, _, ref trait_methods) => {
693 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
694 for trait_method in (*trait_methods).iter() {
695 match *trait_method {
697 // Nothing to do, since required methods don't have
701 check_method_body(ccx, &trait_def.generics, &*m);
706 ast::ItemStruct(..) => {
707 check_struct(ccx, it.id, it.span);
709 ast::ItemTy(ref t, ref generics) => {
710 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
711 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
713 ast::ItemForeignMod(ref m) => {
714 if m.abi == abi::RustIntrinsic {
715 for item in m.items.iter() {
716 check_intrinsic_type(ccx, &**item);
719 for item in m.items.iter() {
720 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
721 if !pty.generics.types.is_empty() {
722 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
726 ast::ForeignItemFn(ref fn_decl, _) => {
727 if fn_decl.variadic && m.abi != abi::C {
728 ccx.tcx.sess.span_err(
729 item.span, "variadic function must have C calling convention");
737 _ => {/* nothing to do */ }
741 fn check_method_body(ccx: &CrateCtxt,
742 item_generics: &ty::Generics,
743 method: &ast::Method) {
745 * Type checks a method body.
748 * - `item_generics`: generics defined on the impl/trait that contains
750 * - `self_bound`: bound for the `Self` type parameter, if any
751 * - `method`: the method definition
754 debug!("check_method_body(item_generics={}, method.id={})",
755 item_generics.repr(ccx.tcx),
757 let method_def_id = local_def(method.id);
758 let method_ty = ty::method(ccx.tcx, method_def_id);
759 let method_generics = &method_ty.generics;
761 let param_env = ty::construct_parameter_environment(ccx.tcx,
765 let fty = ty::node_id_to_type(ccx.tcx, method.id);
767 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
772 ast_trait_ref: &ast::TraitRef,
773 impl_trait_ref: &ty::TraitRef,
774 impl_methods: &[Gc<ast::Method>]) {
775 // Locate trait methods
777 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
779 // Check existing impl methods to see if they are both present in trait
780 // and compatible with trait signature
781 for impl_method in impl_methods.iter() {
782 let impl_method_def_id = local_def(impl_method.id);
783 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
785 // If this is an impl of a trait method, find the corresponding
786 // method definition in the trait.
787 let opt_trait_method_ty =
788 trait_methods.iter().
789 find(|tm| tm.ident.name == impl_method_ty.ident.name);
790 match opt_trait_method_ty {
791 Some(trait_method_ty) => {
792 compare_impl_method(ccx.tcx,
797 &impl_trait_ref.substs);
800 // This is span_bug as it should have already been caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_ident(impl_method_ty.ident),
806 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
811 // Check for missing methods from trait
812 let provided_methods = ty::provided_trait_methods(tcx,
813 impl_trait_ref.def_id);
814 let mut missing_methods = Vec::new();
815 for trait_method in trait_methods.iter() {
817 impl_methods.iter().any(
818 |m| m.ident.name == trait_method.ident.name);
820 provided_methods.iter().any(
821 |m| m.ident.name == trait_method.ident.name);
822 if !is_implemented && !is_provided {
823 missing_methods.push(
824 format!("`{}`", token::get_ident(trait_method.ident)));
828 if !missing_methods.is_empty() {
831 format!("not all trait methods implemented, missing: {}",
832 missing_methods.connect(", ")).as_slice());
837 * Checks that a method from an impl/class conforms to the signature of
838 * the same method as declared in the trait.
842 * - impl_generics: the generics declared on the impl itself (not the method!)
843 * - impl_m: type of the method we are checking
844 * - impl_m_span: span to use for reporting errors
845 * - impl_m_body_id: id of the method body
846 * - trait_m: the method in the trait
847 * - trait_to_impl_substs: the substitutions used on the type of the trait
849 fn compare_impl_method(tcx: &ty::ctxt,
852 impl_m_body_id: ast::NodeId,
853 trait_m: &ty::Method,
854 trait_to_impl_substs: &subst::Substs) {
855 debug!("compare_impl_method()");
856 let infcx = infer::new_infer_ctxt(tcx);
858 // Try to give more informative error messages about self typing
859 // mismatches. Note that any mismatch will also be detected
860 // below, where we construct a canonical function type that
861 // includes the self parameter as a normal parameter. It's just
862 // that the error messages you get out of this code are a bit more
863 // inscrutable, particularly for cases where one method has no
865 match (&trait_m.explicit_self, &impl_m.explicit_self) {
866 (&ast::SelfStatic, &ast::SelfStatic) => {}
867 (&ast::SelfStatic, _) => {
870 format!("method `{}` has a `{}` declaration in the impl, \
871 but not in the trait",
872 token::get_ident(trait_m.ident),
873 pprust::explicit_self_to_str(
874 impl_m.explicit_self)).as_slice());
877 (_, &ast::SelfStatic) => {
880 format!("method `{}` has a `{}` declaration in the trait, \
881 but not in the impl",
882 token::get_ident(trait_m.ident),
883 pprust::explicit_self_to_str(
884 trait_m.explicit_self)).as_slice());
888 // Let the type checker catch other errors below
892 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
893 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
894 if num_impl_m_type_params != num_trait_m_type_params {
897 format!("method `{}` has {} type parameter{} \
898 but its trait declaration has {} type parameter{}",
899 token::get_ident(trait_m.ident),
900 num_impl_m_type_params,
901 if num_impl_m_type_params == 1 {""} else {"s"},
902 num_trait_m_type_params,
903 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
907 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
910 format!("method `{}` has {} parameter{} \
911 but the declaration in trait `{}` has {}",
912 token::get_ident(trait_m.ident),
913 impl_m.fty.sig.inputs.len(),
914 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
915 ty::item_path_str(tcx, trait_m.def_id),
916 trait_m.fty.sig.inputs.len()).as_slice());
920 let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
921 .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
923 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
924 // Check that the impl does not require any builtin-bounds
925 // that the trait does not guarantee:
927 impl_param_def.bounds.builtin_bounds -
928 trait_param_def.bounds.builtin_bounds;
929 if !extra_bounds.is_empty() {
932 format!("in method `{}`, \
933 type parameter {} requires `{}`, \
934 which is not required by \
935 the corresponding type parameter \
936 in the trait declaration",
937 token::get_ident(trait_m.ident),
939 extra_bounds.user_string(tcx)).as_slice());
943 // FIXME(#2687)---we should be checking that the bounds of the
944 // trait imply the bounds of the subtype, but it appears we
945 // are...not checking this.
946 if impl_param_def.bounds.trait_bounds.len() !=
947 trait_param_def.bounds.trait_bounds.len()
949 let found = impl_param_def.bounds.trait_bounds.len();
950 let expected = trait_param_def.bounds.trait_bounds.len();
953 format!("in method `{}`, type parameter {} has {} trait \
954 bound{}, but the corresponding type parameter in \
955 the trait declaration has {} trait bound{}",
956 token::get_ident(trait_m.ident),
959 if found == 1 {""} else {"s"},
961 if expected == 1 {""} else {"s"}).as_slice());
966 // This code is best explained by example. Consider a trait:
969 // fn method<'a,M>(t: T, m: &'a M) -> Self;
974 // impl<'i, U> Trait<&'i U> for Foo {
975 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
978 // We wish to decide if those two method types are compatible.
980 // We start out with trait_to_impl_substs, that maps the trait type
981 // parameters to impl type parameters:
983 // trait_to_impl_substs = {T => &'i U, Self => Foo}
985 // We create a mapping `dummy_substs` that maps from the impl type
986 // parameters to fresh types and regions. For type parameters,
987 // this is the identity transform, but we could as well use any
988 // skolemized types. For regions, we convert from bound to free
989 // regions (Note: but only early-bound regions, i.e., those
990 // declared on the impl or used in type parameter bounds).
992 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
994 // Now we can apply skol_substs to the type of the impl method
995 // to yield a new function type in terms of our fresh, skolemized
998 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1000 // We now want to extract and substitute the type of the *trait*
1001 // method and compare it. To do so, we must create a compound
1002 // substitution by combining trait_to_impl_substs and
1003 // impl_to_skol_substs, and also adding a mapping for the method
1004 // type parameters. We extend the mapping to also include
1005 // the method parameters.
1007 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1009 // Applying this to the trait method type yields:
1011 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1013 // This type is also the same but the name of the bound region ('a
1014 // vs 'b). However, the normal subtyping rules on fn types handle
1015 // this kind of equivalency just fine.
1017 // Create mapping from impl to skolemized.
1019 impl_m.generics.types.map(
1020 |d| ty::mk_param_from_def(tcx, d));
1022 impl_m.generics.regions.map(
1023 |l| ty::free_region_from_def(impl_m_body_id, l));
1024 let impl_to_skol_substs =
1025 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1027 // Compute skolemized form of impl method ty.
1028 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1029 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1031 // Compute skolemized form of trait method ty.
1032 let trait_to_skol_substs =
1033 trait_to_impl_substs
1034 .subst(tcx, &impl_to_skol_substs)
1035 .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
1036 skol_regions.get_vec(subst::FnSpace).clone());
1037 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1038 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1040 // Check the impl method type IM is a subtype of the trait method
1041 // type TM. To see why this makes sense, think of a vtable. The
1042 // expected type of the function pointers in the vtable is the
1043 // type TM of the trait method. The actual type will be the type
1044 // IM of the impl method. Because we know that IM <: TM, that
1045 // means that anywhere a TM is expected, a IM will do instead. In
1046 // other words, anyone expecting to call a method with the type
1047 // from the trait, can safely call a method with the type from the
1049 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1050 impl_fty, trait_fty) {
1055 format!("method `{}` has an incompatible type for trait: {}",
1056 token::get_ident(trait_m.ident),
1057 ty::type_err_to_str(tcx, terr)).as_slice());
1058 ty::note_and_explain_type_err(tcx, terr);
1063 fn check_cast(fcx: &FnCtxt,
1068 // Find the type of `e`. Supply hints based on the type we are casting to,
1070 let t_1 = fcx.to_ty(t);
1071 let t_1 = structurally_resolved_type(fcx, span, t_1);
1073 if ty::type_is_scalar(t_1) {
1074 // Supply the type as a hint so as to influence integer
1075 // literals and other things that might care.
1076 check_expr_with_hint(fcx, e, t_1)
1081 let t_e = fcx.expr_ty(e);
1083 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
1084 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
1086 if ty::type_is_error(t_e) {
1087 fcx.write_error(id);
1090 if ty::type_is_bot(t_e) {
1095 if ty::type_is_trait(t_1) {
1096 // This will be looked up later on.
1097 fcx.write_ty(id, t_1);
1101 let t_1 = structurally_resolved_type(fcx, span, t_1);
1102 let t_e = structurally_resolved_type(fcx, span, t_e);
1104 if ty::type_is_nil(t_e) {
1105 fcx.type_error_message(span, |actual| {
1106 format!("cast from nil: `{}` as `{}`",
1108 fcx.infcx().ty_to_str(t_1))
1110 } else if ty::type_is_nil(t_1) {
1111 fcx.type_error_message(span, |actual| {
1112 format!("cast to nil: `{}` as `{}`",
1114 fcx.infcx().ty_to_str(t_1))
1118 let t_1_is_scalar = ty::type_is_scalar(t_1);
1119 let t_1_is_char = ty::type_is_char(t_1);
1120 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1121 let t_1_is_float = ty::type_is_floating_point(t_1);
1123 // casts to scalars other than `char` and `bare fn` are trivial
1124 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1125 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1127 fcx.type_error_message(span, |actual| {
1128 format!("illegal cast; cast through an \
1129 integer first: `{}` as `{}`",
1131 fcx.infcx().ty_to_str(t_1))
1134 // casts from C-like enums are allowed
1135 } else if t_1_is_char {
1136 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1137 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1138 fcx.type_error_message(span, |actual| {
1139 format!("only `u8` can be cast as \
1140 `char`, not `{}`", actual)
1143 } else if ty::get(t_1).sty == ty::ty_bool {
1147 "cannot cast as `bool`, compare with zero instead");
1148 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1149 fn types_compatible(fcx: &FnCtxt, sp: Span,
1150 t1: ty::t, t2: ty::t) -> bool {
1151 if !ty::type_is_vec(t1) {
1152 // If the type being casted from is not a vector, this special
1153 // case does not apply.
1156 if ty::type_needs_infer(t2) {
1157 // This prevents this special case from going off when casting
1158 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1163 let el = ty::sequence_element_type(fcx.tcx(), t1);
1164 infer::mk_eqty(fcx.infcx(),
1171 // Due to the limitations of LLVM global constants,
1172 // region pointers end up pointing at copies of
1173 // vector elements instead of the original values.
1174 // To allow unsafe pointers to work correctly, we
1175 // need to special-case obtaining an unsafe pointer
1176 // from a region pointer to a vector.
1178 /* this cast is only allowed from &[T] to *T or
1180 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1181 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1182 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1183 if types_compatible(fcx, e.span, mt1, mt2) => {
1184 /* this case is allowed */
1187 demand::coerce(fcx, e.span, t_1, &*e);
1190 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1192 If more type combinations should be supported than are
1193 supported here, then file an enhancement issue and
1194 record the issue number in this comment.
1196 fcx.type_error_message(span, |actual| {
1197 format!("non-scalar cast: `{}` as `{}`",
1199 fcx.infcx().ty_to_str(t_1))
1203 fcx.write_ty(id, t_1);
1206 impl<'a> AstConv for FnCtxt<'a> {
1207 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1209 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1210 ty::lookup_item_type(self.tcx(), id)
1213 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1214 ty::lookup_trait_def(self.tcx(), id)
1217 fn ty_infer(&self, _span: Span) -> ty::t {
1218 self.infcx().next_ty_var()
1222 impl<'a> FnCtxt<'a> {
1223 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1227 pub fn err_count_since_creation(&self) -> uint {
1228 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1231 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1233 infcx: self.infcx(),
1234 param_env: &self.inh.param_env
1239 impl<'a> RegionScope for infer::InferCtxt<'a> {
1240 fn anon_regions(&self, span: Span, count: uint)
1241 -> Result<Vec<ty::Region> , ()> {
1242 Ok(Vec::from_fn(count, |_| {
1243 self.next_region_var(infer::MiscVariable(span))
1248 impl<'a> FnCtxt<'a> {
1249 pub fn tag(&self) -> String {
1250 format!("{}", self as *const FnCtxt)
1253 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1254 match self.inh.locals.borrow().find(&nid) {
1257 self.tcx().sess.span_bug(
1259 format!("no type for local variable {:?}",
1266 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1267 debug!("write_ty({}, {}) in fcx {}",
1268 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1269 self.inh.node_types.borrow_mut().insert(node_id, ty);
1272 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1273 if !substs.substs.is_noop() {
1274 debug!("write_substs({}, {}) in fcx {}",
1276 substs.repr(self.tcx()),
1279 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1283 pub fn write_ty_substs(&self,
1284 node_id: ast::NodeId,
1286 substs: ty::ItemSubsts) {
1287 let ty = ty.subst(self.tcx(), &substs.substs);
1288 self.write_ty(node_id, ty);
1289 self.write_substs(node_id, substs);
1292 pub fn write_autoderef_adjustment(&self,
1293 node_id: ast::NodeId,
1295 if derefs == 0 { return; }
1296 self.write_adjustment(
1298 ty::AutoDerefRef(ty::AutoDerefRef {
1304 pub fn write_adjustment(&self,
1305 node_id: ast::NodeId,
1306 adj: ty::AutoAdjustment) {
1307 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1308 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1311 pub fn write_nil(&self, node_id: ast::NodeId) {
1312 self.write_ty(node_id, ty::mk_nil());
1314 pub fn write_bot(&self, node_id: ast::NodeId) {
1315 self.write_ty(node_id, ty::mk_bot());
1317 pub fn write_error(&self, node_id: ast::NodeId) {
1318 self.write_ty(node_id, ty::mk_err());
1321 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1322 ast_ty_to_ty(self, self.infcx(), ast_t)
1325 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1326 pat.repr(self.tcx())
1329 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1330 match self.inh.node_types.borrow().find(&ex.id) {
1333 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1334 self.tag()).as_slice());
1339 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1340 match self.inh.node_types.borrow().find(&id) {
1343 self.tcx().sess.bug(
1344 format!("no type for node {}: {} in fcx {}",
1345 id, self.tcx().map.node_to_str(id),
1346 self.tag()).as_slice());
1351 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1352 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1353 Some(method) => method.substs.clone(),
1355 self.tcx().sess.bug(
1356 format!("no method entry for node {}: {} in fcx {}",
1357 id, self.tcx().map.node_to_str(id),
1358 self.tag()).as_slice());
1363 pub fn opt_node_ty_substs(&self,
1365 f: |&ty::ItemSubsts|) {
1366 match self.inh.item_substs.borrow().find(&id) {
1372 pub fn mk_subty(&self,
1373 a_is_expected: bool,
1374 origin: infer::TypeOrigin,
1377 -> Result<(), ty::type_err> {
1378 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1381 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1382 -> Result<(), ty::type_err> {
1383 infer::can_mk_subty(self.infcx(), sub, sup)
1386 pub fn mk_assignty(&self,
1390 -> Result<(), ty::type_err> {
1391 match infer::mk_coercety(self.infcx(),
1393 infer::ExprAssignable(expr.span),
1397 Err(ref e) => Err((*e)),
1398 Ok(Some(adjustment)) => {
1399 self.write_adjustment(expr.id, adjustment);
1405 pub fn mk_eqty(&self,
1406 a_is_expected: bool,
1407 origin: infer::TypeOrigin,
1410 -> Result<(), ty::type_err> {
1411 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1414 pub fn mk_subr(&self,
1415 a_is_expected: bool,
1416 origin: infer::SubregionOrigin,
1419 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1422 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1423 let old_region_lb = self.region_lb.get();
1424 self.region_lb.set(lb);
1426 self.region_lb.set(old_region_lb);
1430 pub fn type_error_message(&self,
1432 mk_msg: |String| -> String,
1434 err: Option<&ty::type_err>) {
1435 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1438 pub fn report_mismatched_return_types(&self,
1442 err: &ty::type_err) {
1444 if ty::type_is_error(e) || ty::type_is_error(a) {
1447 self.infcx().report_mismatched_types(sp, e, a, err)
1450 pub fn report_mismatched_types(&self,
1454 err: &ty::type_err) {
1455 self.infcx().report_mismatched_types(sp, e, a, err)
1459 pub enum LvaluePreference {
1464 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1465 expr_id: Option<ast::NodeId>,
1466 mut lvalue_pref: LvaluePreference,
1467 should_stop: |ty::t, uint| -> Option<T>)
1468 -> (ty::t, uint, Option<T>) {
1470 * Executes an autoderef loop for the type `t`. At each step, invokes
1471 * `should_stop` to decide whether to terminate the loop. Returns
1472 * the final type and number of derefs that it performed.
1474 * Note: this method does not modify the adjustments table. The caller is
1475 * responsible for inserting an AutoAdjustment record into the `fcx`
1476 * using one of the suitable methods.
1479 let mut t = base_ty;
1480 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1481 let resolved_t = structurally_resolved_type(fcx, sp, t);
1483 match should_stop(resolved_t, autoderefs) {
1484 Some(x) => return (resolved_t, autoderefs, Some(x)),
1488 // Otherwise, deref if type is derefable:
1489 let mt = match ty::deref(resolved_t, false) {
1490 Some(mt) => Some(mt),
1492 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1493 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1499 if mt.mutbl == ast::MutImmutable {
1500 lvalue_pref = NoPreference;
1503 None => return (resolved_t, autoderefs, None)
1507 // We've reached the recursion limit, error gracefully.
1508 fcx.tcx().sess.span_err(sp,
1509 format!("reached the recursion limit while auto-dereferencing {}",
1510 base_ty.repr(fcx.tcx())).as_slice());
1511 (ty::mk_err(), 0, None)
1514 /// Attempts to resolve a call expression as an overloaded call.
1515 fn try_overloaded_call(fcx: &FnCtxt,
1516 call_expression: &ast::Expr,
1517 callee: Gc<ast::Expr>,
1519 args: &[Gc<ast::Expr>])
1521 // Try `FnOnce`, then `FnMut`, then `Fn`.
1522 for &(maybe_function_trait, method_name) in [
1523 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1524 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1525 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1527 let function_trait = match maybe_function_trait {
1529 Some(function_trait) => function_trait,
1531 let method_callee = match method::lookup_in_trait(
1533 call_expression.span,
1539 DontAutoderefReceiver,
1540 IgnoreStaticMethods) {
1542 Some(method_callee) => method_callee,
1544 let method_call = MethodCall::expr(call_expression.id);
1545 let output_type = check_method_argument_types(fcx,
1546 call_expression.span,
1552 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1553 write_call(fcx, call_expression, output_type);
1555 if !fcx.tcx().sess.features.overloaded_calls.get() {
1556 fcx.tcx().sess.span_err(call_expression.span,
1557 "overloaded calls are experimental");
1558 fcx.tcx().sess.span_note(call_expression.span,
1559 "add `#[feature(overloaded_calls)]` to \
1560 the crate attributes to enable");
1569 fn try_overloaded_deref(fcx: &FnCtxt,
1571 method_call: Option<MethodCall>,
1572 base_expr: Option<&ast::Expr>,
1574 lvalue_pref: LvaluePreference)
1576 // Try DerefMut first, if preferred.
1577 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1578 (PreferMutLvalue, Some(trait_did)) => {
1579 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1580 token::intern("deref_mut"), trait_did,
1581 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1586 // Otherwise, fall back to Deref.
1587 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1588 (None, Some(trait_did)) => {
1589 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1590 token::intern("deref"), trait_did,
1591 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1593 (method, _) => method
1598 let ref_ty = ty::ty_fn_ret(method.ty);
1600 Some(method_call) => {
1601 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1605 ty::deref(ref_ty, true)
1611 fn check_method_argument_types(fcx: &FnCtxt,
1613 method_fn_ty: ty::t,
1614 callee_expr: &ast::Expr,
1615 args: &[Gc<ast::Expr>],
1616 deref_args: DerefArgs,
1617 tuple_arguments: TupleArgumentsFlag)
1619 // HACK(eddyb) ignore provided self (it has special typeck rules).
1620 let args = if tuple_arguments == DontTupleArguments {
1625 if ty::type_is_error(method_fn_ty) {
1626 let err_inputs = err_args(args.len());
1627 check_argument_types(fcx,
1629 err_inputs.as_slice(),
1637 match ty::get(method_fn_ty).sty {
1638 ty::ty_bare_fn(ref fty) => {
1639 // HACK(eddyb) ignore self in the definition (see above).
1640 check_argument_types(fcx,
1642 fty.sig.inputs.slice_from(1),
1651 fcx.tcx().sess.span_bug(callee_expr.span,
1652 "method without bare fn type");
1658 fn check_argument_types(fcx: &FnCtxt,
1660 fn_inputs: &[ty::t],
1661 callee_expr: &ast::Expr,
1662 args: &[Gc<ast::Expr>],
1663 deref_args: DerefArgs,
1665 tuple_arguments: TupleArgumentsFlag) {
1668 * Generic function that factors out common logic from
1669 * function calls, method calls and overloaded operators.
1672 let tcx = fcx.ccx.tcx;
1674 // Grab the argument types, supplying fresh type variables
1675 // if the wrong number of arguments were supplied
1676 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1682 let expected_arg_count = fn_inputs.len();
1683 let formal_tys = if tuple_arguments == TupleArguments {
1684 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1685 match ty::get(tuple_type).sty {
1686 ty::ty_tup(ref arg_types) => {
1687 if arg_types.len() != args.len() {
1689 "this function takes {} parameter{} \
1690 but {} parameter{} supplied",
1692 if arg_types.len() == 1 {""} else {"s"},
1694 if args.len() == 1 {" was"} else {"s were"});
1695 tcx.sess.span_err(sp, msg.as_slice());
1696 err_args(args.len())
1698 (*arg_types).clone()
1702 if args.len() != 0 {
1704 "this function takes 0 parameters \
1705 but {} parameter{} supplied",
1707 if args.len() == 1 {" was"} else {"s were"});
1708 tcx.sess.span_err(sp, msg.as_slice());
1715 "cannot use call notation; the first type \
1716 parameter for the function trait is neither a \
1718 err_args(supplied_arg_count)
1721 } else if expected_arg_count == supplied_arg_count {
1722 fn_inputs.iter().map(|a| *a).collect()
1723 } else if variadic {
1724 if supplied_arg_count >= expected_arg_count {
1725 fn_inputs.iter().map(|a| *a).collect()
1728 "this function takes at least {} parameter{} \
1729 but {} parameter{} supplied",
1731 if expected_arg_count == 1 {""} else {"s"},
1733 if supplied_arg_count == 1 {" was"} else {"s were"});
1735 tcx.sess.span_err(sp, msg.as_slice());
1737 err_args(supplied_arg_count)
1741 "this function takes {} parameter{} \
1742 but {} parameter{} supplied",
1744 if expected_arg_count == 1 {""} else {"s"},
1746 if supplied_arg_count == 1 {" was"} else {"s were"});
1748 tcx.sess.span_err(sp, msg.as_slice());
1750 err_args(supplied_arg_count)
1753 debug!("check_argument_types: formal_tys={:?}",
1754 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1756 // Check the arguments.
1757 // We do this in a pretty awful way: first we typecheck any arguments
1758 // that are not anonymous functions, then we typecheck the anonymous
1759 // functions. This is so that we have more information about the types
1760 // of arguments when we typecheck the functions. This isn't really the
1761 // right way to do this.
1762 let xs = [false, true];
1763 for check_blocks in xs.iter() {
1764 let check_blocks = *check_blocks;
1765 debug!("check_blocks={}", check_blocks);
1767 // More awful hacks: before we check the blocks, try to do
1768 // an "opportunistic" vtable resolution of any trait
1769 // bounds on the call.
1771 vtable::early_resolve_expr(callee_expr, fcx, true);
1774 // For variadic functions, we don't have a declared type for all of
1775 // the arguments hence we only do our usual type checking with
1776 // the arguments who's types we do know.
1777 let t = if variadic {
1779 } else if tuple_arguments == TupleArguments {
1784 for (i, arg) in args.iter().take(t).enumerate() {
1785 let is_block = match arg.node {
1786 ast::ExprFnBlock(..) |
1787 ast::ExprProc(..) => true,
1791 if is_block == check_blocks {
1792 debug!("checking the argument");
1793 let mut formal_ty = *formal_tys.get(i);
1797 match ty::get(formal_ty).sty {
1798 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1801 // So we hit this case when one implements the
1802 // operator traits but leaves an argument as
1803 // just T instead of &T. We'll catch it in the
1804 // mismatch impl/trait method phase no need to
1807 formal_ty = ty::mk_err();
1814 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1820 // We also need to make sure we at least write the ty of the other
1821 // arguments which we skipped above.
1823 for arg in args.iter().skip(expected_arg_count) {
1824 check_expr(fcx, &**arg);
1826 // There are a few types which get autopromoted when passed via varargs
1827 // in C but we just error out instead and require explicit casts.
1828 let arg_ty = structurally_resolved_type(fcx, arg.span,
1829 fcx.expr_ty(&**arg));
1830 match ty::get(arg_ty).sty {
1831 ty::ty_float(ast::TyF32) => {
1832 fcx.type_error_message(arg.span,
1834 format!("can't pass an {} to variadic \
1835 function, cast to c_double", t)
1838 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1839 fcx.type_error_message(arg.span, |t| {
1840 format!("can't pass {} to variadic \
1841 function, cast to c_int",
1845 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1846 fcx.type_error_message(arg.span, |t| {
1847 format!("can't pass {} to variadic \
1848 function, cast to c_uint",
1858 fn err_args(len: uint) -> Vec<ty::t> {
1859 Vec::from_fn(len, |_| ty::mk_err())
1862 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1863 fcx.write_ty(call_expr.id, output);
1866 // AST fragment checking
1867 fn check_lit(fcx: &FnCtxt,
1869 expected: Expectation)
1872 let tcx = fcx.ccx.tcx;
1875 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1876 ast::LitBinary(..) => {
1877 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1879 ast::LitByte(_) => ty::mk_u8(),
1880 ast::LitChar(_) => ty::mk_char(),
1881 ast::LitInt(_, t) => ty::mk_mach_int(t),
1882 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1883 ast::LitIntUnsuffixed(_) => {
1884 let opt_ty = expected.map_to_option(fcx, |sty| {
1886 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1887 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1888 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1889 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1890 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1894 opt_ty.unwrap_or_else(
1895 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1897 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1898 ast::LitFloatUnsuffixed(_) => {
1899 let opt_ty = expected.map_to_option(fcx, |sty| {
1901 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
1905 opt_ty.unwrap_or_else(
1906 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
1908 ast::LitNil => ty::mk_nil(),
1909 ast::LitBool(_) => ty::mk_bool()
1913 pub fn valid_range_bounds(ccx: &CrateCtxt,
1917 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1918 Some(val) => Some(val <= 0),
1923 pub fn check_expr_has_type(fcx: &FnCtxt,
1926 check_expr_with_unifier(
1927 fcx, expr, ExpectHasType(expected), NoPreference,
1928 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
1931 fn check_expr_coercable_to_type(fcx: &FnCtxt,
1934 check_expr_with_unifier(
1935 fcx, expr, ExpectHasType(expected), NoPreference,
1936 || demand::coerce(fcx, expr.span, expected, expr));
1939 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1940 check_expr_with_unifier(
1941 fcx, expr, ExpectHasType(expected), NoPreference,
1945 fn check_expr_with_expectation(fcx: &FnCtxt,
1947 expected: Expectation) {
1948 check_expr_with_unifier(
1949 fcx, expr, expected, NoPreference,
1953 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
1955 expected: Expectation,
1956 lvalue_pref: LvaluePreference)
1958 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1961 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1962 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
1965 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1966 lvalue_pref: LvaluePreference) {
1967 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
1971 // determine the `self` type, using fresh variables for all variables
1972 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1973 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1975 pub fn impl_self_ty(vcx: &VtableContext,
1976 span: Span, // (potential) receiver for this impl
1979 let tcx = vcx.tcx();
1981 let ity = ty::lookup_item_type(tcx, did);
1982 let (n_tps, rps, raw_ty) =
1983 (ity.generics.types.len(subst::TypeSpace),
1984 ity.generics.regions.get_vec(subst::TypeSpace),
1987 let rps = vcx.infcx.region_vars_for_defs(span, rps);
1988 let tps = vcx.infcx.next_ty_vars(n_tps);
1989 let substs = subst::Substs::new_type(tps, rps);
1990 let substd_ty = raw_ty.subst(tcx, &substs);
1992 TypeAndSubsts { substs: substs, ty: substd_ty }
1995 // Only for fields! Returns <none> for methods>
1996 // Indifferent to privacy flags
1997 pub fn lookup_field_ty(tcx: &ty::ctxt,
1998 class_id: ast::DefId,
1999 items: &[ty::field_ty],
2000 fieldname: ast::Name,
2001 substs: &subst::Substs) -> Option<ty::t> {
2003 let o_field = items.iter().find(|f| f.name == fieldname);
2004 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2007 // Controls whether the arguments are automatically referenced. This is useful
2008 // for overloaded binary and unary operators.
2009 pub enum DerefArgs {
2014 /// Controls whether the arguments are tupled. This is used for the call
2017 /// Tupling means that all call-side arguments are packed into a tuple and
2018 /// passed as a single parameter. For example, if tupling is enabled, this
2021 /// fn f(x: (int, int))
2023 /// Can be called as:
2030 #[deriving(Clone, Eq, PartialEq)]
2031 enum TupleArgumentsFlag {
2037 /// If an expression has any sub-expressions that result in a type error,
2038 /// inspecting that expression's type with `ty::type_is_error` will return
2039 /// true. Likewise, if an expression is known to diverge, inspecting its
2040 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2041 /// strict, _|_ can appear in the type of an expression that does not,
2042 /// itself, diverge: for example, fn() -> _|_.)
2043 /// Note that inspecting a type's structure *directly* may expose the fact
2044 /// that there are actually multiple representations for both `ty_err` and
2045 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2046 fn check_expr_with_unifier(fcx: &FnCtxt,
2048 expected: Expectation,
2049 lvalue_pref: LvaluePreference,
2052 debug!(">> typechecking");
2054 // A generic function for doing all of the checking for call expressions
2055 fn check_call(fcx: &FnCtxt,
2056 call_expr: &ast::Expr,
2058 args: &[Gc<ast::Expr>]) {
2059 // Store the type of `f` as the type of the callee
2060 let fn_ty = fcx.expr_ty(f);
2062 // Extract the function signature from `in_fty`.
2063 let fn_sty = structure_of(fcx, f.span, fn_ty);
2065 // This is the "default" function signature, used in case of error.
2066 // In that case, we check each argument against "error" in order to
2067 // set up all the node type bindings.
2068 let error_fn_sig = FnSig {
2069 binder_id: ast::CRATE_NODE_ID,
2070 inputs: err_args(args.len()),
2071 output: ty::mk_err(),
2075 let fn_sig = match *fn_sty {
2076 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2077 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2079 fcx.type_error_message(call_expr.span, |actual| {
2080 format!("expected function but found `{}`", actual)
2086 // Replace any bound regions that appear in the function
2087 // signature with region variables
2088 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2089 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2092 // Call the generic checker.
2093 check_argument_types(fcx,
2095 fn_sig.inputs.as_slice(),
2100 DontTupleArguments);
2102 write_call(fcx, call_expr, fn_sig.output);
2105 // Checks a method call.
2106 fn check_method_call(fcx: &FnCtxt,
2108 method_name: ast::SpannedIdent,
2109 args: &[Gc<ast::Expr>],
2110 tps: &[ast::P<ast::Ty>]) {
2111 let rcvr = args[0].clone();
2112 // We can't know if we need &mut self before we look up the method,
2113 // so treat the receiver as mutable just in case - only explicit
2114 // overloaded dereferences care about the distinction.
2115 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2117 // no need to check for bot/err -- callee does that
2118 let expr_t = structurally_resolved_type(fcx,
2120 fcx.expr_ty(&*rcvr));
2122 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2123 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2124 method_name.node.name,
2125 expr_t, tps.as_slice(),
2127 CheckTraitsAndInherentMethods,
2128 AutoderefReceiver, IgnoreStaticMethods) {
2130 let method_ty = method.ty;
2131 let method_call = MethodCall::expr(expr.id);
2132 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2136 debug!("(checking method call) failing expr is {}", expr.id);
2138 fcx.type_error_message(method_name.span,
2140 format!("type `{}` does not implement any \
2141 method in scope named `{}`",
2143 token::get_ident(method_name.node))
2148 // Add error type for the result
2149 fcx.write_error(expr.id);
2151 // Check for potential static matches (missing self parameters)
2155 method_name.node.name,
2159 CheckTraitsAndInherentMethods,
2160 DontAutoderefReceiver,
2161 ReportStaticMethods);
2167 // Call the generic checker.
2168 let ret_ty = check_method_argument_types(fcx,
2174 DontTupleArguments);
2176 write_call(fcx, expr, ret_ty);
2179 // A generic function for checking the then and else in an if
2181 fn check_then_else(fcx: &FnCtxt,
2182 cond_expr: &ast::Expr,
2183 then_blk: &ast::Block,
2184 opt_else_expr: Option<Gc<ast::Expr>>,
2187 expected: Expectation) {
2188 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2190 let branches_ty = match opt_else_expr {
2191 Some(ref else_expr) => {
2192 // Disregard "castable to" expectations because they
2193 // can lead us astray. Consider for example `if cond
2194 // {22} else {c} as u8` -- if we propagate the
2195 // "castable to u8" constraint to 22, it will pick the
2196 // type 22u8, which is overly constrained (c might not
2197 // be a u8). In effect, the problem is that the
2198 // "castable to" expectation is not the tightest thing
2199 // we can say, so we want to drop it in this case.
2200 // The tightest thing we can say is "must unify with
2201 // else branch". Note that in the case of a "has type"
2202 // constraint, this limitation does not hold.
2203 let expected = expected.only_has_type();
2205 check_block_with_expected(fcx, then_blk, expected);
2206 let then_ty = fcx.node_ty(then_blk.id);
2207 check_expr_with_expectation(fcx, &**else_expr, expected);
2208 let else_ty = fcx.expr_ty(&**else_expr);
2209 infer::common_supertype(fcx.infcx(),
2210 infer::IfExpression(sp),
2216 check_block_no_value(fcx, then_blk);
2221 let cond_ty = fcx.expr_ty(cond_expr);
2222 let if_ty = if ty::type_is_error(cond_ty) {
2224 } else if ty::type_is_bot(cond_ty) {
2230 fcx.write_ty(id, if_ty);
2233 fn lookup_op_method(fcx: &FnCtxt,
2237 trait_did: Option<ast::DefId>,
2238 args: &[Gc<ast::Expr>],
2239 autoderef_receiver: AutoderefReceiverFlag,
2240 unbound_method: ||) -> ty::t {
2241 let method = match trait_did {
2242 Some(trait_did) => {
2243 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2244 trait_did, self_t, [], autoderef_receiver,
2245 IgnoreStaticMethods)
2251 let method_ty = method.ty;
2252 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2253 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2254 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2255 check_method_argument_types(fcx,
2265 // Check the args anyway
2266 // so we get all the error messages
2267 let expected_ty = ty::mk_err();
2268 check_method_argument_types(fcx,
2274 DontTupleArguments);
2280 // could be either an expr_binop or an expr_assign_binop
2281 fn check_binop(fcx: &FnCtxt,
2286 is_binop_assignment: IsBinopAssignment) {
2287 let tcx = fcx.ccx.tcx;
2289 let lvalue_pref = match is_binop_assignment {
2290 BinopAssignment => PreferMutLvalue,
2291 SimpleBinop => NoPreference
2293 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2295 // Callee does bot / err checking
2296 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2297 fcx.expr_ty(&*lhs));
2299 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2300 // Shift is a special case: rhs must be uint, no matter what lhs is
2301 check_expr_has_type(fcx, rhs, ty::mk_uint());
2302 fcx.write_ty(expr.id, lhs_t);
2306 if ty::is_binopable(tcx, lhs_t, op) {
2307 let tvar = fcx.infcx().next_ty_var();
2308 demand::suptype(fcx, expr.span, tvar, lhs_t);
2309 check_expr_has_type(fcx, &*rhs, tvar);
2311 let result_t = match op {
2312 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2314 if ty::type_is_simd(tcx, lhs_t) {
2315 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2316 fcx.type_error_message(expr.span,
2318 format!("binary comparison \
2319 operation `{}` not \
2320 supported for floating \
2321 point SIMD vector `{}`",
2322 ast_util::binop_to_str(op),
2339 fcx.write_ty(expr.id, result_t);
2343 if op == ast::BiOr || op == ast::BiAnd {
2344 // This is an error; one of the operands must have the wrong
2346 fcx.write_error(expr.id);
2347 fcx.write_error(rhs.id);
2348 fcx.type_error_message(expr.span,
2350 format!("binary operation `{}` cannot be applied \
2352 ast_util::binop_to_str(op),
2359 // Check for overloaded operators if not an assignment.
2360 let result_t = if is_binop_assignment == SimpleBinop {
2361 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2363 fcx.type_error_message(expr.span,
2365 format!("binary assignment \
2367 cannot be applied to \
2369 ast_util::binop_to_str(op),
2374 check_expr(fcx, &*rhs);
2378 fcx.write_ty(expr.id, result_t);
2379 if ty::type_is_error(result_t) {
2380 fcx.write_ty(rhs.id, result_t);
2384 fn check_user_binop(fcx: &FnCtxt,
2386 lhs_expr: Gc<ast::Expr>,
2387 lhs_resolved_t: ty::t,
2389 rhs: Gc<ast::Expr>) -> ty::t {
2390 let tcx = fcx.ccx.tcx;
2391 let lang = &tcx.lang_items;
2392 let (name, trait_did) = match op {
2393 ast::BiAdd => ("add", lang.add_trait()),
2394 ast::BiSub => ("sub", lang.sub_trait()),
2395 ast::BiMul => ("mul", lang.mul_trait()),
2396 ast::BiDiv => ("div", lang.div_trait()),
2397 ast::BiRem => ("rem", lang.rem_trait()),
2398 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2399 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2400 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2401 ast::BiShl => ("shl", lang.shl_trait()),
2402 ast::BiShr => ("shr", lang.shr_trait()),
2403 ast::BiLt => ("lt", lang.ord_trait()),
2404 ast::BiLe => ("le", lang.ord_trait()),
2405 ast::BiGe => ("ge", lang.ord_trait()),
2406 ast::BiGt => ("gt", lang.ord_trait()),
2407 ast::BiEq => ("eq", lang.eq_trait()),
2408 ast::BiNe => ("ne", lang.eq_trait()),
2409 ast::BiAnd | ast::BiOr => {
2410 check_expr(fcx, &*rhs);
2411 return ty::mk_err();
2414 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2415 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2416 fcx.type_error_message(ex.span, |actual| {
2417 format!("binary operation `{}` cannot be applied to type `{}`",
2418 ast_util::binop_to_str(op),
2420 }, lhs_resolved_t, None)
2424 fn check_user_unop(fcx: &FnCtxt,
2427 trait_did: Option<ast::DefId>,
2429 rhs_expr: Gc<ast::Expr>,
2430 rhs_t: ty::t) -> ty::t {
2431 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2432 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2433 fcx.type_error_message(ex.span, |actual| {
2434 format!("cannot apply unary operator `{}` to type `{}`",
2440 fn check_expr_fn(fcx: &FnCtxt,
2442 store: ty::TraitStore,
2444 body: ast::P<ast::Block>,
2445 expected: Expectation) {
2446 let tcx = fcx.ccx.tcx;
2448 // Find the expected input/output types (if any). Substitute
2449 // fresh bound regions for any bound regions we find in the
2450 // expected types so as to avoid capture.
2451 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2454 expected_bounds) = {
2455 match expected_sty {
2456 Some(ty::ty_closure(ref cenv)) => {
2458 replace_late_bound_regions_in_fn_sig(
2460 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2461 let onceness = match (&store, &cenv.store) {
2462 // As the closure type and onceness go, only three
2463 // combinations are legit:
2467 // If the actual and expected closure type disagree with
2468 // each other, set expected onceness to be always Once or
2469 // Many according to the actual type. Otherwise, it will
2470 // yield either an illegal "many proc" or a less known
2471 // "once closure" in the error message.
2472 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2473 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2475 (&ty::UniqTraitStore, _) => ast::Once,
2476 (&ty::RegionTraitStore(..), _) => ast::Many,
2478 (Some(sig), onceness, cenv.bounds)
2481 // Not an error! Means we're inferring the closure type
2482 let mut bounds = ty::empty_builtin_bounds();
2483 let onceness = match expr.node {
2484 ast::ExprProc(..) => {
2485 bounds.add(ty::BoundSend);
2490 (None, onceness, bounds)
2495 // construct the function type
2496 let fn_ty = astconv::ty_of_closure(fcx,
2504 let fty_sig = fn_ty.sig.clone();
2505 let fty = ty::mk_closure(tcx, fn_ty);
2506 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2508 fcx.write_ty(expr.id, fty);
2510 // If the closure is a stack closure and hasn't had some non-standard
2511 // style inferred for it, then check it under its parent's style.
2512 // Otherwise, use its own
2513 let (inherited_style, id) = match store {
2514 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2515 fcx.ps.borrow().def),
2516 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2519 check_fn(fcx.ccx, inherited_style, &fty_sig,
2520 &*decl, id, &*body, fcx.inh);
2524 // Check field access expressions
2525 fn check_field(fcx: &FnCtxt,
2527 lvalue_pref: LvaluePreference,
2529 field: &ast::SpannedIdent,
2530 tys: &[ast::P<ast::Ty>]) {
2531 let tcx = fcx.ccx.tcx;
2532 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2533 let expr_t = structurally_resolved_type(fcx, expr.span,
2535 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2536 let (_, autoderefs, field_ty) =
2537 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2538 match ty::get(base_t).sty {
2539 ty::ty_struct(base_id, ref substs) => {
2540 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2541 let fields = ty::lookup_struct_fields(tcx, base_id);
2542 lookup_field_ty(tcx, base_id, fields.as_slice(),
2543 field.node.name, &(*substs))
2550 fcx.write_ty(expr.id, field_ty);
2551 fcx.write_autoderef_adjustment(base.id, autoderefs);
2557 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2558 match method::lookup(fcx,
2565 CheckTraitsAndInherentMethods,
2567 IgnoreStaticMethods) {
2569 fcx.type_error_message(
2572 format!("attempted to take value of method `{}` on type \
2573 `{}`", token::get_ident(field.node), actual)
2577 tcx.sess.span_note(field.span,
2578 "maybe a missing `()` to call it? If not, try an anonymous function.");
2582 fcx.type_error_message(
2585 format!("attempted access of field `{}` on \
2586 type `{}`, but no field with that \
2588 token::get_ident(field.node),
2595 fcx.write_error(expr.id);
2598 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2601 class_id: ast::DefId,
2602 node_id: ast::NodeId,
2603 substitutions: subst::Substs,
2604 field_types: &[ty::field_ty],
2605 ast_fields: &[ast::Field],
2606 check_completeness: bool) {
2607 let tcx = fcx.ccx.tcx;
2609 let mut class_field_map = HashMap::new();
2610 let mut fields_found = 0;
2611 for field in field_types.iter() {
2612 class_field_map.insert(field.name, (field.id, false));
2615 let mut error_happened = false;
2617 // Typecheck each field.
2618 for field in ast_fields.iter() {
2619 let mut expected_field_type = ty::mk_err();
2621 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2624 fcx.type_error_message(
2627 format!("structure `{}` has no field named `{}`",
2628 actual, token::get_ident(field.ident.node))
2632 error_happened = true;
2634 Some((_, true)) => {
2637 format!("field `{}` specified more than once",
2638 token::get_ident(field.ident
2639 .node)).as_slice());
2640 error_happened = true;
2642 Some((field_id, false)) => {
2643 expected_field_type =
2644 ty::lookup_field_type(
2645 tcx, class_id, field_id, &substitutions);
2646 class_field_map.insert(
2647 field.ident.node.name, (field_id, true));
2651 // Make sure to give a type to the field even if there's
2652 // an error, so we can continue typechecking
2653 check_expr_coercable_to_type(
2656 expected_field_type);
2660 fcx.write_error(node_id);
2663 if check_completeness && !error_happened {
2664 // Make sure the programmer specified all the fields.
2665 assert!(fields_found <= field_types.len());
2666 if fields_found < field_types.len() {
2667 let mut missing_fields = Vec::new();
2668 for class_field in field_types.iter() {
2669 let name = class_field.name;
2670 let (_, seen) = *class_field_map.get(&name);
2672 missing_fields.push(
2673 format!("`{}`", token::get_name(name).get()))
2677 tcx.sess.span_err(span,
2679 "missing field{}: {fields}",
2680 if missing_fields.len() == 1 {""} else {"s"},
2681 fields = missing_fields.connect(", ")).as_slice());
2685 if !error_happened {
2686 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2687 class_id, substitutions));
2691 fn check_struct_constructor(fcx: &FnCtxt,
2693 span: codemap::Span,
2694 class_id: ast::DefId,
2695 fields: &[ast::Field],
2696 base_expr: Option<Gc<ast::Expr>>) {
2697 let tcx = fcx.ccx.tcx;
2699 // Look up the number of type parameters and the raw type, and
2700 // determine whether the class is region-parameterized.
2701 let item_type = ty::lookup_item_type(tcx, class_id);
2702 let raw_type = item_type.ty;
2704 // Generate the struct type.
2705 let substitutions = fcx.infcx().fresh_substs_for_type(
2706 span, &item_type.generics);
2707 let mut struct_type = raw_type.subst(tcx, &substitutions);
2709 // Look up and check the fields.
2710 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2711 check_struct_or_variant_fields(fcx,
2717 class_fields.as_slice(),
2719 base_expr.is_none());
2720 if ty::type_is_error(fcx.node_ty(id)) {
2721 struct_type = ty::mk_err();
2724 // Check the base expression if necessary.
2727 Some(base_expr) => {
2728 check_expr_has_type(fcx, &*base_expr, struct_type);
2729 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2730 struct_type = ty::mk_bot();
2735 // Write in the resulting type.
2736 fcx.write_ty(id, struct_type);
2739 fn check_struct_enum_variant(fcx: &FnCtxt,
2741 span: codemap::Span,
2742 enum_id: ast::DefId,
2743 variant_id: ast::DefId,
2744 fields: &[ast::Field]) {
2745 let tcx = fcx.ccx.tcx;
2747 // Look up the number of type parameters and the raw type, and
2748 // determine whether the enum is region-parameterized.
2749 let item_type = ty::lookup_item_type(tcx, enum_id);
2750 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2751 let enum_type = item_type.ty.subst(tcx, &substitutions);
2753 // Look up and check the enum variant fields.
2754 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2755 check_struct_or_variant_fields(fcx,
2761 variant_fields.as_slice(),
2764 fcx.write_ty(id, enum_type);
2767 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2769 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2770 expected: Expectation)
2771 -> (ExprCheckerWithTy, ty::t) {
2772 let tcx = fcx.ccx.tcx;
2773 let (coerce, t) = match expected {
2774 // If we're given an expected type, we can try to coerce to it
2775 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2776 // Otherwise we just leave the type to be resolved later
2777 _ => (false, fcx.infcx().next_ty_var())
2780 (check_expr_coercable_to_type, t)
2782 (check_expr_has_type, t)
2786 let tcx = fcx.ccx.tcx;
2789 ast::ExprVstore(ev, vst) => {
2790 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2791 let typ = match ev.node {
2792 ast::ExprVec(ref args) => {
2793 let mutability = match vst {
2794 ast::ExprVstoreMutSlice => ast::MutMutable,
2795 _ => ast::MutImmutable,
2797 let mut any_error = false;
2798 let mut any_bot = false;
2799 for e in args.iter() {
2800 check(fcx, &**e, t);
2801 let arg_t = fcx.expr_ty(&**e);
2802 if ty::type_is_error(arg_t) {
2805 else if ty::type_is_bot(arg_t) {
2814 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2815 ty::mt{ ty: ty::mk_vec(tcx,
2816 ty::mt {ty: t, mutbl: mutability},
2818 mutbl: mutability })
2821 ast::ExprRepeat(ref element, ref count_expr) => {
2822 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2823 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2824 let mutability = match vst {
2825 ast::ExprVstoreMutSlice => ast::MutMutable,
2826 _ => ast::MutImmutable,
2828 check(fcx, &**element, t);
2829 let arg_t = fcx.expr_ty(&**element);
2830 if ty::type_is_error(arg_t) {
2832 } else if ty::type_is_bot(arg_t) {
2835 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2836 ty::mt{ ty: ty::mk_vec(tcx,
2837 ty::mt {ty: t, mutbl: mutability},
2842 ast::ExprLit(_) => {
2843 let error = if vst == ast::ExprVstoreSlice {
2844 "`&\"string\"` has been removed; use `\"string\"` instead"
2846 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2848 tcx.sess.span_err(expr.span, error);
2851 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2853 fcx.write_ty(ev.id, typ);
2854 fcx.write_ty(id, typ);
2857 ast::ExprBox(ref place, ref subexpr) => {
2858 check_expr(fcx, &**place);
2859 check_expr(fcx, &**subexpr);
2861 let mut checked = false;
2863 ast::ExprPath(ref path) => {
2864 // FIXME(pcwalton): For now we hardcode the two permissible
2865 // places: the exchange heap and the managed heap.
2866 let definition = lookup_def(fcx, path.span, place.id);
2867 let def_id = definition.def_id();
2868 if tcx.lang_items.exchange_heap() == Some(def_id) {
2869 fcx.write_ty(id, ty::mk_uniq(tcx,
2870 fcx.expr_ty(&**subexpr)));
2872 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2873 fcx.write_ty(id, ty::mk_box(tcx,
2874 fcx.expr_ty(&**subexpr)));
2882 tcx.sess.span_err(expr.span,
2883 "only the managed heap and exchange heap are \
2884 currently supported");
2885 fcx.write_ty(id, ty::mk_err());
2889 ast::ExprLit(lit) => {
2890 let typ = check_lit(fcx, lit, expected);
2891 fcx.write_ty(id, typ);
2893 ast::ExprBinary(op, ref lhs, ref rhs) => {
2894 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2896 let lhs_ty = fcx.expr_ty(&**lhs);
2897 let rhs_ty = fcx.expr_ty(&**rhs);
2898 if ty::type_is_error(lhs_ty) ||
2899 ty::type_is_error(rhs_ty) {
2900 fcx.write_error(id);
2902 else if ty::type_is_bot(lhs_ty) ||
2903 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2907 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2908 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
2910 let lhs_t = fcx.expr_ty(&**lhs);
2911 let result_t = fcx.expr_ty(expr);
2912 demand::suptype(fcx, expr.span, result_t, lhs_t);
2914 let tcx = fcx.tcx();
2915 if !ty::expr_is_lval(tcx, &**lhs) {
2916 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2919 // Overwrite result of check_binop...this preserves existing behavior
2920 // but seems quite dubious with regard to user-defined methods
2921 // and so forth. - Niko
2922 if !ty::type_is_error(result_t)
2923 && !ty::type_is_bot(result_t) {
2924 fcx.write_nil(expr.id);
2927 ast::ExprUnary(unop, ref oprnd) => {
2928 let expected = expected.only_has_type();
2929 let expected_inner = expected.map(fcx, |sty| {
2931 ast::UnBox | ast::UnUniq => match *sty {
2932 ty::ty_box(ty) | ty::ty_uniq(ty) => {
2939 ast::UnNot | ast::UnNeg => {
2947 let lvalue_pref = match unop {
2948 ast::UnDeref => lvalue_pref,
2951 check_expr_with_expectation_and_lvalue_pref(
2952 fcx, &**oprnd, expected_inner, lvalue_pref);
2953 let mut oprnd_t = fcx.expr_ty(&**oprnd);
2954 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2957 oprnd_t = ty::mk_box(tcx, oprnd_t)
2960 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2963 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2964 oprnd_t = match ty::deref(oprnd_t, true) {
2966 None => match try_overloaded_deref(fcx, expr.span,
2967 Some(MethodCall::expr(expr.id)),
2968 Some(&**oprnd), oprnd_t, lvalue_pref) {
2971 let is_newtype = match ty::get(oprnd_t).sty {
2972 ty::ty_struct(did, ref substs) => {
2973 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2975 && fields.get(0).ident ==
2976 token::special_idents::unnamed_field
2981 // This is an obsolete struct deref
2982 tcx.sess.span_err(expr.span,
2983 "single-field tuple-structs can \
2984 no longer be dereferenced");
2986 fcx.type_error_message(expr.span, |actual| {
2987 format!("type `{}` cannot be \
2988 dereferenced", actual)
2997 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2999 if !(ty::type_is_integral(oprnd_t) ||
3000 ty::get(oprnd_t).sty == ty::ty_bool) {
3001 oprnd_t = check_user_unop(fcx, "!", "not",
3002 tcx.lang_items.not_trait(),
3003 expr, oprnd.clone(), oprnd_t);
3007 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3009 if !(ty::type_is_integral(oprnd_t) ||
3010 ty::type_is_fp(oprnd_t)) {
3011 oprnd_t = check_user_unop(fcx, "-", "neg",
3012 tcx.lang_items.neg_trait(),
3013 expr, oprnd.clone(), oprnd_t);
3018 fcx.write_ty(id, oprnd_t);
3020 ast::ExprAddrOf(mutbl, ref oprnd) => {
3021 let expected = expected.only_has_type();
3022 let hint = expected.map(fcx, |sty| {
3023 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3024 _ => NoExpectation }
3026 let lvalue_pref = match mutbl {
3027 ast::MutMutable => PreferMutLvalue,
3028 ast::MutImmutable => NoPreference
3030 check_expr_with_expectation_and_lvalue_pref(fcx,
3035 // Note: at this point, we cannot say what the best lifetime
3036 // is to use for resulting pointer. We want to use the
3037 // shortest lifetime possible so as to avoid spurious borrowck
3038 // errors. Moreover, the longest lifetime will depend on the
3039 // precise details of the value whose address is being taken
3040 // (and how long it is valid), which we don't know yet until type
3041 // inference is complete.
3043 // Therefore, here we simply generate a region variable. The
3044 // region inferencer will then select the ultimate value.
3045 // Finally, borrowck is charged with guaranteeing that the
3046 // value whose address was taken can actually be made to live
3047 // as long as it needs to live.
3048 let region = fcx.infcx().next_region_var(
3049 infer::AddrOfRegion(expr.span));
3051 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3052 let oprnd_t = if ty::type_is_error(tm.ty) {
3054 } else if ty::type_is_bot(tm.ty) {
3058 ty::mk_rptr(tcx, region, tm)
3060 fcx.write_ty(id, oprnd_t);
3062 ast::ExprPath(ref pth) => {
3063 let defn = lookup_def(fcx, pth.span, id);
3064 let pty = polytype_for_def(fcx, expr.span, defn);
3065 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3067 ast::ExprInlineAsm(ref ia) => {
3068 for &(_, ref input) in ia.inputs.iter() {
3069 check_expr(fcx, &**input);
3071 for &(_, ref out) in ia.outputs.iter() {
3072 check_expr(fcx, &**out);
3076 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3077 ast::ExprBreak(_) => { fcx.write_bot(id); }
3078 ast::ExprAgain(_) => { fcx.write_bot(id); }
3079 ast::ExprRet(ref expr_opt) => {
3080 let ret_ty = fcx.ret_ty;
3082 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3083 ret_ty, ty::mk_nil()) {
3084 Ok(_) => { /* fall through */ }
3088 "`return;` in function returning non-nil");
3092 check_expr_has_type(fcx, &**e, ret_ty);
3097 ast::ExprParen(a) => {
3098 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3099 fcx.write_ty(id, fcx.expr_ty(a));
3101 ast::ExprAssign(ref lhs, ref rhs) => {
3102 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3104 let tcx = fcx.tcx();
3105 if !ty::expr_is_lval(tcx, &**lhs) {
3106 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3109 let lhs_ty = fcx.expr_ty(&**lhs);
3110 check_expr_has_type(fcx, &**rhs, lhs_ty);
3111 let rhs_ty = fcx.expr_ty(&**rhs);
3113 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3114 fcx.write_error(id);
3115 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3121 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3122 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3123 id, expr.span, expected);
3125 ast::ExprWhile(ref cond, ref body) => {
3126 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3127 check_block_no_value(fcx, &**body);
3128 let cond_ty = fcx.expr_ty(&**cond);
3129 let body_ty = fcx.node_ty(body.id);
3130 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3131 fcx.write_error(id);
3133 else if ty::type_is_bot(cond_ty) {
3140 ast::ExprForLoop(..) =>
3141 fail!("non-desugared expr_for_loop"),
3142 ast::ExprLoop(ref body, _) => {
3143 check_block_no_value(fcx, &**body);
3144 if !may_break(tcx, expr.id, body.clone()) {
3151 ast::ExprMatch(ref discrim, ref arms) => {
3152 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3154 ast::ExprFnBlock(ref decl, ref body) => {
3155 let region = astconv::opt_ast_region_to_region(fcx,
3161 ty::RegionTraitStore(region, ast::MutMutable),
3166 ast::ExprProc(ref decl, ref body) => {
3174 ast::ExprBlock(ref b) => {
3175 check_block_with_expected(fcx, &**b, expected);
3176 fcx.write_ty(id, fcx.node_ty(b.id));
3178 ast::ExprCall(ref f, ref args) => {
3179 // Index expressions need to be handled separately, to inform them
3180 // that they appear in call position.
3181 check_expr(fcx, &**f);
3182 let f_ty = fcx.expr_ty(&**f);
3184 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3185 check_call(fcx, expr, &**f, args.as_slice());
3186 let (args_bot, args_err) = args.iter().fold((false, false),
3187 |(rest_bot, rest_err), a| {
3188 // is this not working?
3189 let a_ty = fcx.expr_ty(&**a);
3190 (rest_bot || ty::type_is_bot(a_ty),
3191 rest_err || ty::type_is_error(a_ty))});
3192 if ty::type_is_error(f_ty) || args_err {
3193 fcx.write_error(id);
3195 else if ty::type_is_bot(f_ty) || args_bot {
3200 ast::ExprMethodCall(ident, ref tps, ref args) => {
3201 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3202 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3203 let (args_bot, args_err) = arg_tys.fold((false, false),
3204 |(rest_bot, rest_err), a| {
3205 (rest_bot || ty::type_is_bot(a),
3206 rest_err || ty::type_is_error(a))});
3208 fcx.write_error(id);
3209 } else if args_bot {
3213 ast::ExprCast(ref e, ref t) => {
3214 check_cast(fcx, &**e, &**t, id, expr.span);
3216 ast::ExprVec(ref args) => {
3217 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3218 for e in args.iter() {
3219 check(fcx, &**e, t);
3221 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3223 fcx.write_ty(id, typ);
3225 ast::ExprRepeat(ref element, ref count_expr) => {
3226 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3227 let count = ty::eval_repeat_count(fcx, &**count_expr);
3228 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3229 check(fcx, &**element, t);
3230 let element_ty = fcx.expr_ty(&**element);
3231 if ty::type_is_error(element_ty) {
3232 fcx.write_error(id);
3234 else if ty::type_is_bot(element_ty) {
3238 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3240 fcx.write_ty(id, t);
3243 ast::ExprTup(ref elts) => {
3244 let expected = expected.only_has_type();
3245 let flds = expected.map_to_option(fcx, |sty| {
3247 ty::ty_tup(ref flds) => Some((*flds).clone()),
3251 let mut bot_field = false;
3252 let mut err_field = false;
3254 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3255 let opt_hint = match flds {
3256 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3259 check_expr_with_expectation(fcx, *e, opt_hint);
3260 let t = fcx.expr_ty(*e);
3261 err_field = err_field || ty::type_is_error(t);
3262 bot_field = bot_field || ty::type_is_bot(t);
3267 } else if err_field {
3268 fcx.write_error(id);
3270 let typ = ty::mk_tup(tcx, elt_ts);
3271 fcx.write_ty(id, typ);
3274 ast::ExprStruct(ref path, ref fields, base_expr) => {
3275 // Resolve the path.
3276 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3278 Some(def::DefStruct(type_def_id)) => {
3279 check_struct_constructor(fcx, id, expr.span, type_def_id,
3280 fields.as_slice(), base_expr);
3282 Some(def::DefVariant(enum_id, variant_id, _)) => {
3283 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3284 variant_id, fields.as_slice());
3287 tcx.sess.span_bug(path.span,
3288 "structure constructor does not name a structure type");
3292 ast::ExprField(ref base, ref field, ref tys) => {
3293 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3295 ast::ExprIndex(ref base, ref idx) => {
3296 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3297 check_expr(fcx, &**idx);
3298 let raw_base_t = fcx.expr_ty(&**base);
3299 let idx_t = fcx.expr_ty(&**idx);
3300 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3301 fcx.write_ty(id, raw_base_t);
3302 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3303 fcx.write_ty(id, idx_t);
3305 let (base_t, autoderefs, field_ty) =
3306 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3307 lvalue_pref, |base_t, _| ty::index(base_t));
3310 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3311 fcx.write_ty(id, mt.ty);
3312 fcx.write_autoderef_adjustment(base.id, autoderefs);
3315 let resolved = structurally_resolved_type(fcx,
3318 let ret_ty = lookup_op_method(fcx,
3321 token::intern("index"),
3322 tcx.lang_items.index_trait(),
3323 [base.clone(), idx.clone()],
3326 fcx.type_error_message(expr.span,
3328 format!("cannot index a \
3335 fcx.write_ty(id, ret_ty);
3342 debug!("type of expr({}) {} is...", expr.id,
3343 syntax::print::pprust::expr_to_str(expr));
3344 debug!("... {}, expected is {}",
3345 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3352 fn only_has_type(self) -> Expectation {
3354 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3355 ExpectHasType(t) => ExpectHasType(t)
3359 // Resolves `expected` by a single level if it is a variable. If
3360 // there is no expected type or resolution is not possible (e.g.,
3361 // no constraints yet present), just returns `None`.
3362 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3367 ExpectCastableToType(t) => {
3368 ExpectCastableToType(
3369 fcx.infcx().resolve_type_vars_if_possible(t))
3371 ExpectHasType(t) => {
3373 fcx.infcx().resolve_type_vars_if_possible(t))
3378 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3379 match self.resolve(fcx) {
3380 NoExpectation => NoExpectation,
3381 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3385 fn map_to_option<O>(self,
3387 unpack: |&ty::sty| -> Option<O>)
3390 match self.resolve(fcx) {
3391 NoExpectation => None,
3392 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3397 impl Repr for Expectation {
3398 fn repr(&self, tcx: &ty::ctxt) -> String {
3400 NoExpectation => format!("NoExpectation"),
3401 ExpectHasType(t) => format!("ExpectHasType({})",
3403 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3409 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3410 if !type_is_uint(fcx, sp, t) {
3411 fcx.type_error_message(sp, |actual| {
3412 format!("mismatched types: expected `uint` type but found `{}`",
3418 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3419 if !type_is_integral(fcx, sp, t) {
3420 fcx.type_error_message(sp, |actual| {
3421 format!("mismatched types: expected integral type but found `{}`",
3427 pub fn check_decl_initializer(fcx: &FnCtxt,
3431 let local_ty = fcx.local_ty(init.span, nid);
3432 check_expr_coercable_to_type(fcx, init, local_ty)
3435 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3436 let tcx = fcx.ccx.tcx;
3438 let t = fcx.local_ty(local.span, local.id);
3439 fcx.write_ty(local.id, t);
3443 check_decl_initializer(fcx, local.id, &**init);
3444 let init_ty = fcx.expr_ty(&**init);
3445 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3446 fcx.write_ty(local.id, init_ty);
3452 let pcx = pat_ctxt {
3454 map: pat_id_map(&tcx.def_map, &*local.pat),
3456 _match::check_pat(&pcx, &*local.pat, t);
3457 let pat_ty = fcx.node_ty(local.pat.id);
3458 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3459 fcx.write_ty(local.id, pat_ty);
3463 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3465 let mut saw_bot = false;
3466 let mut saw_err = false;
3468 ast::StmtDecl(decl, id) => {
3471 ast::DeclLocal(ref l) => {
3472 check_decl_local(fcx, &**l);
3473 let l_t = fcx.node_ty(l.id);
3474 saw_bot = saw_bot || ty::type_is_bot(l_t);
3475 saw_err = saw_err || ty::type_is_error(l_t);
3477 ast::DeclItem(_) => {/* ignore for now */ }
3480 ast::StmtExpr(ref expr, id) => {
3482 // Check with expected type of ()
3483 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3484 let expr_ty = fcx.expr_ty(&**expr);
3485 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3486 saw_err = saw_err || ty::type_is_error(expr_ty);
3488 ast::StmtSemi(ref expr, id) => {
3490 check_expr(fcx, &**expr);
3491 let expr_ty = fcx.expr_ty(&**expr);
3492 saw_bot |= ty::type_is_bot(expr_ty);
3493 saw_err |= ty::type_is_error(expr_ty);
3495 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3498 fcx.write_bot(node_id);
3501 fcx.write_error(node_id);
3504 fcx.write_nil(node_id)
3508 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3509 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3510 let blkty = fcx.node_ty(blk.id);
3511 if ty::type_is_error(blkty) {
3512 fcx.write_error(blk.id);
3514 else if ty::type_is_bot(blkty) {
3515 fcx.write_bot(blk.id);
3518 let nilty = ty::mk_nil();
3519 demand::suptype(fcx, blk.span, nilty, blkty);
3523 fn check_block_with_expected(fcx: &FnCtxt,
3525 expected: Expectation) {
3527 let mut fcx_ps = fcx.ps.borrow_mut();
3528 let fn_style_state = fcx_ps.recurse(blk);
3529 replace(&mut *fcx_ps, fn_style_state)
3532 fcx.with_region_lb(blk.id, || {
3533 let mut warned = false;
3534 let mut last_was_bot = false;
3535 let mut any_bot = false;
3536 let mut any_err = false;
3537 for s in blk.stmts.iter() {
3538 check_stmt(fcx, &**s);
3539 let s_id = ast_util::stmt_id(&**s);
3540 let s_ty = fcx.node_ty(s_id);
3541 if last_was_bot && !warned && match s.node {
3542 ast::StmtDecl(decl, _) => {
3544 ast::DeclLocal(_) => true,
3548 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3554 .add_lint(lint::builtin::UNREACHABLE_CODE,
3557 "unreachable statement".to_string());
3560 if ty::type_is_bot(s_ty) {
3561 last_was_bot = true;
3563 any_bot = any_bot || ty::type_is_bot(s_ty);
3564 any_err = any_err || ty::type_is_error(s_ty);
3567 None => if any_err {
3568 fcx.write_error(blk.id);
3571 fcx.write_bot(blk.id);
3574 fcx.write_nil(blk.id);
3577 if any_bot && !warned {
3581 .add_lint(lint::builtin::UNREACHABLE_CODE,
3584 "unreachable expression".to_string());
3586 check_expr_with_expectation(fcx, e, expected);
3587 let ety = fcx.expr_ty(e);
3588 fcx.write_ty(blk.id, ety);
3590 fcx.write_error(blk.id);
3593 fcx.write_bot(blk.id);
3599 *fcx.ps.borrow_mut() = prev;
3602 pub fn check_const(ccx: &CrateCtxt,
3606 let inh = blank_inherited_fields(ccx);
3607 let rty = ty::node_id_to_type(ccx.tcx, id);
3608 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3609 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3610 check_const_with_ty(&fcx, sp, e, declty);
3613 pub fn check_const_with_ty(fcx: &FnCtxt,
3617 // Gather locals in statics (because of block expressions).
3618 // This is technically unnecessary because locals in static items are forbidden,
3619 // but prevents type checking from blowing up before const checking can properly
3621 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3624 let cty = fcx.expr_ty(e);
3625 demand::suptype(fcx, e.span, declty, cty);
3626 regionck::regionck_expr(fcx, e);
3627 writeback::resolve_type_vars_in_expr(fcx, e);
3630 /// Checks whether a type can be represented in memory. In particular, it
3631 /// identifies types that contain themselves without indirection through a
3632 /// pointer, which would mean their size is unbounded. This is different from
3633 /// the question of whether a type can be instantiated. See the definition of
3634 /// `check_instantiable`.
3635 pub fn check_representable(tcx: &ty::ctxt,
3637 item_id: ast::NodeId,
3638 designation: &str) -> bool {
3639 let rty = ty::node_id_to_type(tcx, item_id);
3641 // Check that it is possible to represent this type. This call identifies
3642 // (1) types that contain themselves and (2) types that contain a different
3643 // recursive type. It is only necessary to throw an error on those that
3644 // contain themselves. For case 2, there must be an inner type that will be
3645 // caught by case 1.
3646 match ty::is_type_representable(tcx, sp, rty) {
3647 ty::SelfRecursive => {
3649 sp, format!("illegal recursive {} type; \
3650 wrap the inner value in a box to make it representable",
3651 designation).as_slice());
3654 ty::Representable | ty::ContainsRecursive => (),
3659 /// Checks whether a type can be created without an instance of itself.
3660 /// This is similar but different from the question of whether a type
3661 /// can be represented. For example, the following type:
3663 /// enum foo { None, Some(foo) }
3665 /// is instantiable but is not representable. Similarly, the type
3667 /// enum foo { Some(@foo) }
3669 /// is representable, but not instantiable.
3670 pub fn check_instantiable(tcx: &ty::ctxt,
3672 item_id: ast::NodeId)
3674 let item_ty = ty::node_id_to_type(tcx, item_id);
3675 if !ty::is_instantiable(tcx, item_ty) {
3678 format!("this type cannot be instantiated without an \
3679 instance of itself; consider using \
3681 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3688 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3689 let t = ty::node_id_to_type(tcx, id);
3690 if ty::type_needs_subst(t) {
3691 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3694 match ty::get(t).sty {
3695 ty::ty_struct(did, ref substs) => {
3696 let fields = ty::lookup_struct_fields(tcx, did);
3697 if fields.is_empty() {
3698 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3701 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3702 if !fields.iter().all(
3703 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3704 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3707 if !ty::type_is_machine(e) {
3708 tcx.sess.span_err(sp, "SIMD vector element type should be \
3717 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3718 vs: &[ast::P<ast::Variant>]) {
3719 for &v in vs.iter() {
3721 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3722 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3723 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3724 let len = arg_tys.len();
3728 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3729 // Allow the last field in an enum to be unsized.
3730 // We want to do this so that we can support smart pointers.
3731 // A struct value with an unsized final field is itself
3732 // unsized and we must track this in the type system.
3733 if !ty::type_is_sized(ccx.tcx, *t) {
3737 args.get(i).ty.span,
3738 format!("type `{}` is dynamically sized. \
3739 dynamically sized types may only \
3740 appear as the final type in a \
3742 ppaux::ty_to_str(ccx.tcx,
3747 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3753 pub fn check_enum_variants(ccx: &CrateCtxt,
3755 vs: &[ast::P<ast::Variant>],
3758 fn disr_in_range(ccx: &CrateCtxt,
3760 disr: ty::Disr) -> bool {
3761 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3763 ast::TyU8 => disr as u8 as Disr == disr,
3764 ast::TyU16 => disr as u16 as Disr == disr,
3765 ast::TyU32 => disr as u32 as Disr == disr,
3766 ast::TyU64 => disr as u64 as Disr == disr,
3767 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3770 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3772 ast::TyI8 => disr as i8 as Disr == disr,
3773 ast::TyI16 => disr as i16 as Disr == disr,
3774 ast::TyI32 => disr as i32 as Disr == disr,
3775 ast::TyI64 => disr as i64 as Disr == disr,
3776 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3780 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3781 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3785 fn do_check(ccx: &CrateCtxt,
3786 vs: &[ast::P<ast::Variant>],
3788 hint: attr::ReprAttr)
3789 -> Vec<Rc<ty::VariantInfo>> {
3791 let rty = ty::node_id_to_type(ccx.tcx, id);
3792 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3793 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3794 let mut prev_disr_val: Option<ty::Disr> = None;
3796 for &v in vs.iter() {
3798 // If the discriminant value is specified explicitly in the enum check whether the
3799 // initialization expression is valid, otherwise use the last value plus one.
3800 let mut current_disr_val = match prev_disr_val {
3801 Some(prev_disr_val) => prev_disr_val + 1,
3802 None => ty::INITIAL_DISCRIMINANT_VALUE
3805 match v.node.disr_expr {
3807 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3809 let inh = blank_inherited_fields(ccx);
3810 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3811 let declty = match hint {
3812 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3813 attr::ReprInt(_, attr::SignedInt(ity)) => {
3814 ty::mk_mach_int(ity)
3816 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3817 ty::mk_mach_uint(ity)
3820 check_const_with_ty(&fcx, e.span, &*e, declty);
3821 // check_expr (from check_const pass) doesn't guarantee
3822 // that the expression is in a form that eval_const_expr can
3823 // handle, so we may still get an internal compiler error
3825 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3826 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3827 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3829 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3835 format!("expected constant: {}",
3843 // Check for duplicate discriminant values
3844 if disr_vals.contains(¤t_disr_val) {
3845 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3847 // Check for unrepresentable discriminant values
3849 attr::ReprAny | attr::ReprExtern => (),
3850 attr::ReprInt(sp, ity) => {
3851 if !disr_in_range(ccx, ity, current_disr_val) {
3852 ccx.tcx.sess.span_err(v.span,
3853 "discriminant value outside specified type");
3854 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3858 disr_vals.push(current_disr_val);
3860 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3862 prev_disr_val = Some(current_disr_val);
3864 variants.push(variant_info);
3870 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3871 if hint != attr::ReprAny && vs.len() <= 1 {
3872 let msg = if vs.len() == 1 {
3873 "unsupported representation for univariant enum"
3875 "unsupported representation for zero-variant enum"
3877 ccx.tcx.sess.span_err(sp, msg)
3880 let variants = do_check(ccx, vs, id, hint);
3882 // cache so that ty::enum_variants won't repeat this work
3883 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3885 check_representable(ccx.tcx, sp, id, "enum");
3887 // Check that it is possible to instantiate this enum:
3889 // This *sounds* like the same that as representable, but it's
3890 // not. See def'n of `check_instantiable()` for details.
3891 check_instantiable(ccx.tcx, sp, id);
3894 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3895 lookup_def_ccx(fcx.ccx, sp, id)
3898 // Returns the type parameter count and the type for the given definition.
3899 pub fn polytype_for_def(fcx: &FnCtxt,
3904 def::DefArg(nid, _) | def::DefLocal(nid, _) |
3905 def::DefBinding(nid, _) => {
3906 let typ = fcx.local_ty(sp, nid);
3907 return no_params(typ);
3909 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
3910 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
3911 def::DefStruct(id) => {
3912 return ty::lookup_item_type(fcx.ccx.tcx, id);
3914 def::DefUpvar(_, inner, _, _) => {
3915 return polytype_for_def(fcx, sp, *inner);
3920 def::DefTyParam(..)=> {
3921 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3923 def::DefMod(..) | def::DefForeignMod(..) => {
3924 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3926 def::DefUse(..) => {
3927 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3929 def::DefRegion(..) => {
3930 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3932 def::DefTyParamBinder(..) => {
3933 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3935 def::DefLabel(..) => {
3936 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3938 def::DefSelfTy(..) => {
3939 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3941 def::DefMethod(..) => {
3942 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3947 // Instantiates the given path, which must refer to an item with the given
3948 // number of type parameters and type.
3949 pub fn instantiate_path(fcx: &FnCtxt,
3954 node_id: ast::NodeId) {
3955 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
3956 path.repr(fcx.tcx()),
3957 def.repr(fcx.tcx()),
3959 polytype.repr(fcx.tcx()));
3961 // We need to extract the type parameters supplied by the user in
3962 // the path `path`. Due to the current setup, this is a bit of a
3963 // tricky-process; the problem is that resolve only tells us the
3964 // end-point of the path resolution, and not the intermediate steps.
3965 // Luckily, we can (at least for now) deduce the intermediate steps
3966 // just from the end-point.
3968 // There are basically three cases to consider:
3970 // 1. Reference to a *type*, such as a struct or enum:
3972 // mod a { struct Foo<T> { ... } }
3974 // Because we don't allow types to be declared within one
3975 // another, a path that leads to a type will always look like
3976 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
3977 // that only the final segment can have type parameters, and
3978 // they are located in the TypeSpace.
3980 // *Note:* Generally speaking, references to types don't
3981 // actually pass through this function, but rather the
3982 // `ast_ty_to_ty` function in `astconv`. However, in the case
3983 // of struct patterns (and maybe literals) we do invoke
3984 // `instantiate_path` to get the general type of an instance of
3985 // a struct. (In these cases, there are actually no type
3986 // parameters permitted at present, but perhaps we will allow
3987 // them in the future.)
3989 // 1b. Reference to a enum variant or tuple-like struct:
3991 // struct foo<T>(...)
3992 // enum E<T> { foo(...) }
3994 // In these cases, the parameters are declared in the type
3997 // 2. Reference to a *fn item*:
4001 // In this case, the path will again always have the form
4002 // `a::b::foo::<T>` where only the final segment should have
4003 // type parameters. However, in this case, those parameters are
4004 // declared on a value, and hence are in the `FnSpace`.
4006 // 3. Reference to a *method*:
4008 // impl<A> SomeStruct<A> {
4012 // Here we can have a path like
4013 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4014 // may appear in two places. The penultimate segment,
4015 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4016 // final segment, `foo::<B>` contains parameters in fn space.
4018 // The first step then is to categorize the segments appropriately.
4020 assert!(path.segments.len() >= 1);
4021 let mut segment_spaces;
4023 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4024 def::DefSelfTy(..) |
4025 def::DefStruct(..) |
4026 def::DefVariant(..) |
4027 def::DefTyParamBinder(..) |
4030 def::DefPrimTy(..) |
4031 def::DefTyParam(..) => {
4032 // Everything but the final segment should have no
4033 // parameters at all.
4034 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4035 segment_spaces.push(Some(subst::TypeSpace));
4038 // Case 2. Reference to a top-level value.
4040 def::DefStatic(..) => {
4041 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4042 segment_spaces.push(Some(subst::FnSpace));
4045 // Case 3. Reference to a method.
4046 def::DefStaticMethod(..) => {
4047 assert!(path.segments.len() >= 2);
4048 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4049 segment_spaces.push(Some(subst::TypeSpace));
4050 segment_spaces.push(Some(subst::FnSpace));
4053 // Other cases. Various nonsense that really shouldn't show up
4054 // here. If they do, an error will have been reported
4055 // elsewhere. (I hope)
4057 def::DefForeignMod(..) |
4060 def::DefMethod(..) |
4061 def::DefBinding(..) |
4063 def::DefRegion(..) |
4065 def::DefUpvar(..) => {
4066 segment_spaces = Vec::from_elem(path.segments.len(), None);
4069 assert_eq!(segment_spaces.len(), path.segments.len());
4071 debug!("segment_spaces={}", segment_spaces);
4073 // Next, examine the definition, and determine how many type
4074 // parameters we expect from each space.
4075 let type_defs = &polytype.generics.types;
4076 let region_defs = &polytype.generics.regions;
4078 // Now that we have categorized what space the parameters for each
4079 // segment belong to, let's sort out the parameters that the user
4080 // provided (if any) into their appropriate spaces. We'll also report
4081 // errors if type parameters are provided in an inappropriate place.
4082 let mut substs = Substs::empty();
4083 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4086 report_error_if_segment_contains_type_parameters(fcx, segment);
4090 push_explicit_parameters_from_segment_to_substs(fcx,
4100 // Now we have to compare the types that the user *actually*
4101 // provided against the types that were *expected*. If the user
4102 // did not provide any types, then we want to substitute inference
4103 // variables. If the user provided some types, we may still need
4104 // to add defaults. If the user provided *too many* types, that's
4106 for &space in ParamSpace::all().iter() {
4107 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4108 assert_eq!(substs.types.get_vec(space).len(),
4109 type_defs.get_vec(space).len());
4111 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4112 assert_eq!(substs.regions().get_vec(space).len(),
4113 region_defs.get_vec(space).len());
4116 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4120 fn report_error_if_segment_contains_type_parameters(
4122 segment: &ast::PathSegment)
4124 for typ in segment.types.iter() {
4125 fcx.tcx().sess.span_err(
4127 "type parameters may not appear here");
4131 for lifetime in segment.lifetimes.iter() {
4132 fcx.tcx().sess.span_err(
4134 "lifetime parameters may not appear here");
4139 fn push_explicit_parameters_from_segment_to_substs(
4141 space: subst::ParamSpace,
4142 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4143 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4144 segment: &ast::PathSegment,
4145 substs: &mut Substs)
4148 * Finds the parameters that the user provided and adds them
4149 * to `substs`. If too many parameters are provided, then
4150 * reports an error and clears the output vector.
4152 * We clear the output vector because that will cause the
4153 * `adjust_XXX_parameters()` later to use inference
4154 * variables. This seems less likely to lead to derived
4157 * Note that we *do not* check for *too few* parameters here.
4158 * Due to the presence of defaults etc that is more
4159 * complicated. I wanted however to do the reporting of *too
4160 * many* parameters here because we can easily use the precise
4161 * span of the N+1'th parameter.
4165 let type_count = type_defs.get_vec(space).len();
4166 assert_eq!(substs.types.get_vec(space).len(), 0);
4167 for (i, &typ) in segment.types.iter().enumerate() {
4168 let t = fcx.to_ty(&*typ);
4170 substs.types.push(space, t);
4171 } else if i == type_count {
4172 fcx.tcx().sess.span_err(
4175 "too many type parameters provided: \
4176 expected at most {} parameter(s) \
4177 but found {} parameter(s)",
4179 segment.types.len()).as_slice());
4180 substs.types.get_mut_vec(space).truncate(0);
4186 let region_count = region_defs.get_vec(space).len();
4187 assert_eq!(substs.regions().get_vec(space).len(), 0);
4188 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4189 let r = ast_region_to_region(fcx.tcx(), lifetime);
4190 if i < region_count {
4191 substs.mut_regions().push(space, r);
4192 } else if i == region_count {
4193 fcx.tcx().sess.span_err(
4196 "too many lifetime parameters provided: \
4197 expected {} parameter(s) but found {} parameter(s)",
4199 segment.lifetimes.len()).as_slice());
4200 substs.mut_regions().get_mut_vec(space).truncate(0);
4206 fn adjust_type_parameters(
4210 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4211 substs: &mut Substs)
4213 let provided_len = substs.types.get_vec(space).len();
4214 let desired = defs.get_vec(space).as_slice();
4215 let required_len = desired.iter()
4216 .take_while(|d| d.default.is_none())
4219 debug!("adjust_type_parameters(space={}, \
4228 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4229 assert!(provided_len <= desired.len());
4231 // Nothing specified at all: supply inference variables for
4233 if provided_len == 0 {
4234 let provided = substs.types.get_mut_vec(space);
4235 *provided = fcx.infcx().next_ty_vars(desired.len());
4239 // Too few parameters specified: report an error and use Err
4241 if provided_len < required_len {
4243 if desired.len() != required_len { "at least " } else { "" };
4244 fcx.tcx().sess.span_err(
4246 format!("too few type parameters provided: \
4247 expected {}{} parameter(s) \
4248 but found {} parameter(s)",
4251 provided_len).as_slice());
4252 let provided = substs.types.get_mut_vec(space);
4253 *provided = Vec::from_elem(desired.len(), ty::mk_err());
4257 // Otherwise, add in any optional parameters that the user
4258 // omitted. The case of *too many* parameters is handled
4260 // push_explicit_parameters_from_segment_to_substs(). Note
4261 // that the *default* type are expressed in terms of all prior
4262 // parameters, so we have to substitute as we go with the
4263 // partial substitution that we have built up.
4264 for i in range(provided_len, desired.len()) {
4265 let default = desired[i].default.unwrap();
4266 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4267 substs.types.push(space, default);
4269 assert_eq!(substs.types.get_vec(space).len(), desired.len());
4271 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4274 fn adjust_region_parameters(
4278 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4279 substs: &mut Substs)
4281 let provided = substs.mut_regions().get_mut_vec(space);
4282 let desired = defs.get_vec(space);
4284 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4285 assert!(provided.len() <= desired.len());
4287 // If nothing was provided, just use inference variables.
4288 if provided.len() == 0 {
4289 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4293 // If just the right number were provided, everybody is happy.
4294 if provided.len() == desired.len() {
4298 // Otherwise, too few were provided. Report an error and then
4299 // use inference variables.
4300 fcx.tcx().sess.span_err(
4303 "too few lifetime parameters provided: \
4304 expected {} parameter(s) \
4305 but found {} parameter(s)",
4307 provided.len()).as_slice());
4309 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4313 // Resolves `typ` by a single level if `typ` is a type variable. If no
4314 // resolution is possible, then an error is reported.
4315 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4316 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4317 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4319 fcx.type_error_message(sp, |_actual| {
4320 "the type of this value must be known in this \
4321 context".to_string()
4323 demand::suptype(fcx, sp, ty::mk_err(), tp);
4329 // Returns the one-level-deep structure of the given type.
4330 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4332 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4335 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4336 let typ_s = structurally_resolved_type(fcx, sp, typ);
4337 return ty::type_is_integral(typ_s);
4340 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4341 let typ_s = structurally_resolved_type(fcx, sp, typ);
4342 return ty::type_is_uint(typ_s);
4345 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4348 mk_inner: || -> ty::mt)
4351 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4352 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4354 ast::ExprLit(..) => {
4355 // string literals and *empty slices* live in static memory
4356 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4358 ast::ExprVec(ref elements) if elements.len() == 0 => {
4359 // string literals and *empty slices* live in static memory
4360 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4362 ast::ExprRepeat(..) |
4363 ast::ExprVec(..) => {
4364 // vector literals are temporaries on the stack
4365 match fcx.tcx().region_maps.temporary_scope(e.id) {
4366 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4367 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4371 fcx.ccx.tcx.sess.span_bug(e.span,
4372 "vstore with unexpected \
4380 // Returns true if b contains a break that can exit from b
4381 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4382 // First: is there an unlabeled break immediately
4384 (loop_query(&*b, |e| {
4386 ast::ExprBreak(_) => true,
4390 // Second: is there a labeled break with label
4391 // <id> nested anywhere inside the loop?
4392 (block_query(b, |e| {
4394 ast::ExprBreak(Some(_)) => {
4395 match cx.def_map.borrow().find(&e.id) {
4396 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4404 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4406 tps: &OwnedSlice<ast::TyParam>,
4408 debug!("check_bounds_are_used(n_tps={}, ty={})",
4409 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4411 // make a vector of booleans initially false, set to true when used
4412 if tps.len() == 0u { return; }
4413 let mut tps_used = Vec::from_elem(tps.len(), false);
4415 ty::walk_ty(ty, |t| {
4416 match ty::get(t).sty {
4417 ty::ty_param(ParamTy {idx, ..}) => {
4418 debug!("Found use of ty param num {}", idx);
4419 *tps_used.get_mut(idx) = true;
4425 for (i, b) in tps_used.iter().enumerate() {
4427 ccx.tcx.sess.span_err(
4429 format!("type parameter `{}` is unused",
4430 token::get_ident(tps.get(i).ident)).as_slice());
4435 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4436 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4437 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4441 let name = token::get_ident(it.ident);
4442 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4443 let split : Vec<&str> = name.get().split('_').collect();
4444 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4446 //We only care about the operation here
4447 match *split.get(1) {
4448 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4452 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4454 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4457 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4458 "min" | "umax" | "umin" => {
4459 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4463 (0, Vec::new(), ty::mk_nil())
4466 tcx.sess.span_err(it.span,
4467 format!("unrecognized atomic operation \
4476 "abort" => (0, Vec::new(), ty::mk_bot()),
4477 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4479 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4480 "init" => (1u, Vec::new(), param(ccx, 0u)),
4481 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4482 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4483 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4484 "move_val_init" => {
4487 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4492 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4493 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4496 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4498 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4500 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4502 mutbl: ast::MutImmutable
4504 (1u, Vec::new(), td_ptr)
4507 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4511 ty::mk_struct(ccx.tcx, did,
4512 subst::Substs::empty())),
4514 tcx.sess.span_fatal(it.span, msg.as_slice());
4519 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4521 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4523 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4524 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4525 Ok((_, vot)) => vot,
4526 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4529 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4531 mutbl: ast::MutImmutable
4533 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4538 ty::mk_ptr(tcx, ty::mt {
4540 mutbl: ast::MutImmutable
4544 ty::mk_ptr(tcx, ty::mt {
4546 mutbl: ast::MutImmutable
4549 "copy_memory" | "copy_nonoverlapping_memory" |
4550 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4553 ty::mk_ptr(tcx, ty::mt {
4555 mutbl: ast::MutMutable
4557 ty::mk_ptr(tcx, ty::mt {
4559 mutbl: ast::MutImmutable
4565 "set_memory" | "volatile_set_memory" => {
4568 ty::mk_ptr(tcx, ty::mt {
4570 mutbl: ast::MutMutable
4577 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4578 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4581 vec!( ty::mk_f32(), ty::mk_i32() ),
4586 vec!( ty::mk_f64(), ty::mk_i32() ),
4589 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4590 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4591 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4592 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4595 vec!( ty::mk_f32(), ty::mk_f32() ),
4600 vec!( ty::mk_f64(), ty::mk_f64() ),
4603 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4604 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4605 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4606 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4607 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4608 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4609 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4610 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4611 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4612 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4615 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4620 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4623 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4624 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4625 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4626 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4627 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4628 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4629 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4630 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4631 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4632 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4633 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4634 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4635 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4636 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4637 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4638 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4639 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4640 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4641 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4642 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4643 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4644 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4645 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4646 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4647 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4648 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4649 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4650 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4651 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4652 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4653 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4656 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4658 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4660 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4661 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4662 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4664 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4665 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4666 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4668 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4669 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4670 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4672 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4673 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4674 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4676 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4677 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4678 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4680 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4681 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4682 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4684 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4685 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4686 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4688 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4689 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4690 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4693 tcx.sess.span_err(it.span,
4694 format!("unrecognized intrinsic function: `{}`",
4695 *other).as_slice());
4700 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4701 fn_style: ast::UnsafeFn,
4702 abi: abi::RustIntrinsic,
4710 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4711 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4712 if i_n_tps != n_tps {
4713 tcx.sess.span_err(it.span,
4714 format!("intrinsic has wrong number of type \
4715 parameters: found {}, expected {}",
4719 require_same_types(tcx,
4726 format!("intrinsic has wrong type: expected `{}`",
4727 ppaux::ty_to_str(ccx.tcx, fty))