1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function). Inference is used to supply types wherever they are
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
26 - main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `typeck::infer` module is in charge
35 of resolving those constraints.
37 - regionck: after main is complete, the regionck pass goes over all
38 types looking for regions and making sure that they did not escape
39 into places they are not in scope. This may also influence the
40 final assignments of the various region variables if there is some
43 - vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
46 - writeback: writes the final types within a function body, replacing
47 type variables with their final inferred types. These final types
48 are written into the `tcx.node_types` table, which should *never* contain
49 any reference to a type variable.
53 While type checking a function, the intermediate types for the
54 expressions, blocks, and so forth contained within the function are
55 stored in `fcx.node_types` and `fcx.item_substs`. These types
56 may contain unresolved type variables. After type checking is
57 complete, the functions in the writeback module are used to take the
58 types from this table, resolve them, and then write them into their
59 permanent home in the type context `ccx.tcx`.
61 This means that during inferencing you should use `fcx.write_ty()`
62 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63 nodes within the function.
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
68 n.b.: A type variable is not the same thing as a type parameter. A
69 type variable is rather an "instance" of a type parameter: that is,
70 given a generic function `fn foo<T>(t: T)`: while checking the
71 function `foo`, the type `ty_param(0)` refers to the type `T`, which
72 is treated in abstract. When `foo()` is called, however, `T` will be
73 substituted for a fresh type variable `N`. This variable will
74 eventually be resolved to some concrete type (which might itself be
80 use middle::const_eval;
82 use middle::pat_util::pat_id_map;
85 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
86 use middle::ty::{FnSig, VariantInfo};
87 use middle::ty::{Polytype};
88 use middle::ty::{ParamTy, Disr, ExprTyProvider};
90 use middle::ty_fold::TypeFolder;
91 use middle::typeck::astconv::AstConv;
92 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
93 use middle::typeck::astconv;
94 use middle::typeck::check::_match::pat_ctxt;
95 use middle::typeck::check::method::{AutoderefReceiver};
96 use middle::typeck::check::method::{AutoderefReceiverFlag};
97 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
98 use middle::typeck::check::method::{DontAutoderefReceiver};
99 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
100 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
101 use middle::typeck::check::regionmanip::relate_free_regions;
102 use middle::typeck::check::vtable::VtableContext;
103 use middle::typeck::CrateCtxt;
104 use middle::typeck::infer::{resolve_type, force_tvar};
105 use middle::typeck::infer;
106 use middle::typeck::rscope::RegionScope;
107 use middle::typeck::{lookup_def_ccx};
108 use middle::typeck::no_params;
109 use middle::typeck::{require_same_types, vtable_map};
110 use middle::typeck::{MethodCall, MethodMap};
111 use middle::typeck::{TypeAndSubsts};
112 use middle::lang_items::TypeIdLangItem;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159 infcx: infer::InferCtxt<'a>,
160 locals: RefCell<NodeMap<ty::t>>,
161 param_env: ty::ParameterEnvironment,
164 node_types: RefCell<NodeMap<ty::t>>,
165 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167 method_map: MethodMap,
168 vtable_map: vtable_map,
169 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(ty::t),
181 /// This expression will be cast to the `ty::t`
182 ExpectCastableToType(ty::t),
186 pub struct FnStyleState {
187 pub def: ast::NodeId,
188 pub fn_style: ast::FnStyle,
193 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
197 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
198 match self.fn_style {
199 // If this unsafe, then if the outer function was already marked as
200 // unsafe we shouldn't attribute the unsafe'ness to the block. This
201 // way the block can be warned about instead of ignoring this
202 // extraneous block (functions are never warned about).
203 ast::UnsafeFn if self.from_fn => *self,
206 let (fn_style, def) = match blk.rules {
207 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208 ast::DefaultBlock => (fn_style, self.def),
210 FnStyleState{ def: def,
218 /// Whether `check_binop` is part of an assignment or not.
219 /// Used to know whether we allow user overloads and to print
220 /// better messages on error.
221 #[deriving(PartialEq)]
222 enum IsBinopAssignment{
228 pub struct FnCtxt<'a> {
229 // This flag is set to true if, during the writeback phase, we encounter
230 // a type error in this function.
231 writeback_errors: Cell<bool>,
233 // Number of errors that had been reported when we started
234 // checking this function. On exit, if we find that *more* errors
235 // have been reported, we will skip regionck and other work that
236 // expects the types within the function to be consistent.
237 err_count_on_creation: uint,
240 ps: RefCell<FnStyleState>,
242 // Sometimes we generate region pointers where the precise region
243 // to use is not known. For example, an expression like `&x.f`
244 // where `x` is of type `@T`: in this case, we will be rooting
245 // `x` onto the stack frame, and we could choose to root it until
246 // the end of (almost) any enclosing block or expression. We
247 // want to pick the narrowest block that encompasses all uses.
249 // What we do in such cases is to generate a region variable with
250 // `region_lb` as a lower bound. The regionck pass then adds
251 // other constraints based on how the variable is used and region
252 // inference selects the ultimate value. Finally, borrowck is
253 // charged with guaranteeing that the value whose address was taken
254 // can actually be made to live as long as it needs to live.
255 region_lb: Cell<ast::NodeId>,
257 inh: &'a Inherited<'a>,
259 ccx: &'a CrateCtxt<'a>,
262 impl<'a> Inherited<'a> {
263 fn new(tcx: &'a ty::ctxt,
264 param_env: ty::ParameterEnvironment)
267 infcx: infer::new_infer_ctxt(tcx),
268 locals: RefCell::new(NodeMap::new()),
269 param_env: param_env,
270 node_types: RefCell::new(NodeMap::new()),
271 item_substs: RefCell::new(NodeMap::new()),
272 adjustments: RefCell::new(NodeMap::new()),
273 method_map: RefCell::new(FnvHashMap::new()),
274 vtable_map: RefCell::new(FnvHashMap::new()),
275 upvar_borrow_map: RefCell::new(HashMap::new()),
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282 inh: &'a Inherited<'a>,
284 region_bnd: ast::NodeId)
287 writeback_errors: Cell::new(false),
288 err_count_on_creation: ccx.tcx.sess.err_count(),
290 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291 region_lb: Cell::new(region_bnd),
297 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
298 // It's kind of a kludge to manufacture a fake function context
299 // and statement context, but we might as well do write the code only once
300 let param_env = ty::ParameterEnvironment {
301 free_substs: subst::Substs::empty(),
302 bounds: subst::VecPerParamSpace::empty()
304 Inherited::new(ccx.tcx, param_env)
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
312 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
319 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
320 fn visit_item(&mut self, i: &ast::Item, _: ()) {
321 check_item(self.ccx, i);
322 visit::walk_item(self, i, ());
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
328 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329 fn visit_item(&mut self, i: &ast::Item, _: ()) {
330 check_item_sized(self.ccx, i);
331 visit::walk_item(self, i, ());
335 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336 let mut visit = CheckItemTypesVisitor { ccx: ccx };
337 visit::walk_crate(&mut visit, krate, ());
339 ccx.tcx.sess.abort_if_errors();
341 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342 visit::walk_crate(&mut visit, krate, ());
345 fn check_bare_fn(ccx: &CrateCtxt,
350 param_env: ty::ParameterEnvironment) {
351 // Compute the fty from point of view of inside fn
352 // (replace any type-scheme with a type)
353 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
355 match ty::get(fty).sty {
356 ty::ty_bare_fn(ref fn_ty) => {
357 let inh = Inherited::new(ccx.tcx, param_env);
358 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
359 decl, id, body, &inh);
361 vtable::resolve_in_block(&fcx, body);
362 regionck::regionck_fn(&fcx, body);
363 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
365 _ => ccx.tcx.sess.impossible_case(body.span,
366 "check_bare_fn: function type expected")
370 struct GatherLocalsVisitor<'a> {
374 impl<'a> GatherLocalsVisitor<'a> {
375 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
378 // infer the variable's type
379 let var_id = self.fcx.infcx().next_ty_var_id();
380 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
381 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
384 // take type that the user specified
385 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
391 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392 // Add explicitly-declared locals.
393 fn visit_local(&mut self, local: &ast::Local, _: ()) {
394 let o_ty = match local.ty.node {
395 ast::TyInfer => None,
396 _ => Some(self.fcx.to_ty(&*local.ty))
398 self.assign(local.id, o_ty);
399 debug!("Local variable {} is assigned type {}",
400 self.fcx.pat_to_str(&*local.pat),
401 self.fcx.infcx().ty_to_str(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
406 // Add pattern bindings.
407 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
409 ast::PatIdent(_, ref path1, _)
410 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
411 self.assign(p.id, None);
412 debug!("Pattern binding {} is assigned to {}",
413 token::get_ident(path1.node),
414 self.fcx.infcx().ty_to_str(
415 self.fcx.inh.locals.borrow().get_copy(&p.id)));
419 visit::walk_pat(self, p, ());
423 fn visit_block(&mut self, b: &ast::Block, _: ()) {
424 // non-obvious: the `blk` variable maps to region lb, so
425 // we have to keep this up-to-date. This
426 // is... unfortunate. It'd be nice to not need this.
427 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
430 // Don't descend into fns and items
431 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
432 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
433 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438 fn_style: ast::FnStyle,
443 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
446 * Helper used by check_bare_fn and check_expr_fn. Does the
447 * grungy work of checking a function body and returns the
448 * function context used for that purpose, since in the case of a
449 * fn item there is still a bit more to do.
452 * - inherited: other fields inherited from the enclosing fn (if any)
456 let err_count_on_creation = tcx.sess.err_count();
458 // First, we have to replace any bound regions in the fn type with free ones.
459 // The free region references will be bound the node_id of the body block.
460 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
461 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
464 relate_free_regions(tcx, &fn_sig);
466 let arg_tys = fn_sig.inputs.as_slice();
467 let ret_ty = fn_sig.output;
469 debug!("check_fn(arg_tys={}, ret_ty={})",
473 // Create the function context. This is either derived from scratch or,
474 // in the case of function expressions, based on the outer context.
476 writeback_errors: Cell::new(false),
477 err_count_on_creation: err_count_on_creation,
479 ps: RefCell::new(FnStyleState::function(fn_style, id)),
480 region_lb: Cell::new(body.id),
487 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
488 // Add formal parameters.
489 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
490 // Create type variables for each argument.
491 pat_util::pat_bindings(&tcx.def_map,
493 |_bm, pat_id, _sp, _path| {
494 visit.assign(pat_id, None);
497 // Check the pattern.
500 map: pat_id_map(&tcx.def_map, &*input.pat),
502 _match::check_pat(&pcx, &*input.pat, *arg_ty);
505 visit.visit_block(body, ());
508 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
510 // We unify the tail expr's type with the
511 // function result type, if there is a tail expr.
513 Some(ref tail_expr) => {
514 // Special case: we print a special error if there appears
515 // to be do-block/for-loop confusion
516 demand::suptype_with_fn(&fcx, tail_expr.span, false,
517 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
519 fcx.report_mismatched_return_types(sp, e, a, s);
525 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526 fcx.write_ty(input.id, *arg);
532 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
533 assert!(field.id.krate == ast::LOCAL_CRATE);
534 let item = match tcx.map.find(struct_id.node) {
535 Some(ast_map::NodeItem(item)) => item,
536 None => fail!("node not in ast map: {}", struct_id.node),
537 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
541 ast::ItemStruct(struct_def, _) => {
542 match struct_def.fields.iter().find(|f| match f.node.kind {
543 ast::NamedField(ident, _) => ident.name == field.name,
549 .bug(format!("Could not find field {}",
550 token::get_name(field.name)).as_slice())
554 _ => tcx.sess.bug("Field found outside of a struct?"),
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
561 let struct_fields = tcx.struct_fields.borrow();
562 let fields = struct_fields.get(&id);
564 let superstructs = tcx.superstructs.borrow();
565 let super_struct = superstructs.get(&id);
566 match *super_struct {
568 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
569 for f in fields.iter() {
570 match super_fields.iter().find(|sf| f.name == sf.name) {
571 Some(prev_field) => {
572 tcx.sess.span_err(span_for_field(tcx, f, id),
573 format!("field `{}` hides field declared in \
575 token::get_name(f.name)).as_slice());
576 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
577 "previously declared here");
587 fn check_fields_sized(tcx: &ty::ctxt,
588 struct_def: &ast::StructDef) {
589 let len = struct_def.fields.len();
593 for f in struct_def.fields.slice_to(len - 1).iter() {
594 let t = ty::node_id_to_type(tcx, f.node.id);
595 if !ty::type_is_sized(tcx, t) {
597 ast::NamedField(ident, _) => {
600 format!("type `{}` is dynamically sized. \
601 dynamically sized types may only \
602 appear as the type of the final \
604 token::get_ident(ident)).as_slice());
606 ast::UnnamedField(_) => {
607 tcx.sess.span_err(f.span, "dynamically sized type in field");
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
617 check_representable(tcx, span, id, "struct");
618 check_instantiable(tcx, span, id);
620 // Check there are no overlapping fields in super-structs
621 check_for_field_shadowing(tcx, local_def(id));
623 if ty::lookup_simd(tcx, local_def(id)) {
624 check_simd(tcx, span, id);
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629 debug!("check_item(it.id={}, it.ident={})",
631 ty::item_path_str(ccx.tcx, local_def(it.id)));
632 let _indenter = indenter();
635 ast::ItemEnum(ref enum_definition, _) => {
636 check_enum_variants_sized(ccx,
637 enum_definition.variants.as_slice());
639 ast::ItemStruct(..) => {
640 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647 debug!("check_item(it.id={}, it.ident={})",
649 ty::item_path_str(ccx.tcx, local_def(it.id)));
650 let _indenter = indenter();
653 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654 ast::ItemEnum(ref enum_definition, _) => {
655 check_enum_variants(ccx,
657 enum_definition.variants.as_slice(),
660 ast::ItemFn(ref decl, _, _, _, ref body) => {
661 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
663 let param_env = ty::construct_parameter_environment(ccx.tcx,
667 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
669 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
672 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
674 check_method_body(ccx, &impl_pty.generics, &**m);
677 match *opt_trait_ref {
678 Some(ref ast_trait_ref) => {
680 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681 check_impl_methods_against_trait(ccx,
686 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
692 ast::ItemTrait(_, _, _, ref trait_methods) => {
693 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
694 for trait_method in (*trait_methods).iter() {
695 match *trait_method {
697 // Nothing to do, since required methods don't have
701 check_method_body(ccx, &trait_def.generics, &*m);
706 ast::ItemStruct(..) => {
707 check_struct(ccx, it.id, it.span);
709 ast::ItemTy(ref t, ref generics) => {
710 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
711 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
713 ast::ItemForeignMod(ref m) => {
714 if m.abi == abi::RustIntrinsic {
715 for item in m.items.iter() {
716 check_intrinsic_type(ccx, &**item);
719 for item in m.items.iter() {
720 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
721 if !pty.generics.types.is_empty() {
722 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
726 ast::ForeignItemFn(ref fn_decl, _) => {
727 if fn_decl.variadic && m.abi != abi::C {
728 ccx.tcx.sess.span_err(
729 item.span, "variadic function must have C calling convention");
737 _ => {/* nothing to do */ }
741 fn check_method_body(ccx: &CrateCtxt,
742 item_generics: &ty::Generics,
743 method: &ast::Method) {
745 * Type checks a method body.
748 * - `item_generics`: generics defined on the impl/trait that contains
750 * - `self_bound`: bound for the `Self` type parameter, if any
751 * - `method`: the method definition
754 debug!("check_method_body(item_generics={}, method.id={})",
755 item_generics.repr(ccx.tcx),
757 let method_def_id = local_def(method.id);
758 let method_ty = ty::method(ccx.tcx, method_def_id);
759 let method_generics = &method_ty.generics;
761 let param_env = ty::construct_parameter_environment(ccx.tcx,
765 let fty = ty::node_id_to_type(ccx.tcx, method.id);
767 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
772 ast_trait_ref: &ast::TraitRef,
773 impl_trait_ref: &ty::TraitRef,
774 impl_methods: &[Gc<ast::Method>]) {
775 // Locate trait methods
777 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
779 // Check existing impl methods to see if they are both present in trait
780 // and compatible with trait signature
781 for impl_method in impl_methods.iter() {
782 let impl_method_def_id = local_def(impl_method.id);
783 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
785 // If this is an impl of a trait method, find the corresponding
786 // method definition in the trait.
787 let opt_trait_method_ty =
788 trait_methods.iter().
789 find(|tm| tm.ident.name == impl_method_ty.ident.name);
790 match opt_trait_method_ty {
791 Some(trait_method_ty) => {
792 compare_impl_method(ccx.tcx,
797 &impl_trait_ref.substs);
800 // This is span_bug as it should have already been caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_ident(impl_method_ty.ident),
806 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
811 // Check for missing methods from trait
812 let provided_methods = ty::provided_trait_methods(tcx,
813 impl_trait_ref.def_id);
814 let mut missing_methods = Vec::new();
815 for trait_method in trait_methods.iter() {
817 impl_methods.iter().any(
818 |m| m.ident.name == trait_method.ident.name);
820 provided_methods.iter().any(
821 |m| m.ident.name == trait_method.ident.name);
822 if !is_implemented && !is_provided {
823 missing_methods.push(
824 format!("`{}`", token::get_ident(trait_method.ident)));
828 if !missing_methods.is_empty() {
831 format!("not all trait methods implemented, missing: {}",
832 missing_methods.connect(", ")).as_slice());
837 * Checks that a method from an impl/class conforms to the signature of
838 * the same method as declared in the trait.
842 * - impl_generics: the generics declared on the impl itself (not the method!)
843 * - impl_m: type of the method we are checking
844 * - impl_m_span: span to use for reporting errors
845 * - impl_m_body_id: id of the method body
846 * - trait_m: the method in the trait
847 * - trait_to_impl_substs: the substitutions used on the type of the trait
849 fn compare_impl_method(tcx: &ty::ctxt,
852 impl_m_body_id: ast::NodeId,
853 trait_m: &ty::Method,
854 trait_to_impl_substs: &subst::Substs) {
855 debug!("compare_impl_method()");
856 let infcx = infer::new_infer_ctxt(tcx);
858 // Try to give more informative error messages about self typing
859 // mismatches. Note that any mismatch will also be detected
860 // below, where we construct a canonical function type that
861 // includes the self parameter as a normal parameter. It's just
862 // that the error messages you get out of this code are a bit more
863 // inscrutable, particularly for cases where one method has no
865 match (&trait_m.explicit_self, &impl_m.explicit_self) {
866 (&ast::SelfStatic, &ast::SelfStatic) => {}
867 (&ast::SelfStatic, _) => {
870 format!("method `{}` has a `{}` declaration in the impl, \
871 but not in the trait",
872 token::get_ident(trait_m.ident),
873 pprust::explicit_self_to_str(
874 impl_m.explicit_self)).as_slice());
877 (_, &ast::SelfStatic) => {
880 format!("method `{}` has a `{}` declaration in the trait, \
881 but not in the impl",
882 token::get_ident(trait_m.ident),
883 pprust::explicit_self_to_str(
884 trait_m.explicit_self)).as_slice());
888 // Let the type checker catch other errors below
892 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
893 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
894 if num_impl_m_type_params != num_trait_m_type_params {
897 format!("method `{}` has {} type parameter{} \
898 but its trait declaration has {} type parameter{}",
899 token::get_ident(trait_m.ident),
900 num_impl_m_type_params,
901 if num_impl_m_type_params == 1 {""} else {"s"},
902 num_trait_m_type_params,
903 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
907 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
910 format!("method `{}` has {} parameter{} \
911 but the declaration in trait `{}` has {}",
912 token::get_ident(trait_m.ident),
913 impl_m.fty.sig.inputs.len(),
914 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
915 ty::item_path_str(tcx, trait_m.def_id),
916 trait_m.fty.sig.inputs.len()).as_slice());
920 let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
921 .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
923 // This code is best explained by example. Consider a trait:
926 // fn method<'a,M>(t: T, m: &'a M) -> Self;
931 // impl<'i, U> Trait<&'i U> for Foo {
932 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
935 // We wish to decide if those two method types are compatible.
937 // We start out with trait_to_impl_substs, that maps the trait type
938 // parameters to impl type parameters:
940 // trait_to_impl_substs = {T => &'i U, Self => Foo}
942 // We create a mapping `dummy_substs` that maps from the impl type
943 // parameters to fresh types and regions. For type parameters,
944 // this is the identity transform, but we could as well use any
945 // skolemized types. For regions, we convert from bound to free
946 // regions (Note: but only early-bound regions, i.e., those
947 // declared on the impl or used in type parameter bounds).
949 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
951 // Now we can apply skol_substs to the type of the impl method
952 // to yield a new function type in terms of our fresh, skolemized
955 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
957 // We now want to extract and substitute the type of the *trait*
958 // method and compare it. To do so, we must create a compound
959 // substitution by combining trait_to_impl_substs and
960 // impl_to_skol_substs, and also adding a mapping for the method
961 // type parameters. We extend the mapping to also include
962 // the method parameters.
964 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
966 // Applying this to the trait method type yields:
968 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
970 // This type is also the same but the name of the bound region ('a
971 // vs 'b). However, the normal subtyping rules on fn types handle
972 // this kind of equivalency just fine.
974 // Create mapping from impl to skolemized.
976 impl_m.generics.types.map(
977 |d| ty::mk_param_from_def(tcx, d));
979 impl_m.generics.regions.map(
980 |l| ty::free_region_from_def(impl_m_body_id, l));
981 let impl_to_skol_substs =
982 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
984 // Compute skolemized form of impl method ty.
985 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
986 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
988 // Compute skolemized form of trait method ty.
989 let trait_to_skol_substs =
991 .subst(tcx, &impl_to_skol_substs)
992 .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
993 skol_regions.get_vec(subst::FnSpace).clone());
994 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
995 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
998 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
999 // Check that the impl does not require any builtin-bounds
1000 // that the trait does not guarantee:
1002 impl_param_def.bounds.builtin_bounds -
1003 trait_param_def.bounds.builtin_bounds;
1004 if !extra_bounds.is_empty() {
1007 format!("in method `{}`, \
1008 type parameter {} requires `{}`, \
1009 which is not required by \
1010 the corresponding type parameter \
1011 in the trait declaration",
1012 token::get_ident(trait_m.ident),
1014 extra_bounds.user_string(tcx)).as_slice());
1018 // Check that the trait bounds of the trait imply the bounds of its
1021 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1022 // traits, but I doubt that'll be wanted often, so meh.
1023 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1024 let impl_trait_bound =
1025 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1028 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1030 trait_bound.subst(tcx, &trait_to_skol_substs);
1031 let infcx = infer::new_infer_ctxt(tcx);
1032 match infer::mk_sub_trait_refs(&infcx,
1034 infer::Misc(impl_m_span),
1036 impl_trait_bound.clone()) {
1046 tcx.sess.span_err(impl_m_span,
1047 format!("in method `{}`, type parameter {} \
1048 requires bound `{}`, which is not \
1049 required by the corresponding \
1050 type parameter in the trait \
1052 token::get_ident(trait_m.ident),
1054 ppaux::trait_ref_to_str(
1056 &*impl_trait_bound)).as_slice())
1061 // Check the impl method type IM is a subtype of the trait method
1062 // type TM. To see why this makes sense, think of a vtable. The
1063 // expected type of the function pointers in the vtable is the
1064 // type TM of the trait method. The actual type will be the type
1065 // IM of the impl method. Because we know that IM <: TM, that
1066 // means that anywhere a TM is expected, a IM will do instead. In
1067 // other words, anyone expecting to call a method with the type
1068 // from the trait, can safely call a method with the type from the
1070 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1071 impl_fty, trait_fty) {
1076 format!("method `{}` has an incompatible type for trait: {}",
1077 token::get_ident(trait_m.ident),
1078 ty::type_err_to_str(tcx, terr)).as_slice());
1079 ty::note_and_explain_type_err(tcx, terr);
1084 fn check_cast(fcx: &FnCtxt,
1089 // Find the type of `e`. Supply hints based on the type we are casting to,
1091 let t_1 = fcx.to_ty(t);
1092 let t_1 = structurally_resolved_type(fcx, span, t_1);
1094 if ty::type_is_scalar(t_1) {
1095 // Supply the type as a hint so as to influence integer
1096 // literals and other things that might care.
1097 check_expr_with_hint(fcx, e, t_1)
1102 let t_e = fcx.expr_ty(e);
1104 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
1105 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
1107 if ty::type_is_error(t_e) {
1108 fcx.write_error(id);
1111 if ty::type_is_bot(t_e) {
1116 if ty::type_is_trait(t_1) {
1117 // This will be looked up later on.
1118 fcx.write_ty(id, t_1);
1122 let t_1 = structurally_resolved_type(fcx, span, t_1);
1123 let t_e = structurally_resolved_type(fcx, span, t_e);
1125 if ty::type_is_nil(t_e) {
1126 fcx.type_error_message(span, |actual| {
1127 format!("cast from nil: `{}` as `{}`",
1129 fcx.infcx().ty_to_str(t_1))
1131 } else if ty::type_is_nil(t_1) {
1132 fcx.type_error_message(span, |actual| {
1133 format!("cast to nil: `{}` as `{}`",
1135 fcx.infcx().ty_to_str(t_1))
1139 let t_1_is_scalar = ty::type_is_scalar(t_1);
1140 let t_1_is_char = ty::type_is_char(t_1);
1141 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1142 let t_1_is_float = ty::type_is_floating_point(t_1);
1144 // casts to scalars other than `char` and `bare fn` are trivial
1145 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1146 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1148 fcx.type_error_message(span, |actual| {
1149 format!("illegal cast; cast through an \
1150 integer first: `{}` as `{}`",
1152 fcx.infcx().ty_to_str(t_1))
1155 // casts from C-like enums are allowed
1156 } else if t_1_is_char {
1157 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1158 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1159 fcx.type_error_message(span, |actual| {
1160 format!("only `u8` can be cast as \
1161 `char`, not `{}`", actual)
1164 } else if ty::get(t_1).sty == ty::ty_bool {
1168 "cannot cast as `bool`, compare with zero instead");
1169 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1170 fn types_compatible(fcx: &FnCtxt, sp: Span,
1171 t1: ty::t, t2: ty::t) -> bool {
1172 if !ty::type_is_vec(t1) {
1173 // If the type being casted from is not a vector, this special
1174 // case does not apply.
1177 if ty::type_needs_infer(t2) {
1178 // This prevents this special case from going off when casting
1179 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1184 let el = ty::sequence_element_type(fcx.tcx(), t1);
1185 infer::mk_eqty(fcx.infcx(),
1192 // Due to the limitations of LLVM global constants,
1193 // region pointers end up pointing at copies of
1194 // vector elements instead of the original values.
1195 // To allow unsafe pointers to work correctly, we
1196 // need to special-case obtaining an unsafe pointer
1197 // from a region pointer to a vector.
1199 /* this cast is only allowed from &[T] to *T or
1201 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1202 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1203 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1204 if types_compatible(fcx, e.span, mt1, mt2) => {
1205 /* this case is allowed */
1208 demand::coerce(fcx, e.span, t_1, &*e);
1211 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1213 If more type combinations should be supported than are
1214 supported here, then file an enhancement issue and
1215 record the issue number in this comment.
1217 fcx.type_error_message(span, |actual| {
1218 format!("non-scalar cast: `{}` as `{}`",
1220 fcx.infcx().ty_to_str(t_1))
1224 fcx.write_ty(id, t_1);
1227 impl<'a> AstConv for FnCtxt<'a> {
1228 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1230 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1231 ty::lookup_item_type(self.tcx(), id)
1234 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1235 ty::lookup_trait_def(self.tcx(), id)
1238 fn ty_infer(&self, _span: Span) -> ty::t {
1239 self.infcx().next_ty_var()
1243 impl<'a> FnCtxt<'a> {
1244 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1248 pub fn err_count_since_creation(&self) -> uint {
1249 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1252 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1254 infcx: self.infcx(),
1255 param_env: &self.inh.param_env
1260 impl<'a> RegionScope for infer::InferCtxt<'a> {
1261 fn anon_regions(&self, span: Span, count: uint)
1262 -> Result<Vec<ty::Region> , ()> {
1263 Ok(Vec::from_fn(count, |_| {
1264 self.next_region_var(infer::MiscVariable(span))
1269 impl<'a> FnCtxt<'a> {
1270 pub fn tag(&self) -> String {
1271 format!("{}", self as *const FnCtxt)
1274 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1275 match self.inh.locals.borrow().find(&nid) {
1278 self.tcx().sess.span_bug(
1280 format!("no type for local variable {:?}",
1287 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1288 debug!("write_ty({}, {}) in fcx {}",
1289 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1290 self.inh.node_types.borrow_mut().insert(node_id, ty);
1293 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1294 if !substs.substs.is_noop() {
1295 debug!("write_substs({}, {}) in fcx {}",
1297 substs.repr(self.tcx()),
1300 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1304 pub fn write_ty_substs(&self,
1305 node_id: ast::NodeId,
1307 substs: ty::ItemSubsts) {
1308 let ty = ty.subst(self.tcx(), &substs.substs);
1309 self.write_ty(node_id, ty);
1310 self.write_substs(node_id, substs);
1313 pub fn write_autoderef_adjustment(&self,
1314 node_id: ast::NodeId,
1316 if derefs == 0 { return; }
1317 self.write_adjustment(
1319 ty::AutoDerefRef(ty::AutoDerefRef {
1325 pub fn write_adjustment(&self,
1326 node_id: ast::NodeId,
1327 adj: ty::AutoAdjustment) {
1328 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1329 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1332 pub fn write_nil(&self, node_id: ast::NodeId) {
1333 self.write_ty(node_id, ty::mk_nil());
1335 pub fn write_bot(&self, node_id: ast::NodeId) {
1336 self.write_ty(node_id, ty::mk_bot());
1338 pub fn write_error(&self, node_id: ast::NodeId) {
1339 self.write_ty(node_id, ty::mk_err());
1342 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1343 ast_ty_to_ty(self, self.infcx(), ast_t)
1346 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1347 pat.repr(self.tcx())
1350 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1351 match self.inh.node_types.borrow().find(&ex.id) {
1354 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1355 self.tag()).as_slice());
1360 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1361 match self.inh.node_types.borrow().find(&id) {
1364 self.tcx().sess.bug(
1365 format!("no type for node {}: {} in fcx {}",
1366 id, self.tcx().map.node_to_str(id),
1367 self.tag()).as_slice());
1372 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1373 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1374 Some(method) => method.substs.clone(),
1376 self.tcx().sess.bug(
1377 format!("no method entry for node {}: {} in fcx {}",
1378 id, self.tcx().map.node_to_str(id),
1379 self.tag()).as_slice());
1384 pub fn opt_node_ty_substs(&self,
1386 f: |&ty::ItemSubsts|) {
1387 match self.inh.item_substs.borrow().find(&id) {
1393 pub fn mk_subty(&self,
1394 a_is_expected: bool,
1395 origin: infer::TypeOrigin,
1398 -> Result<(), ty::type_err> {
1399 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1402 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1403 -> Result<(), ty::type_err> {
1404 infer::can_mk_subty(self.infcx(), sub, sup)
1407 pub fn mk_assignty(&self,
1411 -> Result<(), ty::type_err> {
1412 match infer::mk_coercety(self.infcx(),
1414 infer::ExprAssignable(expr.span),
1418 Err(ref e) => Err((*e)),
1419 Ok(Some(adjustment)) => {
1420 self.write_adjustment(expr.id, adjustment);
1426 pub fn mk_eqty(&self,
1427 a_is_expected: bool,
1428 origin: infer::TypeOrigin,
1431 -> Result<(), ty::type_err> {
1432 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1435 pub fn mk_subr(&self,
1436 a_is_expected: bool,
1437 origin: infer::SubregionOrigin,
1440 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1443 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1444 let old_region_lb = self.region_lb.get();
1445 self.region_lb.set(lb);
1447 self.region_lb.set(old_region_lb);
1451 pub fn type_error_message(&self,
1453 mk_msg: |String| -> String,
1455 err: Option<&ty::type_err>) {
1456 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1459 pub fn report_mismatched_return_types(&self,
1463 err: &ty::type_err) {
1465 if ty::type_is_error(e) || ty::type_is_error(a) {
1468 self.infcx().report_mismatched_types(sp, e, a, err)
1471 pub fn report_mismatched_types(&self,
1475 err: &ty::type_err) {
1476 self.infcx().report_mismatched_types(sp, e, a, err)
1480 pub enum LvaluePreference {
1485 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1486 expr_id: Option<ast::NodeId>,
1487 mut lvalue_pref: LvaluePreference,
1488 should_stop: |ty::t, uint| -> Option<T>)
1489 -> (ty::t, uint, Option<T>) {
1491 * Executes an autoderef loop for the type `t`. At each step, invokes
1492 * `should_stop` to decide whether to terminate the loop. Returns
1493 * the final type and number of derefs that it performed.
1495 * Note: this method does not modify the adjustments table. The caller is
1496 * responsible for inserting an AutoAdjustment record into the `fcx`
1497 * using one of the suitable methods.
1500 let mut t = base_ty;
1501 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1502 let resolved_t = structurally_resolved_type(fcx, sp, t);
1504 match should_stop(resolved_t, autoderefs) {
1505 Some(x) => return (resolved_t, autoderefs, Some(x)),
1509 // Otherwise, deref if type is derefable:
1510 let mt = match ty::deref(resolved_t, false) {
1511 Some(mt) => Some(mt),
1513 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1514 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1520 if mt.mutbl == ast::MutImmutable {
1521 lvalue_pref = NoPreference;
1524 None => return (resolved_t, autoderefs, None)
1528 // We've reached the recursion limit, error gracefully.
1529 fcx.tcx().sess.span_err(sp,
1530 format!("reached the recursion limit while auto-dereferencing {}",
1531 base_ty.repr(fcx.tcx())).as_slice());
1532 (ty::mk_err(), 0, None)
1535 /// Attempts to resolve a call expression as an overloaded call.
1536 fn try_overloaded_call(fcx: &FnCtxt,
1537 call_expression: &ast::Expr,
1538 callee: Gc<ast::Expr>,
1540 args: &[Gc<ast::Expr>])
1542 // Try `FnOnce`, then `FnMut`, then `Fn`.
1543 for &(maybe_function_trait, method_name) in [
1544 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1545 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1546 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1548 let function_trait = match maybe_function_trait {
1550 Some(function_trait) => function_trait,
1552 let method_callee = match method::lookup_in_trait(
1554 call_expression.span,
1560 DontAutoderefReceiver,
1561 IgnoreStaticMethods) {
1563 Some(method_callee) => method_callee,
1565 let method_call = MethodCall::expr(call_expression.id);
1566 let output_type = check_method_argument_types(fcx,
1567 call_expression.span,
1573 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1574 write_call(fcx, call_expression, output_type);
1576 if !fcx.tcx().sess.features.overloaded_calls.get() {
1577 fcx.tcx().sess.span_err(call_expression.span,
1578 "overloaded calls are experimental");
1579 fcx.tcx().sess.span_note(call_expression.span,
1580 "add `#[feature(overloaded_calls)]` to \
1581 the crate attributes to enable");
1590 fn try_overloaded_deref(fcx: &FnCtxt,
1592 method_call: Option<MethodCall>,
1593 base_expr: Option<&ast::Expr>,
1595 lvalue_pref: LvaluePreference)
1597 // Try DerefMut first, if preferred.
1598 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1599 (PreferMutLvalue, Some(trait_did)) => {
1600 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1601 token::intern("deref_mut"), trait_did,
1602 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1607 // Otherwise, fall back to Deref.
1608 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1609 (None, Some(trait_did)) => {
1610 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1611 token::intern("deref"), trait_did,
1612 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1614 (method, _) => method
1619 let ref_ty = ty::ty_fn_ret(method.ty);
1621 Some(method_call) => {
1622 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1626 ty::deref(ref_ty, true)
1632 fn check_method_argument_types(fcx: &FnCtxt,
1634 method_fn_ty: ty::t,
1635 callee_expr: &ast::Expr,
1636 args: &[Gc<ast::Expr>],
1637 deref_args: DerefArgs,
1638 tuple_arguments: TupleArgumentsFlag)
1640 // HACK(eddyb) ignore provided self (it has special typeck rules).
1641 let args = if tuple_arguments == DontTupleArguments {
1646 if ty::type_is_error(method_fn_ty) {
1647 let err_inputs = err_args(args.len());
1648 check_argument_types(fcx,
1650 err_inputs.as_slice(),
1658 match ty::get(method_fn_ty).sty {
1659 ty::ty_bare_fn(ref fty) => {
1660 // HACK(eddyb) ignore self in the definition (see above).
1661 check_argument_types(fcx,
1663 fty.sig.inputs.slice_from(1),
1672 fcx.tcx().sess.span_bug(callee_expr.span,
1673 "method without bare fn type");
1679 fn check_argument_types(fcx: &FnCtxt,
1681 fn_inputs: &[ty::t],
1682 callee_expr: &ast::Expr,
1683 args: &[Gc<ast::Expr>],
1684 deref_args: DerefArgs,
1686 tuple_arguments: TupleArgumentsFlag) {
1689 * Generic function that factors out common logic from
1690 * function calls, method calls and overloaded operators.
1693 let tcx = fcx.ccx.tcx;
1695 // Grab the argument types, supplying fresh type variables
1696 // if the wrong number of arguments were supplied
1697 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1703 let expected_arg_count = fn_inputs.len();
1704 let formal_tys = if tuple_arguments == TupleArguments {
1705 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1706 match ty::get(tuple_type).sty {
1707 ty::ty_tup(ref arg_types) => {
1708 if arg_types.len() != args.len() {
1710 "this function takes {} parameter{} \
1711 but {} parameter{} supplied",
1713 if arg_types.len() == 1 {""} else {"s"},
1715 if args.len() == 1 {" was"} else {"s were"});
1716 tcx.sess.span_err(sp, msg.as_slice());
1717 err_args(args.len())
1719 (*arg_types).clone()
1723 if args.len() != 0 {
1725 "this function takes 0 parameters \
1726 but {} parameter{} supplied",
1728 if args.len() == 1 {" was"} else {"s were"});
1729 tcx.sess.span_err(sp, msg.as_slice());
1736 "cannot use call notation; the first type \
1737 parameter for the function trait is neither a \
1739 err_args(supplied_arg_count)
1742 } else if expected_arg_count == supplied_arg_count {
1743 fn_inputs.iter().map(|a| *a).collect()
1744 } else if variadic {
1745 if supplied_arg_count >= expected_arg_count {
1746 fn_inputs.iter().map(|a| *a).collect()
1749 "this function takes at least {} parameter{} \
1750 but {} parameter{} supplied",
1752 if expected_arg_count == 1 {""} else {"s"},
1754 if supplied_arg_count == 1 {" was"} else {"s were"});
1756 tcx.sess.span_err(sp, msg.as_slice());
1758 err_args(supplied_arg_count)
1762 "this function takes {} parameter{} \
1763 but {} parameter{} supplied",
1765 if expected_arg_count == 1 {""} else {"s"},
1767 if supplied_arg_count == 1 {" was"} else {"s were"});
1769 tcx.sess.span_err(sp, msg.as_slice());
1771 err_args(supplied_arg_count)
1774 debug!("check_argument_types: formal_tys={:?}",
1775 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1777 // Check the arguments.
1778 // We do this in a pretty awful way: first we typecheck any arguments
1779 // that are not anonymous functions, then we typecheck the anonymous
1780 // functions. This is so that we have more information about the types
1781 // of arguments when we typecheck the functions. This isn't really the
1782 // right way to do this.
1783 let xs = [false, true];
1784 for check_blocks in xs.iter() {
1785 let check_blocks = *check_blocks;
1786 debug!("check_blocks={}", check_blocks);
1788 // More awful hacks: before we check the blocks, try to do
1789 // an "opportunistic" vtable resolution of any trait
1790 // bounds on the call.
1792 vtable::early_resolve_expr(callee_expr, fcx, true);
1795 // For variadic functions, we don't have a declared type for all of
1796 // the arguments hence we only do our usual type checking with
1797 // the arguments who's types we do know.
1798 let t = if variadic {
1800 } else if tuple_arguments == TupleArguments {
1805 for (i, arg) in args.iter().take(t).enumerate() {
1806 let is_block = match arg.node {
1807 ast::ExprFnBlock(..) |
1808 ast::ExprProc(..) => true,
1812 if is_block == check_blocks {
1813 debug!("checking the argument");
1814 let mut formal_ty = *formal_tys.get(i);
1818 match ty::get(formal_ty).sty {
1819 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1822 // So we hit this case when one implements the
1823 // operator traits but leaves an argument as
1824 // just T instead of &T. We'll catch it in the
1825 // mismatch impl/trait method phase no need to
1828 formal_ty = ty::mk_err();
1835 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1841 // We also need to make sure we at least write the ty of the other
1842 // arguments which we skipped above.
1844 for arg in args.iter().skip(expected_arg_count) {
1845 check_expr(fcx, &**arg);
1847 // There are a few types which get autopromoted when passed via varargs
1848 // in C but we just error out instead and require explicit casts.
1849 let arg_ty = structurally_resolved_type(fcx, arg.span,
1850 fcx.expr_ty(&**arg));
1851 match ty::get(arg_ty).sty {
1852 ty::ty_float(ast::TyF32) => {
1853 fcx.type_error_message(arg.span,
1855 format!("can't pass an {} to variadic \
1856 function, cast to c_double", t)
1859 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1860 fcx.type_error_message(arg.span, |t| {
1861 format!("can't pass {} to variadic \
1862 function, cast to c_int",
1866 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1867 fcx.type_error_message(arg.span, |t| {
1868 format!("can't pass {} to variadic \
1869 function, cast to c_uint",
1879 fn err_args(len: uint) -> Vec<ty::t> {
1880 Vec::from_fn(len, |_| ty::mk_err())
1883 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1884 fcx.write_ty(call_expr.id, output);
1887 // AST fragment checking
1888 fn check_lit(fcx: &FnCtxt,
1890 expected: Expectation)
1893 let tcx = fcx.ccx.tcx;
1896 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1897 ast::LitBinary(..) => {
1898 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1900 ast::LitByte(_) => ty::mk_u8(),
1901 ast::LitChar(_) => ty::mk_char(),
1902 ast::LitInt(_, t) => ty::mk_mach_int(t),
1903 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1904 ast::LitIntUnsuffixed(_) => {
1905 let opt_ty = expected.map_to_option(fcx, |sty| {
1907 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1908 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1909 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1910 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1911 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1915 opt_ty.unwrap_or_else(
1916 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1918 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1919 ast::LitFloatUnsuffixed(_) => {
1920 let opt_ty = expected.map_to_option(fcx, |sty| {
1922 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
1926 opt_ty.unwrap_or_else(
1927 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
1929 ast::LitNil => ty::mk_nil(),
1930 ast::LitBool(_) => ty::mk_bool()
1934 pub fn valid_range_bounds(ccx: &CrateCtxt,
1938 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1939 Some(val) => Some(val <= 0),
1944 pub fn check_expr_has_type(fcx: &FnCtxt,
1947 check_expr_with_unifier(
1948 fcx, expr, ExpectHasType(expected), NoPreference,
1949 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
1952 fn check_expr_coercable_to_type(fcx: &FnCtxt,
1955 check_expr_with_unifier(
1956 fcx, expr, ExpectHasType(expected), NoPreference,
1957 || demand::coerce(fcx, expr.span, expected, expr));
1960 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1961 check_expr_with_unifier(
1962 fcx, expr, ExpectHasType(expected), NoPreference,
1966 fn check_expr_with_expectation(fcx: &FnCtxt,
1968 expected: Expectation) {
1969 check_expr_with_unifier(
1970 fcx, expr, expected, NoPreference,
1974 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
1976 expected: Expectation,
1977 lvalue_pref: LvaluePreference)
1979 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1982 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1983 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
1986 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1987 lvalue_pref: LvaluePreference) {
1988 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
1992 // determine the `self` type, using fresh variables for all variables
1993 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1994 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1996 pub fn impl_self_ty(vcx: &VtableContext,
1997 span: Span, // (potential) receiver for this impl
2000 let tcx = vcx.tcx();
2002 let ity = ty::lookup_item_type(tcx, did);
2003 let (n_tps, rps, raw_ty) =
2004 (ity.generics.types.len(subst::TypeSpace),
2005 ity.generics.regions.get_vec(subst::TypeSpace),
2008 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2009 let tps = vcx.infcx.next_ty_vars(n_tps);
2010 let substs = subst::Substs::new_type(tps, rps);
2011 let substd_ty = raw_ty.subst(tcx, &substs);
2013 TypeAndSubsts { substs: substs, ty: substd_ty }
2016 // Only for fields! Returns <none> for methods>
2017 // Indifferent to privacy flags
2018 pub fn lookup_field_ty(tcx: &ty::ctxt,
2019 class_id: ast::DefId,
2020 items: &[ty::field_ty],
2021 fieldname: ast::Name,
2022 substs: &subst::Substs) -> Option<ty::t> {
2024 let o_field = items.iter().find(|f| f.name == fieldname);
2025 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2028 // Controls whether the arguments are automatically referenced. This is useful
2029 // for overloaded binary and unary operators.
2030 pub enum DerefArgs {
2035 /// Controls whether the arguments are tupled. This is used for the call
2038 /// Tupling means that all call-side arguments are packed into a tuple and
2039 /// passed as a single parameter. For example, if tupling is enabled, this
2042 /// fn f(x: (int, int))
2044 /// Can be called as:
2051 #[deriving(Clone, Eq, PartialEq)]
2052 enum TupleArgumentsFlag {
2058 /// If an expression has any sub-expressions that result in a type error,
2059 /// inspecting that expression's type with `ty::type_is_error` will return
2060 /// true. Likewise, if an expression is known to diverge, inspecting its
2061 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2062 /// strict, _|_ can appear in the type of an expression that does not,
2063 /// itself, diverge: for example, fn() -> _|_.)
2064 /// Note that inspecting a type's structure *directly* may expose the fact
2065 /// that there are actually multiple representations for both `ty_err` and
2066 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2067 fn check_expr_with_unifier(fcx: &FnCtxt,
2069 expected: Expectation,
2070 lvalue_pref: LvaluePreference,
2073 debug!(">> typechecking");
2075 // A generic function for doing all of the checking for call expressions
2076 fn check_call(fcx: &FnCtxt,
2077 call_expr: &ast::Expr,
2079 args: &[Gc<ast::Expr>]) {
2080 // Store the type of `f` as the type of the callee
2081 let fn_ty = fcx.expr_ty(f);
2083 // Extract the function signature from `in_fty`.
2084 let fn_sty = structure_of(fcx, f.span, fn_ty);
2086 // This is the "default" function signature, used in case of error.
2087 // In that case, we check each argument against "error" in order to
2088 // set up all the node type bindings.
2089 let error_fn_sig = FnSig {
2090 binder_id: ast::CRATE_NODE_ID,
2091 inputs: err_args(args.len()),
2092 output: ty::mk_err(),
2096 let fn_sig = match *fn_sty {
2097 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2098 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2100 fcx.type_error_message(call_expr.span, |actual| {
2101 format!("expected function but found `{}`", actual)
2107 // Replace any bound regions that appear in the function
2108 // signature with region variables
2109 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2110 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2113 // Call the generic checker.
2114 check_argument_types(fcx,
2116 fn_sig.inputs.as_slice(),
2121 DontTupleArguments);
2123 write_call(fcx, call_expr, fn_sig.output);
2126 // Checks a method call.
2127 fn check_method_call(fcx: &FnCtxt,
2129 method_name: ast::SpannedIdent,
2130 args: &[Gc<ast::Expr>],
2131 tps: &[ast::P<ast::Ty>]) {
2132 let rcvr = args[0].clone();
2133 // We can't know if we need &mut self before we look up the method,
2134 // so treat the receiver as mutable just in case - only explicit
2135 // overloaded dereferences care about the distinction.
2136 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2138 // no need to check for bot/err -- callee does that
2139 let expr_t = structurally_resolved_type(fcx,
2141 fcx.expr_ty(&*rcvr));
2143 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2144 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2145 method_name.node.name,
2146 expr_t, tps.as_slice(),
2148 CheckTraitsAndInherentMethods,
2149 AutoderefReceiver, IgnoreStaticMethods) {
2151 let method_ty = method.ty;
2152 let method_call = MethodCall::expr(expr.id);
2153 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2157 debug!("(checking method call) failing expr is {}", expr.id);
2159 fcx.type_error_message(method_name.span,
2161 format!("type `{}` does not implement any \
2162 method in scope named `{}`",
2164 token::get_ident(method_name.node))
2169 // Add error type for the result
2170 fcx.write_error(expr.id);
2172 // Check for potential static matches (missing self parameters)
2176 method_name.node.name,
2180 CheckTraitsAndInherentMethods,
2181 DontAutoderefReceiver,
2182 ReportStaticMethods);
2188 // Call the generic checker.
2189 let ret_ty = check_method_argument_types(fcx,
2195 DontTupleArguments);
2197 write_call(fcx, expr, ret_ty);
2200 // A generic function for checking the then and else in an if
2202 fn check_then_else(fcx: &FnCtxt,
2203 cond_expr: &ast::Expr,
2204 then_blk: &ast::Block,
2205 opt_else_expr: Option<Gc<ast::Expr>>,
2208 expected: Expectation) {
2209 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2211 let branches_ty = match opt_else_expr {
2212 Some(ref else_expr) => {
2213 // Disregard "castable to" expectations because they
2214 // can lead us astray. Consider for example `if cond
2215 // {22} else {c} as u8` -- if we propagate the
2216 // "castable to u8" constraint to 22, it will pick the
2217 // type 22u8, which is overly constrained (c might not
2218 // be a u8). In effect, the problem is that the
2219 // "castable to" expectation is not the tightest thing
2220 // we can say, so we want to drop it in this case.
2221 // The tightest thing we can say is "must unify with
2222 // else branch". Note that in the case of a "has type"
2223 // constraint, this limitation does not hold.
2224 let expected = expected.only_has_type();
2226 check_block_with_expected(fcx, then_blk, expected);
2227 let then_ty = fcx.node_ty(then_blk.id);
2228 check_expr_with_expectation(fcx, &**else_expr, expected);
2229 let else_ty = fcx.expr_ty(&**else_expr);
2230 infer::common_supertype(fcx.infcx(),
2231 infer::IfExpression(sp),
2237 check_block_no_value(fcx, then_blk);
2242 let cond_ty = fcx.expr_ty(cond_expr);
2243 let if_ty = if ty::type_is_error(cond_ty) {
2245 } else if ty::type_is_bot(cond_ty) {
2251 fcx.write_ty(id, if_ty);
2254 fn lookup_op_method(fcx: &FnCtxt,
2258 trait_did: Option<ast::DefId>,
2259 args: &[Gc<ast::Expr>],
2260 autoderef_receiver: AutoderefReceiverFlag,
2261 unbound_method: ||) -> ty::t {
2262 let method = match trait_did {
2263 Some(trait_did) => {
2264 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2265 trait_did, self_t, [], autoderef_receiver,
2266 IgnoreStaticMethods)
2272 let method_ty = method.ty;
2273 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2274 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2275 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2276 check_method_argument_types(fcx,
2286 // Check the args anyway
2287 // so we get all the error messages
2288 let expected_ty = ty::mk_err();
2289 check_method_argument_types(fcx,
2295 DontTupleArguments);
2301 // could be either an expr_binop or an expr_assign_binop
2302 fn check_binop(fcx: &FnCtxt,
2307 is_binop_assignment: IsBinopAssignment) {
2308 let tcx = fcx.ccx.tcx;
2310 let lvalue_pref = match is_binop_assignment {
2311 BinopAssignment => PreferMutLvalue,
2312 SimpleBinop => NoPreference
2314 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2316 // Callee does bot / err checking
2317 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2318 fcx.expr_ty(&*lhs));
2320 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2321 // Shift is a special case: rhs must be uint, no matter what lhs is
2322 check_expr_has_type(fcx, rhs, ty::mk_uint());
2323 fcx.write_ty(expr.id, lhs_t);
2327 if ty::is_binopable(tcx, lhs_t, op) {
2328 let tvar = fcx.infcx().next_ty_var();
2329 demand::suptype(fcx, expr.span, tvar, lhs_t);
2330 check_expr_has_type(fcx, &*rhs, tvar);
2332 let result_t = match op {
2333 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2335 if ty::type_is_simd(tcx, lhs_t) {
2336 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2337 fcx.type_error_message(expr.span,
2339 format!("binary comparison \
2340 operation `{}` not \
2341 supported for floating \
2342 point SIMD vector `{}`",
2343 ast_util::binop_to_str(op),
2360 fcx.write_ty(expr.id, result_t);
2364 if op == ast::BiOr || op == ast::BiAnd {
2365 // This is an error; one of the operands must have the wrong
2367 fcx.write_error(expr.id);
2368 fcx.write_error(rhs.id);
2369 fcx.type_error_message(expr.span,
2371 format!("binary operation `{}` cannot be applied \
2373 ast_util::binop_to_str(op),
2380 // Check for overloaded operators if not an assignment.
2381 let result_t = if is_binop_assignment == SimpleBinop {
2382 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2384 fcx.type_error_message(expr.span,
2386 format!("binary assignment \
2388 cannot be applied to \
2390 ast_util::binop_to_str(op),
2395 check_expr(fcx, &*rhs);
2399 fcx.write_ty(expr.id, result_t);
2400 if ty::type_is_error(result_t) {
2401 fcx.write_ty(rhs.id, result_t);
2405 fn check_user_binop(fcx: &FnCtxt,
2407 lhs_expr: Gc<ast::Expr>,
2408 lhs_resolved_t: ty::t,
2410 rhs: Gc<ast::Expr>) -> ty::t {
2411 let tcx = fcx.ccx.tcx;
2412 let lang = &tcx.lang_items;
2413 let (name, trait_did) = match op {
2414 ast::BiAdd => ("add", lang.add_trait()),
2415 ast::BiSub => ("sub", lang.sub_trait()),
2416 ast::BiMul => ("mul", lang.mul_trait()),
2417 ast::BiDiv => ("div", lang.div_trait()),
2418 ast::BiRem => ("rem", lang.rem_trait()),
2419 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2420 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2421 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2422 ast::BiShl => ("shl", lang.shl_trait()),
2423 ast::BiShr => ("shr", lang.shr_trait()),
2424 ast::BiLt => ("lt", lang.ord_trait()),
2425 ast::BiLe => ("le", lang.ord_trait()),
2426 ast::BiGe => ("ge", lang.ord_trait()),
2427 ast::BiGt => ("gt", lang.ord_trait()),
2428 ast::BiEq => ("eq", lang.eq_trait()),
2429 ast::BiNe => ("ne", lang.eq_trait()),
2430 ast::BiAnd | ast::BiOr => {
2431 check_expr(fcx, &*rhs);
2432 return ty::mk_err();
2435 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2436 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2437 fcx.type_error_message(ex.span, |actual| {
2438 format!("binary operation `{}` cannot be applied to type `{}`",
2439 ast_util::binop_to_str(op),
2441 }, lhs_resolved_t, None)
2445 fn check_user_unop(fcx: &FnCtxt,
2448 trait_did: Option<ast::DefId>,
2450 rhs_expr: Gc<ast::Expr>,
2451 rhs_t: ty::t) -> ty::t {
2452 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2453 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2454 fcx.type_error_message(ex.span, |actual| {
2455 format!("cannot apply unary operator `{}` to type `{}`",
2461 fn check_expr_fn(fcx: &FnCtxt,
2463 store: ty::TraitStore,
2465 body: ast::P<ast::Block>,
2466 expected: Expectation) {
2467 let tcx = fcx.ccx.tcx;
2469 // Find the expected input/output types (if any). Substitute
2470 // fresh bound regions for any bound regions we find in the
2471 // expected types so as to avoid capture.
2472 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2475 expected_bounds) = {
2476 match expected_sty {
2477 Some(ty::ty_closure(ref cenv)) => {
2479 replace_late_bound_regions_in_fn_sig(
2481 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2482 let onceness = match (&store, &cenv.store) {
2483 // As the closure type and onceness go, only three
2484 // combinations are legit:
2488 // If the actual and expected closure type disagree with
2489 // each other, set expected onceness to be always Once or
2490 // Many according to the actual type. Otherwise, it will
2491 // yield either an illegal "many proc" or a less known
2492 // "once closure" in the error message.
2493 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2494 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2496 (&ty::UniqTraitStore, _) => ast::Once,
2497 (&ty::RegionTraitStore(..), _) => ast::Many,
2499 (Some(sig), onceness, cenv.bounds)
2502 // Not an error! Means we're inferring the closure type
2503 let mut bounds = ty::empty_builtin_bounds();
2504 let onceness = match expr.node {
2505 ast::ExprProc(..) => {
2506 bounds.add(ty::BoundSend);
2511 (None, onceness, bounds)
2516 // construct the function type
2517 let fn_ty = astconv::ty_of_closure(fcx,
2525 let fty_sig = fn_ty.sig.clone();
2526 let fty = ty::mk_closure(tcx, fn_ty);
2527 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2529 fcx.write_ty(expr.id, fty);
2531 // If the closure is a stack closure and hasn't had some non-standard
2532 // style inferred for it, then check it under its parent's style.
2533 // Otherwise, use its own
2534 let (inherited_style, id) = match store {
2535 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2536 fcx.ps.borrow().def),
2537 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2540 check_fn(fcx.ccx, inherited_style, &fty_sig,
2541 &*decl, id, &*body, fcx.inh);
2545 // Check field access expressions
2546 fn check_field(fcx: &FnCtxt,
2548 lvalue_pref: LvaluePreference,
2550 field: &ast::SpannedIdent,
2551 tys: &[ast::P<ast::Ty>]) {
2552 let tcx = fcx.ccx.tcx;
2553 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2554 let expr_t = structurally_resolved_type(fcx, expr.span,
2556 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2557 let (_, autoderefs, field_ty) =
2558 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2559 match ty::get(base_t).sty {
2560 ty::ty_struct(base_id, ref substs) => {
2561 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2562 let fields = ty::lookup_struct_fields(tcx, base_id);
2563 lookup_field_ty(tcx, base_id, fields.as_slice(),
2564 field.node.name, &(*substs))
2571 fcx.write_ty(expr.id, field_ty);
2572 fcx.write_autoderef_adjustment(base.id, autoderefs);
2578 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2579 match method::lookup(fcx,
2586 CheckTraitsAndInherentMethods,
2588 IgnoreStaticMethods) {
2590 fcx.type_error_message(
2593 format!("attempted to take value of method `{}` on type \
2594 `{}`", token::get_ident(field.node), actual)
2598 tcx.sess.span_note(field.span,
2599 "maybe a missing `()` to call it? If not, try an anonymous function.");
2603 fcx.type_error_message(
2606 format!("attempted access of field `{}` on \
2607 type `{}`, but no field with that \
2609 token::get_ident(field.node),
2616 fcx.write_error(expr.id);
2619 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2622 class_id: ast::DefId,
2623 node_id: ast::NodeId,
2624 substitutions: subst::Substs,
2625 field_types: &[ty::field_ty],
2626 ast_fields: &[ast::Field],
2627 check_completeness: bool) {
2628 let tcx = fcx.ccx.tcx;
2630 let mut class_field_map = HashMap::new();
2631 let mut fields_found = 0;
2632 for field in field_types.iter() {
2633 class_field_map.insert(field.name, (field.id, false));
2636 let mut error_happened = false;
2638 // Typecheck each field.
2639 for field in ast_fields.iter() {
2640 let mut expected_field_type = ty::mk_err();
2642 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2645 fcx.type_error_message(
2648 format!("structure `{}` has no field named `{}`",
2649 actual, token::get_ident(field.ident.node))
2653 error_happened = true;
2655 Some((_, true)) => {
2658 format!("field `{}` specified more than once",
2659 token::get_ident(field.ident
2660 .node)).as_slice());
2661 error_happened = true;
2663 Some((field_id, false)) => {
2664 expected_field_type =
2665 ty::lookup_field_type(
2666 tcx, class_id, field_id, &substitutions);
2667 class_field_map.insert(
2668 field.ident.node.name, (field_id, true));
2672 // Make sure to give a type to the field even if there's
2673 // an error, so we can continue typechecking
2674 check_expr_coercable_to_type(
2677 expected_field_type);
2681 fcx.write_error(node_id);
2684 if check_completeness && !error_happened {
2685 // Make sure the programmer specified all the fields.
2686 assert!(fields_found <= field_types.len());
2687 if fields_found < field_types.len() {
2688 let mut missing_fields = Vec::new();
2689 for class_field in field_types.iter() {
2690 let name = class_field.name;
2691 let (_, seen) = *class_field_map.get(&name);
2693 missing_fields.push(
2694 format!("`{}`", token::get_name(name).get()))
2698 tcx.sess.span_err(span,
2700 "missing field{}: {fields}",
2701 if missing_fields.len() == 1 {""} else {"s"},
2702 fields = missing_fields.connect(", ")).as_slice());
2706 if !error_happened {
2707 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2708 class_id, substitutions));
2712 fn check_struct_constructor(fcx: &FnCtxt,
2714 span: codemap::Span,
2715 class_id: ast::DefId,
2716 fields: &[ast::Field],
2717 base_expr: Option<Gc<ast::Expr>>) {
2718 let tcx = fcx.ccx.tcx;
2720 // Look up the number of type parameters and the raw type, and
2721 // determine whether the class is region-parameterized.
2722 let item_type = ty::lookup_item_type(tcx, class_id);
2723 let raw_type = item_type.ty;
2725 // Generate the struct type.
2726 let substitutions = fcx.infcx().fresh_substs_for_type(
2727 span, &item_type.generics);
2728 let mut struct_type = raw_type.subst(tcx, &substitutions);
2730 // Look up and check the fields.
2731 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2732 check_struct_or_variant_fields(fcx,
2738 class_fields.as_slice(),
2740 base_expr.is_none());
2741 if ty::type_is_error(fcx.node_ty(id)) {
2742 struct_type = ty::mk_err();
2745 // Check the base expression if necessary.
2748 Some(base_expr) => {
2749 check_expr_has_type(fcx, &*base_expr, struct_type);
2750 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2751 struct_type = ty::mk_bot();
2756 // Write in the resulting type.
2757 fcx.write_ty(id, struct_type);
2760 fn check_struct_enum_variant(fcx: &FnCtxt,
2762 span: codemap::Span,
2763 enum_id: ast::DefId,
2764 variant_id: ast::DefId,
2765 fields: &[ast::Field]) {
2766 let tcx = fcx.ccx.tcx;
2768 // Look up the number of type parameters and the raw type, and
2769 // determine whether the enum is region-parameterized.
2770 let item_type = ty::lookup_item_type(tcx, enum_id);
2771 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2772 let enum_type = item_type.ty.subst(tcx, &substitutions);
2774 // Look up and check the enum variant fields.
2775 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2776 check_struct_or_variant_fields(fcx,
2782 variant_fields.as_slice(),
2785 fcx.write_ty(id, enum_type);
2788 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2790 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2791 expected: Expectation)
2792 -> (ExprCheckerWithTy, ty::t) {
2793 let tcx = fcx.ccx.tcx;
2794 let (coerce, t) = match expected {
2795 // If we're given an expected type, we can try to coerce to it
2796 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2797 // Otherwise we just leave the type to be resolved later
2798 _ => (false, fcx.infcx().next_ty_var())
2801 (check_expr_coercable_to_type, t)
2803 (check_expr_has_type, t)
2807 let tcx = fcx.ccx.tcx;
2810 ast::ExprVstore(ev, vst) => {
2811 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
2812 let typ = match ev.node {
2813 ast::ExprVec(ref args) => {
2814 let mutability = match vst {
2815 ast::ExprVstoreMutSlice => ast::MutMutable,
2816 _ => ast::MutImmutable,
2818 let mut any_error = false;
2819 let mut any_bot = false;
2820 for e in args.iter() {
2821 check(fcx, &**e, t);
2822 let arg_t = fcx.expr_ty(&**e);
2823 if ty::type_is_error(arg_t) {
2826 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},
2839 mutbl: mutability })
2842 ast::ExprRepeat(ref element, ref count_expr) => {
2843 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2844 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2845 let mutability = match vst {
2846 ast::ExprVstoreMutSlice => ast::MutMutable,
2847 _ => ast::MutImmutable,
2849 check(fcx, &**element, t);
2850 let arg_t = fcx.expr_ty(&**element);
2851 if ty::type_is_error(arg_t) {
2853 } else if ty::type_is_bot(arg_t) {
2856 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2857 ty::mt{ ty: ty::mk_vec(tcx,
2858 ty::mt {ty: t, mutbl: mutability},
2863 ast::ExprLit(_) => {
2864 let error = if vst == ast::ExprVstoreSlice {
2865 "`&\"string\"` has been removed; use `\"string\"` instead"
2867 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2869 tcx.sess.span_err(expr.span, error);
2872 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2874 fcx.write_ty(ev.id, typ);
2875 fcx.write_ty(id, typ);
2878 ast::ExprBox(ref place, ref subexpr) => {
2879 check_expr(fcx, &**place);
2880 check_expr(fcx, &**subexpr);
2882 let mut checked = false;
2884 ast::ExprPath(ref path) => {
2885 // FIXME(pcwalton): For now we hardcode the two permissible
2886 // places: the exchange heap and the managed heap.
2887 let definition = lookup_def(fcx, path.span, place.id);
2888 let def_id = definition.def_id();
2889 if tcx.lang_items.exchange_heap() == Some(def_id) {
2890 fcx.write_ty(id, ty::mk_uniq(tcx,
2891 fcx.expr_ty(&**subexpr)));
2893 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2894 fcx.write_ty(id, ty::mk_box(tcx,
2895 fcx.expr_ty(&**subexpr)));
2903 tcx.sess.span_err(expr.span,
2904 "only the managed heap and exchange heap are \
2905 currently supported");
2906 fcx.write_ty(id, ty::mk_err());
2910 ast::ExprLit(lit) => {
2911 let typ = check_lit(fcx, lit, expected);
2912 fcx.write_ty(id, typ);
2914 ast::ExprBinary(op, ref lhs, ref rhs) => {
2915 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2917 let lhs_ty = fcx.expr_ty(&**lhs);
2918 let rhs_ty = fcx.expr_ty(&**rhs);
2919 if ty::type_is_error(lhs_ty) ||
2920 ty::type_is_error(rhs_ty) {
2921 fcx.write_error(id);
2923 else if ty::type_is_bot(lhs_ty) ||
2924 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2928 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2929 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
2931 let lhs_t = fcx.expr_ty(&**lhs);
2932 let result_t = fcx.expr_ty(expr);
2933 demand::suptype(fcx, expr.span, result_t, lhs_t);
2935 let tcx = fcx.tcx();
2936 if !ty::expr_is_lval(tcx, &**lhs) {
2937 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2940 // Overwrite result of check_binop...this preserves existing behavior
2941 // but seems quite dubious with regard to user-defined methods
2942 // and so forth. - Niko
2943 if !ty::type_is_error(result_t)
2944 && !ty::type_is_bot(result_t) {
2945 fcx.write_nil(expr.id);
2948 ast::ExprUnary(unop, ref oprnd) => {
2949 let expected = expected.only_has_type();
2950 let expected_inner = expected.map(fcx, |sty| {
2952 ast::UnBox | ast::UnUniq => match *sty {
2953 ty::ty_box(ty) | ty::ty_uniq(ty) => {
2960 ast::UnNot | ast::UnNeg => {
2968 let lvalue_pref = match unop {
2969 ast::UnDeref => lvalue_pref,
2972 check_expr_with_expectation_and_lvalue_pref(
2973 fcx, &**oprnd, expected_inner, lvalue_pref);
2974 let mut oprnd_t = fcx.expr_ty(&**oprnd);
2975 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2978 oprnd_t = ty::mk_box(tcx, oprnd_t)
2981 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2984 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2985 oprnd_t = match ty::deref(oprnd_t, true) {
2987 None => match try_overloaded_deref(fcx, expr.span,
2988 Some(MethodCall::expr(expr.id)),
2989 Some(&**oprnd), oprnd_t, lvalue_pref) {
2992 let is_newtype = match ty::get(oprnd_t).sty {
2993 ty::ty_struct(did, ref substs) => {
2994 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2996 && fields.get(0).ident ==
2997 token::special_idents::unnamed_field
3002 // This is an obsolete struct deref
3003 tcx.sess.span_err(expr.span,
3004 "single-field tuple-structs can \
3005 no longer be dereferenced");
3007 fcx.type_error_message(expr.span, |actual| {
3008 format!("type `{}` cannot be \
3009 dereferenced", actual)
3018 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3020 if !(ty::type_is_integral(oprnd_t) ||
3021 ty::get(oprnd_t).sty == ty::ty_bool) {
3022 oprnd_t = check_user_unop(fcx, "!", "not",
3023 tcx.lang_items.not_trait(),
3024 expr, oprnd.clone(), oprnd_t);
3028 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3030 if !(ty::type_is_integral(oprnd_t) ||
3031 ty::type_is_fp(oprnd_t)) {
3032 oprnd_t = check_user_unop(fcx, "-", "neg",
3033 tcx.lang_items.neg_trait(),
3034 expr, oprnd.clone(), oprnd_t);
3039 fcx.write_ty(id, oprnd_t);
3041 ast::ExprAddrOf(mutbl, ref oprnd) => {
3042 let expected = expected.only_has_type();
3043 let hint = expected.map(fcx, |sty| {
3044 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3045 _ => NoExpectation }
3047 let lvalue_pref = match mutbl {
3048 ast::MutMutable => PreferMutLvalue,
3049 ast::MutImmutable => NoPreference
3051 check_expr_with_expectation_and_lvalue_pref(fcx,
3056 // Note: at this point, we cannot say what the best lifetime
3057 // is to use for resulting pointer. We want to use the
3058 // shortest lifetime possible so as to avoid spurious borrowck
3059 // errors. Moreover, the longest lifetime will depend on the
3060 // precise details of the value whose address is being taken
3061 // (and how long it is valid), which we don't know yet until type
3062 // inference is complete.
3064 // Therefore, here we simply generate a region variable. The
3065 // region inferencer will then select the ultimate value.
3066 // Finally, borrowck is charged with guaranteeing that the
3067 // value whose address was taken can actually be made to live
3068 // as long as it needs to live.
3069 let region = fcx.infcx().next_region_var(
3070 infer::AddrOfRegion(expr.span));
3072 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3073 let oprnd_t = if ty::type_is_error(tm.ty) {
3075 } else if ty::type_is_bot(tm.ty) {
3079 ty::mk_rptr(tcx, region, tm)
3081 fcx.write_ty(id, oprnd_t);
3083 ast::ExprPath(ref pth) => {
3084 let defn = lookup_def(fcx, pth.span, id);
3085 let pty = polytype_for_def(fcx, expr.span, defn);
3086 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3088 ast::ExprInlineAsm(ref ia) => {
3089 for &(_, ref input) in ia.inputs.iter() {
3090 check_expr(fcx, &**input);
3092 for &(_, ref out) in ia.outputs.iter() {
3093 check_expr(fcx, &**out);
3097 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3098 ast::ExprBreak(_) => { fcx.write_bot(id); }
3099 ast::ExprAgain(_) => { fcx.write_bot(id); }
3100 ast::ExprRet(ref expr_opt) => {
3101 let ret_ty = fcx.ret_ty;
3103 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3104 ret_ty, ty::mk_nil()) {
3105 Ok(_) => { /* fall through */ }
3109 "`return;` in function returning non-nil");
3113 check_expr_has_type(fcx, &**e, ret_ty);
3118 ast::ExprParen(a) => {
3119 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3120 fcx.write_ty(id, fcx.expr_ty(a));
3122 ast::ExprAssign(ref lhs, ref rhs) => {
3123 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3125 let tcx = fcx.tcx();
3126 if !ty::expr_is_lval(tcx, &**lhs) {
3127 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3130 let lhs_ty = fcx.expr_ty(&**lhs);
3131 check_expr_has_type(fcx, &**rhs, lhs_ty);
3132 let rhs_ty = fcx.expr_ty(&**rhs);
3134 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3135 fcx.write_error(id);
3136 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3142 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3143 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3144 id, expr.span, expected);
3146 ast::ExprWhile(ref cond, ref body) => {
3147 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3148 check_block_no_value(fcx, &**body);
3149 let cond_ty = fcx.expr_ty(&**cond);
3150 let body_ty = fcx.node_ty(body.id);
3151 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3152 fcx.write_error(id);
3154 else if ty::type_is_bot(cond_ty) {
3161 ast::ExprForLoop(..) =>
3162 fail!("non-desugared expr_for_loop"),
3163 ast::ExprLoop(ref body, _) => {
3164 check_block_no_value(fcx, &**body);
3165 if !may_break(tcx, expr.id, body.clone()) {
3172 ast::ExprMatch(ref discrim, ref arms) => {
3173 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3175 ast::ExprFnBlock(ref decl, ref body) => {
3176 let region = astconv::opt_ast_region_to_region(fcx,
3182 ty::RegionTraitStore(region, ast::MutMutable),
3187 ast::ExprProc(ref decl, ref body) => {
3195 ast::ExprBlock(ref b) => {
3196 check_block_with_expected(fcx, &**b, expected);
3197 fcx.write_ty(id, fcx.node_ty(b.id));
3199 ast::ExprCall(ref f, ref args) => {
3200 // Index expressions need to be handled separately, to inform them
3201 // that they appear in call position.
3202 check_expr(fcx, &**f);
3203 let f_ty = fcx.expr_ty(&**f);
3205 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3206 check_call(fcx, expr, &**f, args.as_slice());
3207 let (args_bot, args_err) = args.iter().fold((false, false),
3208 |(rest_bot, rest_err), a| {
3209 // is this not working?
3210 let a_ty = fcx.expr_ty(&**a);
3211 (rest_bot || ty::type_is_bot(a_ty),
3212 rest_err || ty::type_is_error(a_ty))});
3213 if ty::type_is_error(f_ty) || args_err {
3214 fcx.write_error(id);
3216 else if ty::type_is_bot(f_ty) || args_bot {
3221 ast::ExprMethodCall(ident, ref tps, ref args) => {
3222 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3223 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3224 let (args_bot, args_err) = arg_tys.fold((false, false),
3225 |(rest_bot, rest_err), a| {
3226 (rest_bot || ty::type_is_bot(a),
3227 rest_err || ty::type_is_error(a))});
3229 fcx.write_error(id);
3230 } else if args_bot {
3234 ast::ExprCast(ref e, ref t) => {
3235 check_cast(fcx, &**e, &**t, id, expr.span);
3237 ast::ExprVec(ref args) => {
3238 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3239 for e in args.iter() {
3240 check(fcx, &**e, t);
3242 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3244 fcx.write_ty(id, typ);
3246 ast::ExprRepeat(ref element, ref count_expr) => {
3247 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3248 let count = ty::eval_repeat_count(fcx, &**count_expr);
3249 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3250 check(fcx, &**element, t);
3251 let element_ty = fcx.expr_ty(&**element);
3252 if ty::type_is_error(element_ty) {
3253 fcx.write_error(id);
3255 else if ty::type_is_bot(element_ty) {
3259 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3261 fcx.write_ty(id, t);
3264 ast::ExprTup(ref elts) => {
3265 let expected = expected.only_has_type();
3266 let flds = expected.map_to_option(fcx, |sty| {
3268 ty::ty_tup(ref flds) => Some((*flds).clone()),
3272 let mut bot_field = false;
3273 let mut err_field = false;
3275 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3276 let opt_hint = match flds {
3277 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3280 check_expr_with_expectation(fcx, *e, opt_hint);
3281 let t = fcx.expr_ty(*e);
3282 err_field = err_field || ty::type_is_error(t);
3283 bot_field = bot_field || ty::type_is_bot(t);
3288 } else if err_field {
3289 fcx.write_error(id);
3291 let typ = ty::mk_tup(tcx, elt_ts);
3292 fcx.write_ty(id, typ);
3295 ast::ExprStruct(ref path, ref fields, base_expr) => {
3296 // Resolve the path.
3297 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3299 Some(def::DefStruct(type_def_id)) => {
3300 check_struct_constructor(fcx, id, expr.span, type_def_id,
3301 fields.as_slice(), base_expr);
3303 Some(def::DefVariant(enum_id, variant_id, _)) => {
3304 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3305 variant_id, fields.as_slice());
3308 tcx.sess.span_bug(path.span,
3309 "structure constructor does not name a structure type");
3313 ast::ExprField(ref base, ref field, ref tys) => {
3314 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3316 ast::ExprIndex(ref base, ref idx) => {
3317 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3318 check_expr(fcx, &**idx);
3319 let raw_base_t = fcx.expr_ty(&**base);
3320 let idx_t = fcx.expr_ty(&**idx);
3321 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3322 fcx.write_ty(id, raw_base_t);
3323 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3324 fcx.write_ty(id, idx_t);
3326 let (base_t, autoderefs, field_ty) =
3327 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3328 lvalue_pref, |base_t, _| ty::index(base_t));
3331 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3332 fcx.write_ty(id, mt.ty);
3333 fcx.write_autoderef_adjustment(base.id, autoderefs);
3336 let resolved = structurally_resolved_type(fcx,
3339 let ret_ty = lookup_op_method(fcx,
3342 token::intern("index"),
3343 tcx.lang_items.index_trait(),
3344 [base.clone(), idx.clone()],
3347 fcx.type_error_message(expr.span,
3349 format!("cannot index a \
3356 fcx.write_ty(id, ret_ty);
3363 debug!("type of expr({}) {} is...", expr.id,
3364 syntax::print::pprust::expr_to_str(expr));
3365 debug!("... {}, expected is {}",
3366 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3373 fn only_has_type(self) -> Expectation {
3375 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3376 ExpectHasType(t) => ExpectHasType(t)
3380 // Resolves `expected` by a single level if it is a variable. If
3381 // there is no expected type or resolution is not possible (e.g.,
3382 // no constraints yet present), just returns `None`.
3383 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3388 ExpectCastableToType(t) => {
3389 ExpectCastableToType(
3390 fcx.infcx().resolve_type_vars_if_possible(t))
3392 ExpectHasType(t) => {
3394 fcx.infcx().resolve_type_vars_if_possible(t))
3399 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3400 match self.resolve(fcx) {
3401 NoExpectation => NoExpectation,
3402 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3406 fn map_to_option<O>(self,
3408 unpack: |&ty::sty| -> Option<O>)
3411 match self.resolve(fcx) {
3412 NoExpectation => None,
3413 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3418 impl Repr for Expectation {
3419 fn repr(&self, tcx: &ty::ctxt) -> String {
3421 NoExpectation => format!("NoExpectation"),
3422 ExpectHasType(t) => format!("ExpectHasType({})",
3424 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3430 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3431 if !type_is_uint(fcx, sp, t) {
3432 fcx.type_error_message(sp, |actual| {
3433 format!("mismatched types: expected `uint` type but found `{}`",
3439 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3440 if !type_is_integral(fcx, sp, t) {
3441 fcx.type_error_message(sp, |actual| {
3442 format!("mismatched types: expected integral type but found `{}`",
3448 pub fn check_decl_initializer(fcx: &FnCtxt,
3452 let local_ty = fcx.local_ty(init.span, nid);
3453 check_expr_coercable_to_type(fcx, init, local_ty)
3456 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3457 let tcx = fcx.ccx.tcx;
3459 let t = fcx.local_ty(local.span, local.id);
3460 fcx.write_ty(local.id, t);
3464 check_decl_initializer(fcx, local.id, &**init);
3465 let init_ty = fcx.expr_ty(&**init);
3466 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3467 fcx.write_ty(local.id, init_ty);
3473 let pcx = pat_ctxt {
3475 map: pat_id_map(&tcx.def_map, &*local.pat),
3477 _match::check_pat(&pcx, &*local.pat, t);
3478 let pat_ty = fcx.node_ty(local.pat.id);
3479 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3480 fcx.write_ty(local.id, pat_ty);
3484 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3486 let mut saw_bot = false;
3487 let mut saw_err = false;
3489 ast::StmtDecl(decl, id) => {
3492 ast::DeclLocal(ref l) => {
3493 check_decl_local(fcx, &**l);
3494 let l_t = fcx.node_ty(l.id);
3495 saw_bot = saw_bot || ty::type_is_bot(l_t);
3496 saw_err = saw_err || ty::type_is_error(l_t);
3498 ast::DeclItem(_) => {/* ignore for now */ }
3501 ast::StmtExpr(ref expr, id) => {
3503 // Check with expected type of ()
3504 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3505 let expr_ty = fcx.expr_ty(&**expr);
3506 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3507 saw_err = saw_err || ty::type_is_error(expr_ty);
3509 ast::StmtSemi(ref expr, id) => {
3511 check_expr(fcx, &**expr);
3512 let expr_ty = fcx.expr_ty(&**expr);
3513 saw_bot |= ty::type_is_bot(expr_ty);
3514 saw_err |= ty::type_is_error(expr_ty);
3516 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3519 fcx.write_bot(node_id);
3522 fcx.write_error(node_id);
3525 fcx.write_nil(node_id)
3529 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3530 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3531 let blkty = fcx.node_ty(blk.id);
3532 if ty::type_is_error(blkty) {
3533 fcx.write_error(blk.id);
3535 else if ty::type_is_bot(blkty) {
3536 fcx.write_bot(blk.id);
3539 let nilty = ty::mk_nil();
3540 demand::suptype(fcx, blk.span, nilty, blkty);
3544 fn check_block_with_expected(fcx: &FnCtxt,
3546 expected: Expectation) {
3548 let mut fcx_ps = fcx.ps.borrow_mut();
3549 let fn_style_state = fcx_ps.recurse(blk);
3550 replace(&mut *fcx_ps, fn_style_state)
3553 fcx.with_region_lb(blk.id, || {
3554 let mut warned = false;
3555 let mut last_was_bot = false;
3556 let mut any_bot = false;
3557 let mut any_err = false;
3558 for s in blk.stmts.iter() {
3559 check_stmt(fcx, &**s);
3560 let s_id = ast_util::stmt_id(&**s);
3561 let s_ty = fcx.node_ty(s_id);
3562 if last_was_bot && !warned && match s.node {
3563 ast::StmtDecl(decl, _) => {
3565 ast::DeclLocal(_) => true,
3569 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3575 .add_lint(lint::builtin::UNREACHABLE_CODE,
3578 "unreachable statement".to_string());
3581 if ty::type_is_bot(s_ty) {
3582 last_was_bot = true;
3584 any_bot = any_bot || ty::type_is_bot(s_ty);
3585 any_err = any_err || ty::type_is_error(s_ty);
3588 None => if any_err {
3589 fcx.write_error(blk.id);
3592 fcx.write_bot(blk.id);
3595 fcx.write_nil(blk.id);
3598 if any_bot && !warned {
3602 .add_lint(lint::builtin::UNREACHABLE_CODE,
3605 "unreachable expression".to_string());
3607 check_expr_with_expectation(fcx, e, expected);
3608 let ety = fcx.expr_ty(e);
3609 fcx.write_ty(blk.id, ety);
3611 fcx.write_error(blk.id);
3614 fcx.write_bot(blk.id);
3620 *fcx.ps.borrow_mut() = prev;
3623 pub fn check_const(ccx: &CrateCtxt,
3627 let inh = blank_inherited_fields(ccx);
3628 let rty = ty::node_id_to_type(ccx.tcx, id);
3629 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3630 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3631 check_const_with_ty(&fcx, sp, e, declty);
3634 pub fn check_const_with_ty(fcx: &FnCtxt,
3638 // Gather locals in statics (because of block expressions).
3639 // This is technically unnecessary because locals in static items are forbidden,
3640 // but prevents type checking from blowing up before const checking can properly
3642 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3645 let cty = fcx.expr_ty(e);
3646 demand::suptype(fcx, e.span, declty, cty);
3647 regionck::regionck_expr(fcx, e);
3648 writeback::resolve_type_vars_in_expr(fcx, e);
3651 /// Checks whether a type can be represented in memory. In particular, it
3652 /// identifies types that contain themselves without indirection through a
3653 /// pointer, which would mean their size is unbounded. This is different from
3654 /// the question of whether a type can be instantiated. See the definition of
3655 /// `check_instantiable`.
3656 pub fn check_representable(tcx: &ty::ctxt,
3658 item_id: ast::NodeId,
3659 designation: &str) -> bool {
3660 let rty = ty::node_id_to_type(tcx, item_id);
3662 // Check that it is possible to represent this type. This call identifies
3663 // (1) types that contain themselves and (2) types that contain a different
3664 // recursive type. It is only necessary to throw an error on those that
3665 // contain themselves. For case 2, there must be an inner type that will be
3666 // caught by case 1.
3667 match ty::is_type_representable(tcx, sp, rty) {
3668 ty::SelfRecursive => {
3670 sp, format!("illegal recursive {} type; \
3671 wrap the inner value in a box to make it representable",
3672 designation).as_slice());
3675 ty::Representable | ty::ContainsRecursive => (),
3680 /// Checks whether a type can be created without an instance of itself.
3681 /// This is similar but different from the question of whether a type
3682 /// can be represented. For example, the following type:
3684 /// enum foo { None, Some(foo) }
3686 /// is instantiable but is not representable. Similarly, the type
3688 /// enum foo { Some(@foo) }
3690 /// is representable, but not instantiable.
3691 pub fn check_instantiable(tcx: &ty::ctxt,
3693 item_id: ast::NodeId)
3695 let item_ty = ty::node_id_to_type(tcx, item_id);
3696 if !ty::is_instantiable(tcx, item_ty) {
3699 format!("this type cannot be instantiated without an \
3700 instance of itself; consider using \
3702 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3709 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3710 let t = ty::node_id_to_type(tcx, id);
3711 if ty::type_needs_subst(t) {
3712 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3715 match ty::get(t).sty {
3716 ty::ty_struct(did, ref substs) => {
3717 let fields = ty::lookup_struct_fields(tcx, did);
3718 if fields.is_empty() {
3719 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3722 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3723 if !fields.iter().all(
3724 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3725 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3728 if !ty::type_is_machine(e) {
3729 tcx.sess.span_err(sp, "SIMD vector element type should be \
3738 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3739 vs: &[ast::P<ast::Variant>]) {
3740 for &v in vs.iter() {
3742 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3743 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3744 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3745 let len = arg_tys.len();
3749 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3750 // Allow the last field in an enum to be unsized.
3751 // We want to do this so that we can support smart pointers.
3752 // A struct value with an unsized final field is itself
3753 // unsized and we must track this in the type system.
3754 if !ty::type_is_sized(ccx.tcx, *t) {
3758 args.get(i).ty.span,
3759 format!("type `{}` is dynamically sized. \
3760 dynamically sized types may only \
3761 appear as the final type in a \
3763 ppaux::ty_to_str(ccx.tcx,
3768 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3774 pub fn check_enum_variants(ccx: &CrateCtxt,
3776 vs: &[ast::P<ast::Variant>],
3779 fn disr_in_range(ccx: &CrateCtxt,
3781 disr: ty::Disr) -> bool {
3782 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3784 ast::TyU8 => disr as u8 as Disr == disr,
3785 ast::TyU16 => disr as u16 as Disr == disr,
3786 ast::TyU32 => disr as u32 as Disr == disr,
3787 ast::TyU64 => disr as u64 as Disr == disr,
3788 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3791 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3793 ast::TyI8 => disr as i8 as Disr == disr,
3794 ast::TyI16 => disr as i16 as Disr == disr,
3795 ast::TyI32 => disr as i32 as Disr == disr,
3796 ast::TyI64 => disr as i64 as Disr == disr,
3797 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3801 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3802 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3806 fn do_check(ccx: &CrateCtxt,
3807 vs: &[ast::P<ast::Variant>],
3809 hint: attr::ReprAttr)
3810 -> Vec<Rc<ty::VariantInfo>> {
3812 let rty = ty::node_id_to_type(ccx.tcx, id);
3813 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3814 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3815 let mut prev_disr_val: Option<ty::Disr> = None;
3817 for &v in vs.iter() {
3819 // If the discriminant value is specified explicitly in the enum check whether the
3820 // initialization expression is valid, otherwise use the last value plus one.
3821 let mut current_disr_val = match prev_disr_val {
3822 Some(prev_disr_val) => prev_disr_val + 1,
3823 None => ty::INITIAL_DISCRIMINANT_VALUE
3826 match v.node.disr_expr {
3828 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3830 let inh = blank_inherited_fields(ccx);
3831 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3832 let declty = match hint {
3833 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3834 attr::ReprInt(_, attr::SignedInt(ity)) => {
3835 ty::mk_mach_int(ity)
3837 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3838 ty::mk_mach_uint(ity)
3841 check_const_with_ty(&fcx, e.span, &*e, declty);
3842 // check_expr (from check_const pass) doesn't guarantee
3843 // that the expression is in a form that eval_const_expr can
3844 // handle, so we may still get an internal compiler error
3846 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3847 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3848 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3850 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3856 format!("expected constant: {}",
3864 // Check for duplicate discriminant values
3865 if disr_vals.contains(¤t_disr_val) {
3866 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3868 // Check for unrepresentable discriminant values
3870 attr::ReprAny | attr::ReprExtern => (),
3871 attr::ReprInt(sp, ity) => {
3872 if !disr_in_range(ccx, ity, current_disr_val) {
3873 ccx.tcx.sess.span_err(v.span,
3874 "discriminant value outside specified type");
3875 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3879 disr_vals.push(current_disr_val);
3881 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3883 prev_disr_val = Some(current_disr_val);
3885 variants.push(variant_info);
3891 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3892 if hint != attr::ReprAny && vs.len() <= 1 {
3893 let msg = if vs.len() == 1 {
3894 "unsupported representation for univariant enum"
3896 "unsupported representation for zero-variant enum"
3898 ccx.tcx.sess.span_err(sp, msg)
3901 let variants = do_check(ccx, vs, id, hint);
3903 // cache so that ty::enum_variants won't repeat this work
3904 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3906 check_representable(ccx.tcx, sp, id, "enum");
3908 // Check that it is possible to instantiate this enum:
3910 // This *sounds* like the same that as representable, but it's
3911 // not. See def'n of `check_instantiable()` for details.
3912 check_instantiable(ccx.tcx, sp, id);
3915 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3916 lookup_def_ccx(fcx.ccx, sp, id)
3919 // Returns the type parameter count and the type for the given definition.
3920 pub fn polytype_for_def(fcx: &FnCtxt,
3925 def::DefArg(nid, _) | def::DefLocal(nid, _) |
3926 def::DefBinding(nid, _) => {
3927 let typ = fcx.local_ty(sp, nid);
3928 return no_params(typ);
3930 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
3931 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
3932 def::DefStruct(id) => {
3933 return ty::lookup_item_type(fcx.ccx.tcx, id);
3935 def::DefUpvar(_, inner, _, _) => {
3936 return polytype_for_def(fcx, sp, *inner);
3941 def::DefTyParam(..)=> {
3942 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3944 def::DefMod(..) | def::DefForeignMod(..) => {
3945 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3947 def::DefUse(..) => {
3948 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3950 def::DefRegion(..) => {
3951 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3953 def::DefTyParamBinder(..) => {
3954 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3956 def::DefLabel(..) => {
3957 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3959 def::DefSelfTy(..) => {
3960 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3962 def::DefMethod(..) => {
3963 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3968 // Instantiates the given path, which must refer to an item with the given
3969 // number of type parameters and type.
3970 pub fn instantiate_path(fcx: &FnCtxt,
3975 node_id: ast::NodeId) {
3976 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
3977 path.repr(fcx.tcx()),
3978 def.repr(fcx.tcx()),
3980 polytype.repr(fcx.tcx()));
3982 // We need to extract the type parameters supplied by the user in
3983 // the path `path`. Due to the current setup, this is a bit of a
3984 // tricky-process; the problem is that resolve only tells us the
3985 // end-point of the path resolution, and not the intermediate steps.
3986 // Luckily, we can (at least for now) deduce the intermediate steps
3987 // just from the end-point.
3989 // There are basically three cases to consider:
3991 // 1. Reference to a *type*, such as a struct or enum:
3993 // mod a { struct Foo<T> { ... } }
3995 // Because we don't allow types to be declared within one
3996 // another, a path that leads to a type will always look like
3997 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
3998 // that only the final segment can have type parameters, and
3999 // they are located in the TypeSpace.
4001 // *Note:* Generally speaking, references to types don't
4002 // actually pass through this function, but rather the
4003 // `ast_ty_to_ty` function in `astconv`. However, in the case
4004 // of struct patterns (and maybe literals) we do invoke
4005 // `instantiate_path` to get the general type of an instance of
4006 // a struct. (In these cases, there are actually no type
4007 // parameters permitted at present, but perhaps we will allow
4008 // them in the future.)
4010 // 1b. Reference to a enum variant or tuple-like struct:
4012 // struct foo<T>(...)
4013 // enum E<T> { foo(...) }
4015 // In these cases, the parameters are declared in the type
4018 // 2. Reference to a *fn item*:
4022 // In this case, the path will again always have the form
4023 // `a::b::foo::<T>` where only the final segment should have
4024 // type parameters. However, in this case, those parameters are
4025 // declared on a value, and hence are in the `FnSpace`.
4027 // 3. Reference to a *method*:
4029 // impl<A> SomeStruct<A> {
4033 // Here we can have a path like
4034 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4035 // may appear in two places. The penultimate segment,
4036 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4037 // final segment, `foo::<B>` contains parameters in fn space.
4039 // The first step then is to categorize the segments appropriately.
4041 assert!(path.segments.len() >= 1);
4042 let mut segment_spaces;
4044 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4045 def::DefSelfTy(..) |
4046 def::DefStruct(..) |
4047 def::DefVariant(..) |
4048 def::DefTyParamBinder(..) |
4051 def::DefPrimTy(..) |
4052 def::DefTyParam(..) => {
4053 // Everything but the final segment should have no
4054 // parameters at all.
4055 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4056 segment_spaces.push(Some(subst::TypeSpace));
4059 // Case 2. Reference to a top-level value.
4061 def::DefStatic(..) => {
4062 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4063 segment_spaces.push(Some(subst::FnSpace));
4066 // Case 3. Reference to a method.
4067 def::DefStaticMethod(..) => {
4068 assert!(path.segments.len() >= 2);
4069 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4070 segment_spaces.push(Some(subst::TypeSpace));
4071 segment_spaces.push(Some(subst::FnSpace));
4074 // Other cases. Various nonsense that really shouldn't show up
4075 // here. If they do, an error will have been reported
4076 // elsewhere. (I hope)
4078 def::DefForeignMod(..) |
4081 def::DefMethod(..) |
4082 def::DefBinding(..) |
4084 def::DefRegion(..) |
4086 def::DefUpvar(..) => {
4087 segment_spaces = Vec::from_elem(path.segments.len(), None);
4090 assert_eq!(segment_spaces.len(), path.segments.len());
4092 debug!("segment_spaces={}", segment_spaces);
4094 // Next, examine the definition, and determine how many type
4095 // parameters we expect from each space.
4096 let type_defs = &polytype.generics.types;
4097 let region_defs = &polytype.generics.regions;
4099 // Now that we have categorized what space the parameters for each
4100 // segment belong to, let's sort out the parameters that the user
4101 // provided (if any) into their appropriate spaces. We'll also report
4102 // errors if type parameters are provided in an inappropriate place.
4103 let mut substs = Substs::empty();
4104 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4107 report_error_if_segment_contains_type_parameters(fcx, segment);
4111 push_explicit_parameters_from_segment_to_substs(fcx,
4121 // Now we have to compare the types that the user *actually*
4122 // provided against the types that were *expected*. If the user
4123 // did not provide any types, then we want to substitute inference
4124 // variables. If the user provided some types, we may still need
4125 // to add defaults. If the user provided *too many* types, that's
4127 for &space in ParamSpace::all().iter() {
4128 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4129 assert_eq!(substs.types.get_vec(space).len(),
4130 type_defs.get_vec(space).len());
4132 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4133 assert_eq!(substs.regions().get_vec(space).len(),
4134 region_defs.get_vec(space).len());
4137 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4141 fn report_error_if_segment_contains_type_parameters(
4143 segment: &ast::PathSegment)
4145 for typ in segment.types.iter() {
4146 fcx.tcx().sess.span_err(
4148 "type parameters may not appear here");
4152 for lifetime in segment.lifetimes.iter() {
4153 fcx.tcx().sess.span_err(
4155 "lifetime parameters may not appear here");
4160 fn push_explicit_parameters_from_segment_to_substs(
4162 space: subst::ParamSpace,
4163 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4164 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4165 segment: &ast::PathSegment,
4166 substs: &mut Substs)
4169 * Finds the parameters that the user provided and adds them
4170 * to `substs`. If too many parameters are provided, then
4171 * reports an error and clears the output vector.
4173 * We clear the output vector because that will cause the
4174 * `adjust_XXX_parameters()` later to use inference
4175 * variables. This seems less likely to lead to derived
4178 * Note that we *do not* check for *too few* parameters here.
4179 * Due to the presence of defaults etc that is more
4180 * complicated. I wanted however to do the reporting of *too
4181 * many* parameters here because we can easily use the precise
4182 * span of the N+1'th parameter.
4186 let type_count = type_defs.get_vec(space).len();
4187 assert_eq!(substs.types.get_vec(space).len(), 0);
4188 for (i, &typ) in segment.types.iter().enumerate() {
4189 let t = fcx.to_ty(&*typ);
4191 substs.types.push(space, t);
4192 } else if i == type_count {
4193 fcx.tcx().sess.span_err(
4196 "too many type parameters provided: \
4197 expected at most {} parameter(s) \
4198 but found {} parameter(s)",
4200 segment.types.len()).as_slice());
4201 substs.types.get_mut_vec(space).truncate(0);
4207 let region_count = region_defs.get_vec(space).len();
4208 assert_eq!(substs.regions().get_vec(space).len(), 0);
4209 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4210 let r = ast_region_to_region(fcx.tcx(), lifetime);
4211 if i < region_count {
4212 substs.mut_regions().push(space, r);
4213 } else if i == region_count {
4214 fcx.tcx().sess.span_err(
4217 "too many lifetime parameters provided: \
4218 expected {} parameter(s) but found {} parameter(s)",
4220 segment.lifetimes.len()).as_slice());
4221 substs.mut_regions().get_mut_vec(space).truncate(0);
4227 fn adjust_type_parameters(
4231 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4232 substs: &mut Substs)
4234 let provided_len = substs.types.get_vec(space).len();
4235 let desired = defs.get_vec(space).as_slice();
4236 let required_len = desired.iter()
4237 .take_while(|d| d.default.is_none())
4240 debug!("adjust_type_parameters(space={}, \
4249 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4250 assert!(provided_len <= desired.len());
4252 // Nothing specified at all: supply inference variables for
4254 if provided_len == 0 {
4255 let provided = substs.types.get_mut_vec(space);
4256 *provided = fcx.infcx().next_ty_vars(desired.len());
4260 // Too few parameters specified: report an error and use Err
4262 if provided_len < required_len {
4264 if desired.len() != required_len { "at least " } else { "" };
4265 fcx.tcx().sess.span_err(
4267 format!("too few type parameters provided: \
4268 expected {}{} parameter(s) \
4269 but found {} parameter(s)",
4272 provided_len).as_slice());
4273 let provided = substs.types.get_mut_vec(space);
4274 *provided = Vec::from_elem(desired.len(), ty::mk_err());
4278 // Otherwise, add in any optional parameters that the user
4279 // omitted. The case of *too many* parameters is handled
4281 // push_explicit_parameters_from_segment_to_substs(). Note
4282 // that the *default* type are expressed in terms of all prior
4283 // parameters, so we have to substitute as we go with the
4284 // partial substitution that we have built up.
4285 for i in range(provided_len, desired.len()) {
4286 let default = desired[i].default.unwrap();
4287 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4288 substs.types.push(space, default);
4290 assert_eq!(substs.types.get_vec(space).len(), desired.len());
4292 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4295 fn adjust_region_parameters(
4299 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4300 substs: &mut Substs)
4302 let provided = substs.mut_regions().get_mut_vec(space);
4303 let desired = defs.get_vec(space);
4305 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4306 assert!(provided.len() <= desired.len());
4308 // If nothing was provided, just use inference variables.
4309 if provided.len() == 0 {
4310 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4314 // If just the right number were provided, everybody is happy.
4315 if provided.len() == desired.len() {
4319 // Otherwise, too few were provided. Report an error and then
4320 // use inference variables.
4321 fcx.tcx().sess.span_err(
4324 "too few lifetime parameters provided: \
4325 expected {} parameter(s) \
4326 but found {} parameter(s)",
4328 provided.len()).as_slice());
4330 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4334 // Resolves `typ` by a single level if `typ` is a type variable. If no
4335 // resolution is possible, then an error is reported.
4336 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4337 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4338 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4340 fcx.type_error_message(sp, |_actual| {
4341 "the type of this value must be known in this \
4342 context".to_string()
4344 demand::suptype(fcx, sp, ty::mk_err(), tp);
4350 // Returns the one-level-deep structure of the given type.
4351 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4353 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4356 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4357 let typ_s = structurally_resolved_type(fcx, sp, typ);
4358 return ty::type_is_integral(typ_s);
4361 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4362 let typ_s = structurally_resolved_type(fcx, sp, typ);
4363 return ty::type_is_uint(typ_s);
4366 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4369 mk_inner: || -> ty::mt)
4372 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4373 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4375 ast::ExprLit(..) => {
4376 // string literals and *empty slices* live in static memory
4377 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4379 ast::ExprVec(ref elements) if elements.len() == 0 => {
4380 // string literals and *empty slices* live in static memory
4381 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4383 ast::ExprRepeat(..) |
4384 ast::ExprVec(..) => {
4385 // vector literals are temporaries on the stack
4386 match fcx.tcx().region_maps.temporary_scope(e.id) {
4387 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4388 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4392 fcx.ccx.tcx.sess.span_bug(e.span,
4393 "vstore with unexpected \
4401 // Returns true if b contains a break that can exit from b
4402 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4403 // First: is there an unlabeled break immediately
4405 (loop_query(&*b, |e| {
4407 ast::ExprBreak(_) => true,
4411 // Second: is there a labeled break with label
4412 // <id> nested anywhere inside the loop?
4413 (block_query(b, |e| {
4415 ast::ExprBreak(Some(_)) => {
4416 match cx.def_map.borrow().find(&e.id) {
4417 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4425 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4427 tps: &OwnedSlice<ast::TyParam>,
4429 debug!("check_bounds_are_used(n_tps={}, ty={})",
4430 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4432 // make a vector of booleans initially false, set to true when used
4433 if tps.len() == 0u { return; }
4434 let mut tps_used = Vec::from_elem(tps.len(), false);
4436 ty::walk_ty(ty, |t| {
4437 match ty::get(t).sty {
4438 ty::ty_param(ParamTy {idx, ..}) => {
4439 debug!("Found use of ty param num {}", idx);
4440 *tps_used.get_mut(idx) = true;
4446 for (i, b) in tps_used.iter().enumerate() {
4448 ccx.tcx.sess.span_err(
4450 format!("type parameter `{}` is unused",
4451 token::get_ident(tps.get(i).ident)).as_slice());
4456 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4457 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4458 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4462 let name = token::get_ident(it.ident);
4463 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4464 let split : Vec<&str> = name.get().split('_').collect();
4465 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4467 //We only care about the operation here
4468 match *split.get(1) {
4469 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4473 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4475 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4478 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4479 "min" | "umax" | "umin" => {
4480 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4484 (0, Vec::new(), ty::mk_nil())
4487 tcx.sess.span_err(it.span,
4488 format!("unrecognized atomic operation \
4497 "abort" => (0, Vec::new(), ty::mk_bot()),
4498 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4500 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4501 "init" => (1u, Vec::new(), param(ccx, 0u)),
4502 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4503 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4504 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4505 "move_val_init" => {
4508 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4513 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4514 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4517 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4519 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4521 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4523 mutbl: ast::MutImmutable
4525 (1u, Vec::new(), td_ptr)
4528 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4532 ty::mk_struct(ccx.tcx, did,
4533 subst::Substs::empty())),
4535 tcx.sess.span_fatal(it.span, msg.as_slice());
4540 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4542 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4544 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4545 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4546 Ok((_, vot)) => vot,
4547 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4550 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4552 mutbl: ast::MutImmutable
4554 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4559 ty::mk_ptr(tcx, ty::mt {
4561 mutbl: ast::MutImmutable
4565 ty::mk_ptr(tcx, ty::mt {
4567 mutbl: ast::MutImmutable
4570 "copy_memory" | "copy_nonoverlapping_memory" |
4571 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4574 ty::mk_ptr(tcx, ty::mt {
4576 mutbl: ast::MutMutable
4578 ty::mk_ptr(tcx, ty::mt {
4580 mutbl: ast::MutImmutable
4586 "set_memory" | "volatile_set_memory" => {
4589 ty::mk_ptr(tcx, ty::mt {
4591 mutbl: ast::MutMutable
4598 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4599 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4602 vec!( ty::mk_f32(), ty::mk_i32() ),
4607 vec!( ty::mk_f64(), ty::mk_i32() ),
4610 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4611 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4612 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4613 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4616 vec!( ty::mk_f32(), ty::mk_f32() ),
4621 vec!( ty::mk_f64(), ty::mk_f64() ),
4624 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4625 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4626 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4627 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4628 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4629 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4630 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4631 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4632 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4633 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4636 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4641 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4644 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4645 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4646 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4647 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4648 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4649 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4650 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4651 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4652 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4653 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4654 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4655 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4656 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4657 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4658 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4659 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4660 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4661 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4662 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4663 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4664 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4665 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4666 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4667 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4668 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4669 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4670 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4671 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4672 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4673 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4674 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4677 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4679 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4681 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4682 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4683 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4685 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4686 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4687 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4689 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4690 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4691 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4693 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4694 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4695 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4697 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4698 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4699 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4701 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4702 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4703 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4705 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4706 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4707 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4709 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4710 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4711 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4714 tcx.sess.span_err(it.span,
4715 format!("unrecognized intrinsic function: `{}`",
4716 *other).as_slice());
4721 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4722 fn_style: ast::UnsafeFn,
4723 abi: abi::RustIntrinsic,
4731 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4732 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4733 if i_n_tps != n_tps {
4734 tcx.sess.span_err(it.span,
4735 format!("intrinsic has wrong number of type \
4736 parameters: found {}, expected {}",
4740 require_same_types(tcx,
4747 format!("intrinsic has wrong type: expected `{}`",
4748 ppaux::ty_to_str(ccx.tcx, fty))