1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function). Inference is used to supply types wherever they are
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
26 - main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `typeck::infer` module is in charge
35 of resolving those constraints.
37 - regionck: after main is complete, the regionck pass goes over all
38 types looking for regions and making sure that they did not escape
39 into places they are not in scope. This may also influence the
40 final assignments of the various region variables if there is some
43 - vtable: find and records the impls to use for each trait bound that
44 appears on a type parameter.
46 - writeback: writes the final types within a function body, replacing
47 type variables with their final inferred types. These final types
48 are written into the `tcx.node_types` table, which should *never* contain
49 any reference to a type variable.
53 While type checking a function, the intermediate types for the
54 expressions, blocks, and so forth contained within the function are
55 stored in `fcx.node_types` and `fcx.item_substs`. These types
56 may contain unresolved type variables. After type checking is
57 complete, the functions in the writeback module are used to take the
58 types from this table, resolve them, and then write them into their
59 permanent home in the type context `ccx.tcx`.
61 This means that during inferencing you should use `fcx.write_ty()`
62 and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
63 nodes within the function.
65 The types of top-level items, which never contain unbound type
66 variables, are stored directly into the `tcx` tables.
68 n.b.: A type variable is not the same thing as a type parameter. A
69 type variable is rather an "instance" of a type parameter: that is,
70 given a generic function `fn foo<T>(t: T)`: while checking the
71 function `foo`, the type `ty_param(0)` refers to the type `T`, which
72 is treated in abstract. When `foo()` is called, however, `T` will be
73 substituted for a fresh type variable `N`. This variable will
74 eventually be resolved to some concrete type (which might itself be
80 use middle::const_eval;
82 use middle::pat_util::pat_id_map;
85 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
86 use middle::ty::{FnSig, VariantInfo};
87 use middle::ty::{Polytype};
88 use middle::ty::{ParamTy, Disr, ExprTyProvider};
90 use middle::ty_fold::TypeFolder;
91 use middle::typeck::astconv::AstConv;
92 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
93 use middle::typeck::astconv;
94 use middle::typeck::check::_match::pat_ctxt;
95 use middle::typeck::check::method::{AutoderefReceiver};
96 use middle::typeck::check::method::{AutoderefReceiverFlag};
97 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
98 use middle::typeck::check::method::{DontAutoderefReceiver};
99 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
100 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
101 use middle::typeck::check::regionmanip::relate_free_regions;
102 use middle::typeck::check::vtable::VtableContext;
103 use middle::typeck::CrateCtxt;
104 use middle::typeck::infer::{resolve_type, force_tvar};
105 use middle::typeck::infer;
106 use middle::typeck::rscope::RegionScope;
107 use middle::typeck::{lookup_def_ccx};
108 use middle::typeck::no_params;
109 use middle::typeck::{require_same_types, vtable_map};
110 use middle::typeck::{MethodCall, MethodMap};
111 use middle::typeck::{TypeAndSubsts};
112 use middle::lang_items::TypeIdLangItem;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159 infcx: infer::InferCtxt<'a>,
160 locals: RefCell<NodeMap<ty::t>>,
161 param_env: ty::ParameterEnvironment,
164 node_types: RefCell<NodeMap<ty::t>>,
165 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167 method_map: MethodMap,
168 vtable_map: vtable_map,
169 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 /// When type-checking an expression, we propagate downward
173 /// whatever type hint we are able in the form of an `Expectation`.
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(ty::t),
181 /// This expression will be cast to the `ty::t`
182 ExpectCastableToType(ty::t),
186 pub struct FnStyleState {
187 pub def: ast::NodeId,
188 pub fn_style: ast::FnStyle,
193 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
194 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
197 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
198 match self.fn_style {
199 // If this unsafe, then if the outer function was already marked as
200 // unsafe we shouldn't attribute the unsafe'ness to the block. This
201 // way the block can be warned about instead of ignoring this
202 // extraneous block (functions are never warned about).
203 ast::UnsafeFn if self.from_fn => *self,
206 let (fn_style, def) = match blk.rules {
207 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
208 ast::DefaultBlock => (fn_style, self.def),
210 FnStyleState{ def: def,
218 /// Whether `check_binop` is part of an assignment or not.
219 /// Used to know whether we allow user overloads and to print
220 /// better messages on error.
221 #[deriving(PartialEq)]
222 enum IsBinopAssignment{
228 pub struct FnCtxt<'a> {
229 // This flag is set to true if, during the writeback phase, we encounter
230 // a type error in this function.
231 writeback_errors: Cell<bool>,
233 // Number of errors that had been reported when we started
234 // checking this function. On exit, if we find that *more* errors
235 // have been reported, we will skip regionck and other work that
236 // expects the types within the function to be consistent.
237 err_count_on_creation: uint,
240 ps: RefCell<FnStyleState>,
242 // Sometimes we generate region pointers where the precise region
243 // to use is not known. For example, an expression like `&x.f`
244 // where `x` is of type `@T`: in this case, we will be rooting
245 // `x` onto the stack frame, and we could choose to root it until
246 // the end of (almost) any enclosing block or expression. We
247 // want to pick the narrowest block that encompasses all uses.
249 // What we do in such cases is to generate a region variable with
250 // `region_lb` as a lower bound. The regionck pass then adds
251 // other constraints based on how the variable is used and region
252 // inference selects the ultimate value. Finally, borrowck is
253 // charged with guaranteeing that the value whose address was taken
254 // can actually be made to live as long as it needs to live.
255 region_lb: Cell<ast::NodeId>,
257 inh: &'a Inherited<'a>,
259 ccx: &'a CrateCtxt<'a>,
262 impl<'a> Inherited<'a> {
263 fn new(tcx: &'a ty::ctxt,
264 param_env: ty::ParameterEnvironment)
267 infcx: infer::new_infer_ctxt(tcx),
268 locals: RefCell::new(NodeMap::new()),
269 param_env: param_env,
270 node_types: RefCell::new(NodeMap::new()),
271 item_substs: RefCell::new(NodeMap::new()),
272 adjustments: RefCell::new(NodeMap::new()),
273 method_map: RefCell::new(FnvHashMap::new()),
274 vtable_map: RefCell::new(FnvHashMap::new()),
275 upvar_borrow_map: RefCell::new(HashMap::new()),
280 // Used by check_const and check_enum_variants
281 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
282 inh: &'a Inherited<'a>,
284 region_bnd: ast::NodeId)
287 writeback_errors: Cell::new(false),
288 err_count_on_creation: ccx.tcx.sess.err_count(),
290 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
291 region_lb: Cell::new(region_bnd),
297 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
298 // It's kind of a kludge to manufacture a fake function context
299 // and statement context, but we might as well do write the code only once
300 let param_env = ty::ParameterEnvironment {
301 free_substs: subst::Substs::empty(),
302 bounds: subst::VecPerParamSpace::empty()
304 Inherited::new(ccx.tcx, param_env)
307 impl<'a> ExprTyProvider for FnCtxt<'a> {
308 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
312 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
317 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
319 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
320 fn visit_item(&mut self, i: &ast::Item, _: ()) {
321 check_item(self.ccx, i);
322 visit::walk_item(self, i, ());
326 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
328 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329 fn visit_item(&mut self, i: &ast::Item, _: ()) {
330 check_item_sized(self.ccx, i);
331 visit::walk_item(self, i, ());
335 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336 let mut visit = CheckItemTypesVisitor { ccx: ccx };
337 visit::walk_crate(&mut visit, krate, ());
339 ccx.tcx.sess.abort_if_errors();
341 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342 visit::walk_crate(&mut visit, krate, ());
345 fn check_bare_fn(ccx: &CrateCtxt,
350 param_env: ty::ParameterEnvironment) {
351 // Compute the fty from point of view of inside fn
352 // (replace any type-scheme with a type)
353 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
355 match ty::get(fty).sty {
356 ty::ty_bare_fn(ref fn_ty) => {
357 let inh = Inherited::new(ccx.tcx, param_env);
358 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
359 decl, id, body, &inh);
361 vtable::resolve_in_block(&fcx, body);
362 regionck::regionck_fn(&fcx, body);
363 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
365 _ => ccx.tcx.sess.impossible_case(body.span,
366 "check_bare_fn: function type expected")
370 struct GatherLocalsVisitor<'a> {
374 impl<'a> GatherLocalsVisitor<'a> {
375 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
378 // infer the variable's type
379 let var_id = self.fcx.infcx().next_ty_var_id();
380 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
381 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
384 // take type that the user specified
385 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
391 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392 // Add explicitly-declared locals.
393 fn visit_local(&mut self, local: &ast::Local, _: ()) {
394 let o_ty = match local.ty.node {
395 ast::TyInfer => None,
396 _ => Some(self.fcx.to_ty(&*local.ty))
398 self.assign(local.id, o_ty);
399 debug!("Local variable {} is assigned type {}",
400 self.fcx.pat_to_str(&*local.pat),
401 self.fcx.infcx().ty_to_str(
402 self.fcx.inh.locals.borrow().get_copy(&local.id)));
403 visit::walk_local(self, local, ());
406 // Add pattern bindings.
407 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
409 ast::PatIdent(_, ref path, _)
410 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
411 self.assign(p.id, None);
412 debug!("Pattern binding {} is assigned to {}",
413 token::get_ident(path.segments.get(0).identifier),
414 self.fcx.infcx().ty_to_str(
415 self.fcx.inh.locals.borrow().get_copy(&p.id)));
419 visit::walk_pat(self, p, ());
423 fn visit_block(&mut self, b: &ast::Block, _: ()) {
424 // non-obvious: the `blk` variable maps to region lb, so
425 // we have to keep this up-to-date. This
426 // is... unfortunate. It'd be nice to not need this.
427 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
430 // Don't descend into fns and items
431 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
432 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
433 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
437 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
438 fn_style: ast::FnStyle,
443 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
446 * Helper used by check_bare_fn and check_expr_fn. Does the
447 * grungy work of checking a function body and returns the
448 * function context used for that purpose, since in the case of a
449 * fn item there is still a bit more to do.
452 * - inherited: other fields inherited from the enclosing fn (if any)
456 let err_count_on_creation = tcx.sess.err_count();
458 // First, we have to replace any bound regions in the fn type with free ones.
459 // The free region references will be bound the node_id of the body block.
460 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
461 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
464 relate_free_regions(tcx, &fn_sig);
466 let arg_tys = fn_sig.inputs.as_slice();
467 let ret_ty = fn_sig.output;
469 debug!("check_fn(arg_tys={}, ret_ty={})",
473 // Create the function context. This is either derived from scratch or,
474 // in the case of function expressions, based on the outer context.
476 writeback_errors: Cell::new(false),
477 err_count_on_creation: err_count_on_creation,
479 ps: RefCell::new(FnStyleState::function(fn_style, id)),
480 region_lb: Cell::new(body.id),
487 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
488 // Add formal parameters.
489 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
490 // Create type variables for each argument.
491 pat_util::pat_bindings(&tcx.def_map,
493 |_bm, pat_id, _sp, _path| {
494 visit.assign(pat_id, None);
497 // Check the pattern.
500 map: pat_id_map(&tcx.def_map, &*input.pat),
502 _match::check_pat(&pcx, &*input.pat, *arg_ty);
505 visit.visit_block(body, ());
508 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
510 // We unify the tail expr's type with the
511 // function result type, if there is a tail expr.
513 Some(ref tail_expr) => {
514 // Special case: we print a special error if there appears
515 // to be do-block/for-loop confusion
516 demand::suptype_with_fn(&fcx, tail_expr.span, false,
517 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
519 fcx.report_mismatched_return_types(sp, e, a, s);
525 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
526 fcx.write_ty(input.id, *arg);
532 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
533 assert!(field.id.krate == ast::LOCAL_CRATE);
534 let item = match tcx.map.find(struct_id.node) {
535 Some(ast_map::NodeItem(item)) => item,
536 None => fail!("node not in ast map: {}", struct_id.node),
537 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
541 ast::ItemStruct(struct_def, _) => {
542 match struct_def.fields.iter().find(|f| match f.node.kind {
543 ast::NamedField(ident, _) => ident.name == field.name,
549 .bug(format!("Could not find field {}",
550 token::get_name(field.name)).as_slice())
554 _ => tcx.sess.bug("Field found outside of a struct?"),
558 // Check struct fields are uniquely named wrt parents.
559 fn check_for_field_shadowing(tcx: &ty::ctxt,
561 let struct_fields = tcx.struct_fields.borrow();
562 let fields = struct_fields.get(&id);
564 let superstructs = tcx.superstructs.borrow();
565 let super_struct = superstructs.get(&id);
566 match *super_struct {
568 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
569 for f in fields.iter() {
570 match super_fields.iter().find(|sf| f.name == sf.name) {
571 Some(prev_field) => {
572 tcx.sess.span_err(span_for_field(tcx, f, id),
573 format!("field `{}` hides field declared in \
575 token::get_name(f.name)).as_slice());
576 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
577 "previously declared here");
587 fn check_fields_sized(tcx: &ty::ctxt,
588 struct_def: &ast::StructDef) {
589 let len = struct_def.fields.len();
593 for f in struct_def.fields.slice_to(len - 1).iter() {
594 let t = ty::node_id_to_type(tcx, f.node.id);
595 if !ty::type_is_sized(tcx, t) {
597 ast::NamedField(ident, _) => {
600 format!("type `{}` is dynamically sized. \
601 dynamically sized types may only \
602 appear as the type of the final \
604 token::get_ident(ident)).as_slice());
606 ast::UnnamedField(_) => {
607 tcx.sess.span_err(f.span, "dynamically sized type in field");
614 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
617 check_representable(tcx, span, id, "struct");
618 check_instantiable(tcx, span, id);
620 // Check there are no overlapping fields in super-structs
621 check_for_field_shadowing(tcx, local_def(id));
623 if ty::lookup_simd(tcx, local_def(id)) {
624 check_simd(tcx, span, id);
628 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
629 debug!("check_item(it.id={}, it.ident={})",
631 ty::item_path_str(ccx.tcx, local_def(it.id)));
632 let _indenter = indenter();
635 ast::ItemEnum(ref enum_definition, _) => {
636 check_enum_variants_sized(ccx,
637 enum_definition.variants.as_slice());
639 ast::ItemStruct(..) => {
640 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
646 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
647 debug!("check_item(it.id={}, it.ident={})",
649 ty::item_path_str(ccx.tcx, local_def(it.id)));
650 let _indenter = indenter();
653 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
654 ast::ItemEnum(ref enum_definition, _) => {
655 check_enum_variants(ccx,
657 enum_definition.variants.as_slice(),
660 ast::ItemFn(ref decl, _, _, _, ref body) => {
661 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
663 let param_env = ty::construct_parameter_environment(ccx.tcx,
667 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
669 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
670 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
672 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
674 check_method_body(ccx, &impl_pty.generics, &**m);
677 match *opt_trait_ref {
678 Some(ref ast_trait_ref) => {
680 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
681 check_impl_methods_against_trait(ccx,
686 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
692 ast::ItemTrait(_, _, _, ref trait_methods) => {
693 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
694 for trait_method in (*trait_methods).iter() {
695 match *trait_method {
697 // Nothing to do, since required methods don't have
701 check_method_body(ccx, &trait_def.generics, &*m);
706 ast::ItemStruct(..) => {
707 check_struct(ccx, it.id, it.span);
709 ast::ItemTy(ref t, ref generics) => {
710 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
711 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
713 ast::ItemForeignMod(ref m) => {
714 if m.abi == abi::RustIntrinsic {
715 for item in m.items.iter() {
716 check_intrinsic_type(ccx, &**item);
719 for item in m.items.iter() {
720 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
721 if !pty.generics.types.is_empty() {
722 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
726 ast::ForeignItemFn(ref fn_decl, _) => {
727 if fn_decl.variadic && m.abi != abi::C {
728 ccx.tcx.sess.span_err(
729 item.span, "variadic function must have C calling convention");
737 _ => {/* nothing to do */ }
741 fn check_method_body(ccx: &CrateCtxt,
742 item_generics: &ty::Generics,
743 method: &ast::Method) {
745 * Type checks a method body.
748 * - `item_generics`: generics defined on the impl/trait that contains
750 * - `self_bound`: bound for the `Self` type parameter, if any
751 * - `method`: the method definition
754 debug!("check_method_body(item_generics={}, method.id={})",
755 item_generics.repr(ccx.tcx),
757 let method_def_id = local_def(method.id);
758 let method_ty = ty::method(ccx.tcx, method_def_id);
759 let method_generics = &method_ty.generics;
761 let param_env = ty::construct_parameter_environment(ccx.tcx,
765 let fty = ty::node_id_to_type(ccx.tcx, method.id);
767 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
770 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
772 ast_trait_ref: &ast::TraitRef,
773 impl_trait_ref: &ty::TraitRef,
774 impl_methods: &[Gc<ast::Method>]) {
775 // Locate trait methods
777 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
779 // Check existing impl methods to see if they are both present in trait
780 // and compatible with trait signature
781 for impl_method in impl_methods.iter() {
782 let impl_method_def_id = local_def(impl_method.id);
783 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
785 // If this is an impl of a trait method, find the corresponding
786 // method definition in the trait.
787 let opt_trait_method_ty =
788 trait_methods.iter().
789 find(|tm| tm.ident.name == impl_method_ty.ident.name);
790 match opt_trait_method_ty {
791 Some(trait_method_ty) => {
792 compare_impl_method(ccx.tcx,
797 &impl_trait_ref.substs);
800 // This is span_bug as it should have already been caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_ident(impl_method_ty.ident),
806 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
811 // Check for missing methods from trait
812 let provided_methods = ty::provided_trait_methods(tcx,
813 impl_trait_ref.def_id);
814 let mut missing_methods = Vec::new();
815 for trait_method in trait_methods.iter() {
817 impl_methods.iter().any(
818 |m| m.ident.name == trait_method.ident.name);
820 provided_methods.iter().any(
821 |m| m.ident.name == trait_method.ident.name);
822 if !is_implemented && !is_provided {
823 missing_methods.push(
824 format!("`{}`", token::get_ident(trait_method.ident)));
828 if !missing_methods.is_empty() {
831 format!("not all trait methods implemented, missing: {}",
832 missing_methods.connect(", ")).as_slice());
837 * Checks that a method from an impl/class conforms to the signature of
838 * the same method as declared in the trait.
842 * - impl_generics: the generics declared on the impl itself (not the method!)
843 * - impl_m: type of the method we are checking
844 * - impl_m_span: span to use for reporting errors
845 * - impl_m_body_id: id of the method body
846 * - trait_m: the method in the trait
847 * - trait_to_impl_substs: the substitutions used on the type of the trait
849 fn compare_impl_method(tcx: &ty::ctxt,
852 impl_m_body_id: ast::NodeId,
853 trait_m: &ty::Method,
854 trait_to_impl_substs: &subst::Substs) {
855 debug!("compare_impl_method()");
856 let infcx = infer::new_infer_ctxt(tcx);
858 // Try to give more informative error messages about self typing
859 // mismatches. Note that any mismatch will also be detected
860 // below, where we construct a canonical function type that
861 // includes the self parameter as a normal parameter. It's just
862 // that the error messages you get out of this code are a bit more
863 // inscrutable, particularly for cases where one method has no
865 match (&trait_m.explicit_self, &impl_m.explicit_self) {
866 (&ast::SelfStatic, &ast::SelfStatic) => {}
867 (&ast::SelfStatic, _) => {
870 format!("method `{}` has a `{}` declaration in the impl, \
871 but not in the trait",
872 token::get_ident(trait_m.ident),
873 pprust::explicit_self_to_str(
874 impl_m.explicit_self)).as_slice());
877 (_, &ast::SelfStatic) => {
880 format!("method `{}` has a `{}` declaration in the trait, \
881 but not in the impl",
882 token::get_ident(trait_m.ident),
883 pprust::explicit_self_to_str(
884 trait_m.explicit_self)).as_slice());
888 // Let the type checker catch other errors below
892 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
893 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
894 if num_impl_m_type_params != num_trait_m_type_params {
897 format!("method `{}` has {} type parameter{} \
898 but its trait declaration has {} type parameter{}",
899 token::get_ident(trait_m.ident),
900 num_impl_m_type_params,
901 if num_impl_m_type_params == 1 {""} else {"s"},
902 num_trait_m_type_params,
903 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
907 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
910 format!("method `{}` has {} parameter{} \
911 but the declaration in trait `{}` has {}",
912 token::get_ident(trait_m.ident),
913 impl_m.fty.sig.inputs.len(),
914 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
915 ty::item_path_str(tcx, trait_m.def_id),
916 trait_m.fty.sig.inputs.len()).as_slice());
920 let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
921 .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
923 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
924 // Check that the impl does not require any builtin-bounds
925 // that the trait does not guarantee:
927 impl_param_def.bounds.builtin_bounds -
928 trait_param_def.bounds.builtin_bounds;
929 if !extra_bounds.is_empty() {
932 format!("in method `{}`, \
933 type parameter {} requires `{}`, \
934 which is not required by \
935 the corresponding type parameter \
936 in the trait declaration",
937 token::get_ident(trait_m.ident),
939 extra_bounds.user_string(tcx)).as_slice());
943 // FIXME(#2687)---we should be checking that the bounds of the
944 // trait imply the bounds of the subtype, but it appears we
945 // are...not checking this.
946 if impl_param_def.bounds.trait_bounds.len() !=
947 trait_param_def.bounds.trait_bounds.len()
949 let found = impl_param_def.bounds.trait_bounds.len();
950 let expected = trait_param_def.bounds.trait_bounds.len();
953 format!("in method `{}`, type parameter {} has {} trait \
954 bound{}, but the corresponding type parameter in \
955 the trait declaration has {} trait bound{}",
956 token::get_ident(trait_m.ident),
959 if found == 1 {""} else {"s"},
961 if expected == 1 {""} else {"s"}).as_slice());
966 // This code is best explained by example. Consider a trait:
969 // fn method<'a,M>(t: T, m: &'a M) -> Self;
974 // impl<'i, U> Trait<&'i U> for Foo {
975 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
978 // We wish to decide if those two method types are compatible.
980 // We start out with trait_to_impl_substs, that maps the trait type
981 // parameters to impl type parameters:
983 // trait_to_impl_substs = {T => &'i U, Self => Foo}
985 // We create a mapping `dummy_substs` that maps from the impl type
986 // parameters to fresh types and regions. For type parameters,
987 // this is the identity transform, but we could as well use any
988 // skolemized types. For regions, we convert from bound to free
989 // regions (Note: but only early-bound regions, i.e., those
990 // declared on the impl or used in type parameter bounds).
992 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
994 // Now we can apply skol_substs to the type of the impl method
995 // to yield a new function type in terms of our fresh, skolemized
998 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1000 // We now want to extract and substitute the type of the *trait*
1001 // method and compare it. To do so, we must create a compound
1002 // substitution by combining trait_to_impl_substs and
1003 // impl_to_skol_substs, and also adding a mapping for the method
1004 // type parameters. We extend the mapping to also include
1005 // the method parameters.
1007 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1009 // Applying this to the trait method type yields:
1011 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1013 // This type is also the same but the name of the bound region ('a
1014 // vs 'b). However, the normal subtyping rules on fn types handle
1015 // this kind of equivalency just fine.
1017 // Create mapping from impl to skolemized.
1019 impl_m.generics.types.map(
1020 |d| ty::mk_param_from_def(tcx, d));
1022 impl_m.generics.regions.map(
1023 |l| ty::free_region_from_def(impl_m_body_id, l));
1024 let impl_to_skol_substs =
1025 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1027 // Compute skolemized form of impl method ty.
1028 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1029 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1031 // Compute skolemized form of trait method ty.
1032 let trait_to_skol_substs =
1033 trait_to_impl_substs
1034 .subst(tcx, &impl_to_skol_substs)
1035 .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
1036 skol_regions.get_vec(subst::FnSpace).clone());
1037 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1038 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1040 // Check the impl method type IM is a subtype of the trait method
1041 // type TM. To see why this makes sense, think of a vtable. The
1042 // expected type of the function pointers in the vtable is the
1043 // type TM of the trait method. The actual type will be the type
1044 // IM of the impl method. Because we know that IM <: TM, that
1045 // means that anywhere a TM is expected, a IM will do instead. In
1046 // other words, anyone expecting to call a method with the type
1047 // from the trait, can safely call a method with the type from the
1049 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1050 impl_fty, trait_fty) {
1055 format!("method `{}` has an incompatible type for trait: {}",
1056 token::get_ident(trait_m.ident),
1057 ty::type_err_to_str(tcx, terr)).as_slice());
1058 ty::note_and_explain_type_err(tcx, terr);
1063 fn check_cast(fcx: &FnCtxt,
1068 // Find the type of `e`. Supply hints based on the type we are casting to,
1070 let t_1 = fcx.to_ty(t);
1071 let t_1 = structurally_resolved_type(fcx, span, t_1);
1073 if ty::type_is_scalar(t_1) {
1074 // Supply the type as a hint so as to influence integer
1075 // literals and other things that might care.
1076 check_expr_with_hint(fcx, e, t_1)
1081 let t_e = fcx.expr_ty(e);
1083 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
1084 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
1086 if ty::type_is_error(t_e) {
1087 fcx.write_error(id);
1090 if ty::type_is_bot(t_e) {
1095 if ty::type_is_trait(t_1) {
1096 // This will be looked up later on.
1097 fcx.write_ty(id, t_1);
1101 let t_1 = structurally_resolved_type(fcx, span, t_1);
1102 let t_e = structurally_resolved_type(fcx, span, t_e);
1104 if ty::type_is_nil(t_e) {
1105 fcx.type_error_message(span, |actual| {
1106 format!("cast from nil: `{}` as `{}`",
1108 fcx.infcx().ty_to_str(t_1))
1110 } else if ty::type_is_nil(t_1) {
1111 fcx.type_error_message(span, |actual| {
1112 format!("cast to nil: `{}` as `{}`",
1114 fcx.infcx().ty_to_str(t_1))
1118 let t_1_is_scalar = ty::type_is_scalar(t_1);
1119 let t_1_is_char = ty::type_is_char(t_1);
1120 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1121 let t_1_is_float = ty::type_is_floating_point(t_1);
1123 // casts to scalars other than `char` and `bare fn` are trivial
1124 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1125 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1127 fcx.type_error_message(span, |actual| {
1128 format!("illegal cast; cast through an \
1129 integer first: `{}` as `{}`",
1131 fcx.infcx().ty_to_str(t_1))
1134 // casts from C-like enums are allowed
1135 } else if t_1_is_char {
1136 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1137 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1138 fcx.type_error_message(span, |actual| {
1139 format!("only `u8` can be cast as \
1140 `char`, not `{}`", actual)
1143 } else if ty::get(t_1).sty == ty::ty_bool {
1147 "cannot cast as `bool`, compare with zero instead");
1148 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1149 fn is_vec(t: ty::t) -> bool {
1150 match ty::get(t).sty {
1151 ty::ty_vec(..) => true,
1152 ty::ty_ptr(ty::mt{ty: t, ..}) |
1153 ty::ty_rptr(_, ty::mt{ty: t, ..}) |
1156 match ty::get(t).sty {
1157 ty::ty_vec(_, None) => true,
1164 fn types_compatible(fcx: &FnCtxt, sp: Span,
1165 t1: ty::t, t2: ty::t) -> bool {
1167 // If the type being casted from is not a vector, this special
1168 // case does not apply.
1171 if ty::type_needs_infer(t2) {
1172 // This prevents this special case from going off when casting
1173 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1178 let el = ty::sequence_element_type(fcx.tcx(), t1);
1179 infer::mk_eqty(fcx.infcx(),
1186 // Due to the limitations of LLVM global constants,
1187 // region pointers end up pointing at copies of
1188 // vector elements instead of the original values.
1189 // To allow unsafe pointers to work correctly, we
1190 // need to special-case obtaining an unsafe pointer
1191 // from a region pointer to a vector.
1193 /* this cast is only allowed from &[T] to *T or
1195 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1196 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1197 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1198 if types_compatible(fcx, e.span, mt1, mt2) => {
1199 /* this case is allowed */
1202 demand::coerce(fcx, e.span, t_1, &*e);
1205 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1207 If more type combinations should be supported than are
1208 supported here, then file an enhancement issue and
1209 record the issue number in this comment.
1211 fcx.type_error_message(span, |actual| {
1212 format!("non-scalar cast: `{}` as `{}`",
1214 fcx.infcx().ty_to_str(t_1))
1218 fcx.write_ty(id, t_1);
1221 impl<'a> AstConv for FnCtxt<'a> {
1222 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1224 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1225 ty::lookup_item_type(self.tcx(), id)
1228 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1229 ty::lookup_trait_def(self.tcx(), id)
1232 fn ty_infer(&self, _span: Span) -> ty::t {
1233 self.infcx().next_ty_var()
1237 impl<'a> FnCtxt<'a> {
1238 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1242 pub fn err_count_since_creation(&self) -> uint {
1243 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1246 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1248 infcx: self.infcx(),
1249 param_env: &self.inh.param_env
1254 impl<'a> RegionScope for infer::InferCtxt<'a> {
1255 fn anon_regions(&self, span: Span, count: uint)
1256 -> Result<Vec<ty::Region> , ()> {
1257 Ok(Vec::from_fn(count, |_| {
1258 self.next_region_var(infer::MiscVariable(span))
1263 impl<'a> FnCtxt<'a> {
1264 pub fn tag(&self) -> String {
1265 format!("{}", self as *const FnCtxt)
1268 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1269 match self.inh.locals.borrow().find(&nid) {
1272 self.tcx().sess.span_bug(
1274 format!("no type for local variable {:?}",
1281 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1282 debug!("write_ty({}, {}) in fcx {}",
1283 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1284 self.inh.node_types.borrow_mut().insert(node_id, ty);
1287 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1288 if !substs.substs.is_noop() {
1289 debug!("write_substs({}, {}) in fcx {}",
1291 substs.repr(self.tcx()),
1294 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1298 pub fn write_ty_substs(&self,
1299 node_id: ast::NodeId,
1301 substs: ty::ItemSubsts) {
1302 let ty = ty.subst(self.tcx(), &substs.substs);
1303 self.write_ty(node_id, ty);
1304 self.write_substs(node_id, substs);
1307 pub fn write_autoderef_adjustment(&self,
1308 node_id: ast::NodeId,
1310 if derefs == 0 { return; }
1311 self.write_adjustment(
1313 ty::AutoDerefRef(ty::AutoDerefRef {
1319 pub fn write_adjustment(&self,
1320 node_id: ast::NodeId,
1321 adj: ty::AutoAdjustment) {
1322 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1323 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1326 pub fn write_nil(&self, node_id: ast::NodeId) {
1327 self.write_ty(node_id, ty::mk_nil());
1329 pub fn write_bot(&self, node_id: ast::NodeId) {
1330 self.write_ty(node_id, ty::mk_bot());
1332 pub fn write_error(&self, node_id: ast::NodeId) {
1333 self.write_ty(node_id, ty::mk_err());
1336 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1337 ast_ty_to_ty(self, self.infcx(), ast_t)
1340 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1341 pat.repr(self.tcx())
1344 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1345 match self.inh.node_types.borrow().find(&ex.id) {
1348 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1349 self.tag()).as_slice());
1354 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1355 match self.inh.node_types.borrow().find(&id) {
1358 self.tcx().sess.bug(
1359 format!("no type for node {}: {} in fcx {}",
1360 id, self.tcx().map.node_to_str(id),
1361 self.tag()).as_slice());
1366 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1367 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1368 Some(method) => method.substs.clone(),
1370 self.tcx().sess.bug(
1371 format!("no method entry for node {}: {} in fcx {}",
1372 id, self.tcx().map.node_to_str(id),
1373 self.tag()).as_slice());
1378 pub fn opt_node_ty_substs(&self,
1380 f: |&ty::ItemSubsts|) {
1381 match self.inh.item_substs.borrow().find(&id) {
1387 pub fn mk_subty(&self,
1388 a_is_expected: bool,
1389 origin: infer::TypeOrigin,
1392 -> Result<(), ty::type_err> {
1393 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1396 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1397 -> Result<(), ty::type_err> {
1398 infer::can_mk_subty(self.infcx(), sub, sup)
1401 pub fn mk_assignty(&self,
1405 -> Result<(), ty::type_err> {
1406 match infer::mk_coercety(self.infcx(),
1408 infer::ExprAssignable(expr.span),
1412 Err(ref e) => Err((*e)),
1413 Ok(Some(adjustment)) => {
1414 self.write_adjustment(expr.id, adjustment);
1420 pub fn mk_eqty(&self,
1421 a_is_expected: bool,
1422 origin: infer::TypeOrigin,
1425 -> Result<(), ty::type_err> {
1426 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1429 pub fn mk_subr(&self,
1430 a_is_expected: bool,
1431 origin: infer::SubregionOrigin,
1434 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1437 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1438 let old_region_lb = self.region_lb.get();
1439 self.region_lb.set(lb);
1441 self.region_lb.set(old_region_lb);
1445 pub fn type_error_message(&self,
1447 mk_msg: |String| -> String,
1449 err: Option<&ty::type_err>) {
1450 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1453 pub fn report_mismatched_return_types(&self,
1457 err: &ty::type_err) {
1459 if ty::type_is_error(e) || ty::type_is_error(a) {
1462 self.infcx().report_mismatched_types(sp, e, a, err)
1465 pub fn report_mismatched_types(&self,
1469 err: &ty::type_err) {
1470 self.infcx().report_mismatched_types(sp, e, a, err)
1474 pub enum LvaluePreference {
1479 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1480 expr_id: Option<ast::NodeId>,
1481 mut lvalue_pref: LvaluePreference,
1482 should_stop: |ty::t, uint| -> Option<T>)
1483 -> (ty::t, uint, Option<T>) {
1485 * Executes an autoderef loop for the type `t`. At each step, invokes
1486 * `should_stop` to decide whether to terminate the loop. Returns
1487 * the final type and number of derefs that it performed.
1489 * Note: this method does not modify the adjustments table. The caller is
1490 * responsible for inserting an AutoAdjustment record into the `fcx`
1491 * using one of the suitable methods.
1494 let mut t = base_ty;
1495 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1496 let resolved_t = structurally_resolved_type(fcx, sp, t);
1498 match should_stop(resolved_t, autoderefs) {
1499 Some(x) => return (resolved_t, autoderefs, Some(x)),
1503 // Otherwise, deref if type is derefable:
1504 let mt = match ty::deref(resolved_t, false) {
1505 Some(mt) => Some(mt),
1507 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1508 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1514 if mt.mutbl == ast::MutImmutable {
1515 lvalue_pref = NoPreference;
1518 None => return (resolved_t, autoderefs, None)
1522 // We've reached the recursion limit, error gracefully.
1523 fcx.tcx().sess.span_err(sp,
1524 format!("reached the recursion limit while auto-dereferencing {}",
1525 base_ty.repr(fcx.tcx())).as_slice());
1526 (ty::mk_err(), 0, None)
1529 /// Attempts to resolve a call expression as an overloaded call.
1530 fn try_overloaded_call(fcx: &FnCtxt,
1531 call_expression: &ast::Expr,
1532 callee: Gc<ast::Expr>,
1534 args: &[Gc<ast::Expr>])
1536 // Try `FnOnce`, then `FnMut`, then `Fn`.
1537 for &(maybe_function_trait, method_name) in [
1538 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1539 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1540 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1542 let function_trait = match maybe_function_trait {
1544 Some(function_trait) => function_trait,
1546 let method_callee = match method::lookup_in_trait(
1548 call_expression.span,
1554 DontAutoderefReceiver,
1555 IgnoreStaticMethods) {
1557 Some(method_callee) => method_callee,
1559 let method_call = MethodCall::expr(call_expression.id);
1560 let output_type = check_method_argument_types(fcx,
1561 call_expression.span,
1567 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1568 write_call(fcx, call_expression, output_type);
1570 if !fcx.tcx().sess.features.overloaded_calls.get() {
1571 fcx.tcx().sess.span_err(call_expression.span,
1572 "overloaded calls are experimental");
1573 fcx.tcx().sess.span_note(call_expression.span,
1574 "add `#[feature(overloaded_calls)]` to \
1575 the crate attributes to enable");
1584 fn try_overloaded_deref(fcx: &FnCtxt,
1586 method_call: Option<MethodCall>,
1587 base_expr: Option<&ast::Expr>,
1589 lvalue_pref: LvaluePreference)
1591 // Try DerefMut first, if preferred.
1592 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1593 (PreferMutLvalue, Some(trait_did)) => {
1594 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1595 token::intern("deref_mut"), trait_did,
1596 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1601 // Otherwise, fall back to Deref.
1602 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1603 (None, Some(trait_did)) => {
1604 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1605 token::intern("deref"), trait_did,
1606 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1608 (method, _) => method
1613 let ref_ty = ty::ty_fn_ret(method.ty);
1615 Some(method_call) => {
1616 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1620 ty::deref(ref_ty, true)
1626 fn check_method_argument_types(fcx: &FnCtxt,
1628 method_fn_ty: ty::t,
1629 callee_expr: &ast::Expr,
1630 args: &[Gc<ast::Expr>],
1631 deref_args: DerefArgs,
1632 tuple_arguments: TupleArgumentsFlag)
1634 // HACK(eddyb) ignore provided self (it has special typeck rules).
1635 let args = if tuple_arguments == DontTupleArguments {
1640 if ty::type_is_error(method_fn_ty) {
1641 let err_inputs = err_args(args.len());
1642 check_argument_types(fcx,
1644 err_inputs.as_slice(),
1652 match ty::get(method_fn_ty).sty {
1653 ty::ty_bare_fn(ref fty) => {
1654 // HACK(eddyb) ignore self in the definition (see above).
1655 check_argument_types(fcx,
1657 fty.sig.inputs.slice_from(1),
1666 fcx.tcx().sess.span_bug(callee_expr.span,
1667 "method without bare fn type");
1673 fn check_argument_types(fcx: &FnCtxt,
1675 fn_inputs: &[ty::t],
1676 callee_expr: &ast::Expr,
1677 args: &[Gc<ast::Expr>],
1678 deref_args: DerefArgs,
1680 tuple_arguments: TupleArgumentsFlag) {
1683 * Generic function that factors out common logic from
1684 * function calls, method calls and overloaded operators.
1687 let tcx = fcx.ccx.tcx;
1689 // Grab the argument types, supplying fresh type variables
1690 // if the wrong number of arguments were supplied
1691 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1697 let expected_arg_count = fn_inputs.len();
1698 let formal_tys = if tuple_arguments == TupleArguments {
1699 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1700 match ty::get(tuple_type).sty {
1701 ty::ty_tup(ref arg_types) => {
1702 if arg_types.len() != args.len() {
1704 "this function takes {} parameter{} \
1705 but {} parameter{} supplied",
1707 if arg_types.len() == 1 {""} else {"s"},
1709 if args.len() == 1 {" was"} else {"s were"});
1710 tcx.sess.span_err(sp, msg.as_slice());
1711 err_args(args.len())
1713 (*arg_types).clone()
1717 if args.len() != 0 {
1719 "this function takes 0 parameters \
1720 but {} parameter{} supplied",
1722 if args.len() == 1 {" was"} else {"s were"});
1723 tcx.sess.span_err(sp, msg.as_slice());
1730 "cannot use call notation; the first type \
1731 parameter for the function trait is neither a \
1733 err_args(supplied_arg_count)
1736 } else if expected_arg_count == supplied_arg_count {
1737 fn_inputs.iter().map(|a| *a).collect()
1738 } else if variadic {
1739 if supplied_arg_count >= expected_arg_count {
1740 fn_inputs.iter().map(|a| *a).collect()
1743 "this function takes at least {} parameter{} \
1744 but {} parameter{} supplied",
1746 if expected_arg_count == 1 {""} else {"s"},
1748 if supplied_arg_count == 1 {" was"} else {"s were"});
1750 tcx.sess.span_err(sp, msg.as_slice());
1752 err_args(supplied_arg_count)
1756 "this function takes {} parameter{} \
1757 but {} parameter{} supplied",
1759 if expected_arg_count == 1 {""} else {"s"},
1761 if supplied_arg_count == 1 {" was"} else {"s were"});
1763 tcx.sess.span_err(sp, msg.as_slice());
1765 err_args(supplied_arg_count)
1768 debug!("check_argument_types: formal_tys={:?}",
1769 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1771 // Check the arguments.
1772 // We do this in a pretty awful way: first we typecheck any arguments
1773 // that are not anonymous functions, then we typecheck the anonymous
1774 // functions. This is so that we have more information about the types
1775 // of arguments when we typecheck the functions. This isn't really the
1776 // right way to do this.
1777 let xs = [false, true];
1778 for check_blocks in xs.iter() {
1779 let check_blocks = *check_blocks;
1780 debug!("check_blocks={}", check_blocks);
1782 // More awful hacks: before we check the blocks, try to do
1783 // an "opportunistic" vtable resolution of any trait
1784 // bounds on the call.
1786 vtable::early_resolve_expr(callee_expr, fcx, true);
1789 // For variadic functions, we don't have a declared type for all of
1790 // the arguments hence we only do our usual type checking with
1791 // the arguments who's types we do know.
1792 let t = if variadic {
1794 } else if tuple_arguments == TupleArguments {
1799 for (i, arg) in args.iter().take(t).enumerate() {
1800 let is_block = match arg.node {
1801 ast::ExprFnBlock(..) |
1802 ast::ExprProc(..) => true,
1806 if is_block == check_blocks {
1807 debug!("checking the argument");
1808 let mut formal_ty = *formal_tys.get(i);
1812 match ty::get(formal_ty).sty {
1813 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1816 // So we hit this case when one implements the
1817 // operator traits but leaves an argument as
1818 // just T instead of &T. We'll catch it in the
1819 // mismatch impl/trait method phase no need to
1822 formal_ty = ty::mk_err();
1829 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1835 // We also need to make sure we at least write the ty of the other
1836 // arguments which we skipped above.
1838 for arg in args.iter().skip(expected_arg_count) {
1839 check_expr(fcx, &**arg);
1841 // There are a few types which get autopromoted when passed via varargs
1842 // in C but we just error out instead and require explicit casts.
1843 let arg_ty = structurally_resolved_type(fcx, arg.span,
1844 fcx.expr_ty(&**arg));
1845 match ty::get(arg_ty).sty {
1846 ty::ty_float(ast::TyF32) => {
1847 fcx.type_error_message(arg.span,
1849 format!("can't pass an {} to variadic \
1850 function, cast to c_double", t)
1853 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1854 fcx.type_error_message(arg.span, |t| {
1855 format!("can't pass {} to variadic \
1856 function, cast to c_int",
1860 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1861 fcx.type_error_message(arg.span, |t| {
1862 format!("can't pass {} to variadic \
1863 function, cast to c_uint",
1873 fn err_args(len: uint) -> Vec<ty::t> {
1874 Vec::from_fn(len, |_| ty::mk_err())
1877 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1878 fcx.write_ty(call_expr.id, output);
1881 // AST fragment checking
1882 fn check_lit(fcx: &FnCtxt,
1884 expected: Expectation)
1887 let tcx = fcx.ccx.tcx;
1890 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1891 ast::LitBinary(..) => {
1892 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1894 ast::LitByte(_) => ty::mk_u8(),
1895 ast::LitChar(_) => ty::mk_char(),
1896 ast::LitInt(_, t) => ty::mk_mach_int(t),
1897 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1898 ast::LitIntUnsuffixed(_) => {
1899 let opt_ty = expected.map_to_option(fcx, |sty| {
1901 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
1902 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
1903 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
1904 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
1905 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
1909 opt_ty.unwrap_or_else(
1910 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
1912 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1913 ast::LitFloatUnsuffixed(_) => {
1914 let opt_ty = expected.map_to_option(fcx, |sty| {
1916 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
1920 opt_ty.unwrap_or_else(
1921 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
1923 ast::LitNil => ty::mk_nil(),
1924 ast::LitBool(_) => ty::mk_bool()
1928 pub fn valid_range_bounds(ccx: &CrateCtxt,
1932 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1933 Some(val) => Some(val <= 0),
1938 pub fn check_expr_has_type(fcx: &FnCtxt,
1941 check_expr_with_unifier(
1942 fcx, expr, ExpectHasType(expected), NoPreference,
1943 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
1946 fn check_expr_coercable_to_type(fcx: &FnCtxt,
1949 check_expr_with_unifier(
1950 fcx, expr, ExpectHasType(expected), NoPreference,
1951 || demand::coerce(fcx, expr.span, expected, expr));
1954 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1955 check_expr_with_unifier(
1956 fcx, expr, ExpectHasType(expected), NoPreference,
1960 fn check_expr_with_expectation(fcx: &FnCtxt,
1962 expected: Expectation) {
1963 check_expr_with_unifier(
1964 fcx, expr, expected, NoPreference,
1968 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
1970 expected: Expectation,
1971 lvalue_pref: LvaluePreference)
1973 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1976 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1977 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
1980 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1981 lvalue_pref: LvaluePreference) {
1982 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
1986 // determine the `self` type, using fresh variables for all variables
1987 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1988 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1990 pub fn impl_self_ty(vcx: &VtableContext,
1991 span: Span, // (potential) receiver for this impl
1994 let tcx = vcx.tcx();
1996 let ity = ty::lookup_item_type(tcx, did);
1997 let (n_tps, rps, raw_ty) =
1998 (ity.generics.types.len(subst::TypeSpace),
1999 ity.generics.regions.get_vec(subst::TypeSpace),
2002 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2003 let tps = vcx.infcx.next_ty_vars(n_tps);
2004 let substs = subst::Substs::new_type(tps, rps);
2005 let substd_ty = raw_ty.subst(tcx, &substs);
2007 TypeAndSubsts { substs: substs, ty: substd_ty }
2010 // Only for fields! Returns <none> for methods>
2011 // Indifferent to privacy flags
2012 pub fn lookup_field_ty(tcx: &ty::ctxt,
2013 class_id: ast::DefId,
2014 items: &[ty::field_ty],
2015 fieldname: ast::Name,
2016 substs: &subst::Substs) -> Option<ty::t> {
2018 let o_field = items.iter().find(|f| f.name == fieldname);
2019 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2022 // Controls whether the arguments are automatically referenced. This is useful
2023 // for overloaded binary and unary operators.
2024 pub enum DerefArgs {
2029 /// Controls whether the arguments are tupled. This is used for the call
2032 /// Tupling means that all call-side arguments are packed into a tuple and
2033 /// passed as a single parameter. For example, if tupling is enabled, this
2036 /// fn f(x: (int, int))
2038 /// Can be called as:
2045 #[deriving(Clone, Eq, PartialEq)]
2046 enum TupleArgumentsFlag {
2052 /// If an expression has any sub-expressions that result in a type error,
2053 /// inspecting that expression's type with `ty::type_is_error` will return
2054 /// true. Likewise, if an expression is known to diverge, inspecting its
2055 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2056 /// strict, _|_ can appear in the type of an expression that does not,
2057 /// itself, diverge: for example, fn() -> _|_.)
2058 /// Note that inspecting a type's structure *directly* may expose the fact
2059 /// that there are actually multiple representations for both `ty_err` and
2060 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2061 fn check_expr_with_unifier(fcx: &FnCtxt,
2063 expected: Expectation,
2064 lvalue_pref: LvaluePreference,
2067 debug!(">> typechecking");
2069 // A generic function for doing all of the checking for call expressions
2070 fn check_call(fcx: &FnCtxt,
2071 call_expr: &ast::Expr,
2073 args: &[Gc<ast::Expr>]) {
2074 // Store the type of `f` as the type of the callee
2075 let fn_ty = fcx.expr_ty(f);
2077 // Extract the function signature from `in_fty`.
2078 let fn_sty = structure_of(fcx, f.span, fn_ty);
2080 // This is the "default" function signature, used in case of error.
2081 // In that case, we check each argument against "error" in order to
2082 // set up all the node type bindings.
2083 let error_fn_sig = FnSig {
2084 binder_id: ast::CRATE_NODE_ID,
2085 inputs: err_args(args.len()),
2086 output: ty::mk_err(),
2090 let fn_sig = match *fn_sty {
2091 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2092 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2094 fcx.type_error_message(call_expr.span, |actual| {
2095 format!("expected function but found `{}`", actual)
2101 // Replace any bound regions that appear in the function
2102 // signature with region variables
2103 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2104 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2107 // Call the generic checker.
2108 check_argument_types(fcx,
2110 fn_sig.inputs.as_slice(),
2115 DontTupleArguments);
2117 write_call(fcx, call_expr, fn_sig.output);
2120 // Checks a method call.
2121 fn check_method_call(fcx: &FnCtxt,
2123 method_name: ast::SpannedIdent,
2124 args: &[Gc<ast::Expr>],
2125 tps: &[ast::P<ast::Ty>]) {
2126 let rcvr = args[0].clone();
2127 // We can't know if we need &mut self before we look up the method,
2128 // so treat the receiver as mutable just in case - only explicit
2129 // overloaded dereferences care about the distinction.
2130 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2132 // no need to check for bot/err -- callee does that
2133 let expr_t = structurally_resolved_type(fcx,
2135 fcx.expr_ty(&*rcvr));
2137 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2138 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2139 method_name.node.name,
2140 expr_t, tps.as_slice(),
2142 CheckTraitsAndInherentMethods,
2143 AutoderefReceiver, IgnoreStaticMethods) {
2145 let method_ty = method.ty;
2146 let method_call = MethodCall::expr(expr.id);
2147 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2151 debug!("(checking method call) failing expr is {}", expr.id);
2153 fcx.type_error_message(method_name.span,
2155 format!("type `{}` does not implement any \
2156 method in scope named `{}`",
2158 token::get_ident(method_name.node))
2163 // Add error type for the result
2164 fcx.write_error(expr.id);
2166 // Check for potential static matches (missing self parameters)
2170 method_name.node.name,
2174 CheckTraitsAndInherentMethods,
2175 DontAutoderefReceiver,
2176 ReportStaticMethods);
2182 // Call the generic checker.
2183 let ret_ty = check_method_argument_types(fcx,
2189 DontTupleArguments);
2191 write_call(fcx, expr, ret_ty);
2194 // A generic function for checking the then and else in an if
2196 fn check_then_else(fcx: &FnCtxt,
2197 cond_expr: &ast::Expr,
2198 then_blk: &ast::Block,
2199 opt_else_expr: Option<Gc<ast::Expr>>,
2202 expected: Expectation) {
2203 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2205 let branches_ty = match opt_else_expr {
2206 Some(ref else_expr) => {
2207 // Disregard "castable to" expectations because they
2208 // can lead us astray. Consider for example `if cond
2209 // {22} else {c} as u8` -- if we propagate the
2210 // "castable to u8" constraint to 22, it will pick the
2211 // type 22u8, which is overly constrained (c might not
2212 // be a u8). In effect, the problem is that the
2213 // "castable to" expectation is not the tightest thing
2214 // we can say, so we want to drop it in this case.
2215 // The tightest thing we can say is "must unify with
2216 // else branch". Note that in the case of a "has type"
2217 // constraint, this limitation does not hold.
2218 let expected = expected.only_has_type();
2220 check_block_with_expected(fcx, then_blk, expected);
2221 let then_ty = fcx.node_ty(then_blk.id);
2222 check_expr_with_expectation(fcx, &**else_expr, expected);
2223 let else_ty = fcx.expr_ty(&**else_expr);
2224 infer::common_supertype(fcx.infcx(),
2225 infer::IfExpression(sp),
2231 check_block_no_value(fcx, then_blk);
2236 let cond_ty = fcx.expr_ty(cond_expr);
2237 let if_ty = if ty::type_is_error(cond_ty) {
2239 } else if ty::type_is_bot(cond_ty) {
2245 fcx.write_ty(id, if_ty);
2248 fn lookup_op_method(fcx: &FnCtxt,
2252 trait_did: Option<ast::DefId>,
2253 args: &[Gc<ast::Expr>],
2254 autoderef_receiver: AutoderefReceiverFlag,
2255 unbound_method: ||) -> ty::t {
2256 let method = match trait_did {
2257 Some(trait_did) => {
2258 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2259 trait_did, self_t, [], autoderef_receiver,
2260 IgnoreStaticMethods)
2266 let method_ty = method.ty;
2267 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2268 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2269 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2270 check_method_argument_types(fcx,
2280 // Check the args anyway
2281 // so we get all the error messages
2282 let expected_ty = ty::mk_err();
2283 check_method_argument_types(fcx,
2289 DontTupleArguments);
2295 // could be either an expr_binop or an expr_assign_binop
2296 fn check_binop(fcx: &FnCtxt,
2301 is_binop_assignment: IsBinopAssignment) {
2302 let tcx = fcx.ccx.tcx;
2304 let lvalue_pref = match is_binop_assignment {
2305 BinopAssignment => PreferMutLvalue,
2306 SimpleBinop => NoPreference
2308 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2310 // Callee does bot / err checking
2311 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2312 fcx.expr_ty(&*lhs));
2314 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2315 // Shift is a special case: rhs must be uint, no matter what lhs is
2316 check_expr_has_type(fcx, rhs, ty::mk_uint());
2317 fcx.write_ty(expr.id, lhs_t);
2321 if ty::is_binopable(tcx, lhs_t, op) {
2322 let tvar = fcx.infcx().next_ty_var();
2323 demand::suptype(fcx, expr.span, tvar, lhs_t);
2324 check_expr_has_type(fcx, &*rhs, tvar);
2326 let result_t = match op {
2327 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2329 if ty::type_is_simd(tcx, lhs_t) {
2330 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2331 fcx.type_error_message(expr.span,
2333 format!("binary comparison \
2334 operation `{}` not \
2335 supported for floating \
2336 point SIMD vector `{}`",
2337 ast_util::binop_to_str(op),
2354 fcx.write_ty(expr.id, result_t);
2358 if op == ast::BiOr || op == ast::BiAnd {
2359 // This is an error; one of the operands must have the wrong
2361 fcx.write_error(expr.id);
2362 fcx.write_error(rhs.id);
2363 fcx.type_error_message(expr.span,
2365 format!("binary operation `{}` cannot be applied \
2367 ast_util::binop_to_str(op),
2374 // Check for overloaded operators if not an assignment.
2375 let result_t = if is_binop_assignment == SimpleBinop {
2376 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2378 fcx.type_error_message(expr.span,
2380 format!("binary assignment \
2382 cannot be applied to \
2384 ast_util::binop_to_str(op),
2389 check_expr(fcx, &*rhs);
2393 fcx.write_ty(expr.id, result_t);
2394 if ty::type_is_error(result_t) {
2395 fcx.write_ty(rhs.id, result_t);
2399 fn check_user_binop(fcx: &FnCtxt,
2401 lhs_expr: Gc<ast::Expr>,
2402 lhs_resolved_t: ty::t,
2404 rhs: Gc<ast::Expr>) -> ty::t {
2405 let tcx = fcx.ccx.tcx;
2406 let lang = &tcx.lang_items;
2407 let (name, trait_did) = match op {
2408 ast::BiAdd => ("add", lang.add_trait()),
2409 ast::BiSub => ("sub", lang.sub_trait()),
2410 ast::BiMul => ("mul", lang.mul_trait()),
2411 ast::BiDiv => ("div", lang.div_trait()),
2412 ast::BiRem => ("rem", lang.rem_trait()),
2413 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2414 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2415 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2416 ast::BiShl => ("shl", lang.shl_trait()),
2417 ast::BiShr => ("shr", lang.shr_trait()),
2418 ast::BiLt => ("lt", lang.ord_trait()),
2419 ast::BiLe => ("le", lang.ord_trait()),
2420 ast::BiGe => ("ge", lang.ord_trait()),
2421 ast::BiGt => ("gt", lang.ord_trait()),
2422 ast::BiEq => ("eq", lang.eq_trait()),
2423 ast::BiNe => ("ne", lang.eq_trait()),
2424 ast::BiAnd | ast::BiOr => {
2425 check_expr(fcx, &*rhs);
2426 return ty::mk_err();
2429 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2430 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2431 fcx.type_error_message(ex.span, |actual| {
2432 format!("binary operation `{}` cannot be applied to type `{}`",
2433 ast_util::binop_to_str(op),
2435 }, lhs_resolved_t, None)
2439 fn check_user_unop(fcx: &FnCtxt,
2442 trait_did: Option<ast::DefId>,
2444 rhs_expr: Gc<ast::Expr>,
2445 rhs_t: ty::t) -> ty::t {
2446 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2447 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2448 fcx.type_error_message(ex.span, |actual| {
2449 format!("cannot apply unary operator `{}` to type `{}`",
2455 fn check_expr_fn(fcx: &FnCtxt,
2457 store: ty::TraitStore,
2459 body: ast::P<ast::Block>,
2460 expected: Expectation) {
2461 let tcx = fcx.ccx.tcx;
2463 // Find the expected input/output types (if any). Substitute
2464 // fresh bound regions for any bound regions we find in the
2465 // expected types so as to avoid capture.
2466 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2469 expected_bounds) = {
2470 match expected_sty {
2471 Some(ty::ty_closure(ref cenv)) => {
2473 replace_late_bound_regions_in_fn_sig(
2475 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2476 let onceness = match (&store, &cenv.store) {
2477 // As the closure type and onceness go, only three
2478 // combinations are legit:
2482 // If the actual and expected closure type disagree with
2483 // each other, set expected onceness to be always Once or
2484 // Many according to the actual type. Otherwise, it will
2485 // yield either an illegal "many proc" or a less known
2486 // "once closure" in the error message.
2487 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2488 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2490 (&ty::UniqTraitStore, _) => ast::Once,
2491 (&ty::RegionTraitStore(..), _) => ast::Many,
2493 (Some(sig), onceness, cenv.bounds)
2496 // Not an error! Means we're inferring the closure type
2497 let mut bounds = ty::empty_builtin_bounds();
2498 let onceness = match expr.node {
2499 ast::ExprProc(..) => {
2500 bounds.add(ty::BoundSend);
2505 (None, onceness, bounds)
2510 // construct the function type
2511 let fn_ty = astconv::ty_of_closure(fcx,
2519 let fty_sig = fn_ty.sig.clone();
2520 let fty = ty::mk_closure(tcx, fn_ty);
2521 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2523 fcx.write_ty(expr.id, fty);
2525 // If the closure is a stack closure and hasn't had some non-standard
2526 // style inferred for it, then check it under its parent's style.
2527 // Otherwise, use its own
2528 let (inherited_style, id) = match store {
2529 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2530 fcx.ps.borrow().def),
2531 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2534 check_fn(fcx.ccx, inherited_style, &fty_sig,
2535 &*decl, id, &*body, fcx.inh);
2539 // Check field access expressions
2540 fn check_field(fcx: &FnCtxt,
2542 lvalue_pref: LvaluePreference,
2544 field: &ast::SpannedIdent,
2545 tys: &[ast::P<ast::Ty>]) {
2546 let tcx = fcx.ccx.tcx;
2547 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2548 let expr_t = structurally_resolved_type(fcx, expr.span,
2550 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2551 let (_, autoderefs, field_ty) =
2552 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2553 match ty::get(base_t).sty {
2554 ty::ty_struct(base_id, ref substs) => {
2555 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2556 let fields = ty::lookup_struct_fields(tcx, base_id);
2557 lookup_field_ty(tcx, base_id, fields.as_slice(),
2558 field.node.name, &(*substs))
2565 fcx.write_ty(expr.id, field_ty);
2566 fcx.write_autoderef_adjustment(base.id, autoderefs);
2572 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2573 match method::lookup(fcx,
2580 CheckTraitsAndInherentMethods,
2582 IgnoreStaticMethods) {
2584 fcx.type_error_message(
2587 format!("attempted to take value of method `{}` on type \
2588 `{}`", token::get_ident(field.node), actual)
2592 tcx.sess.span_note(field.span,
2593 "maybe a missing `()` to call it? If not, try an anonymous function.");
2597 fcx.type_error_message(
2600 format!("attempted access of field `{}` on \
2601 type `{}`, but no field with that \
2603 token::get_ident(field.node),
2610 fcx.write_error(expr.id);
2613 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2616 class_id: ast::DefId,
2617 node_id: ast::NodeId,
2618 substitutions: subst::Substs,
2619 field_types: &[ty::field_ty],
2620 ast_fields: &[ast::Field],
2621 check_completeness: bool) {
2622 let tcx = fcx.ccx.tcx;
2624 let mut class_field_map = HashMap::new();
2625 let mut fields_found = 0;
2626 for field in field_types.iter() {
2627 class_field_map.insert(field.name, (field.id, false));
2630 let mut error_happened = false;
2632 // Typecheck each field.
2633 for field in ast_fields.iter() {
2634 let mut expected_field_type = ty::mk_err();
2636 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2639 fcx.type_error_message(
2642 format!("structure `{}` has no field named `{}`",
2643 actual, token::get_ident(field.ident.node))
2647 error_happened = true;
2649 Some((_, true)) => {
2652 format!("field `{}` specified more than once",
2653 token::get_ident(field.ident
2654 .node)).as_slice());
2655 error_happened = true;
2657 Some((field_id, false)) => {
2658 expected_field_type =
2659 ty::lookup_field_type(
2660 tcx, class_id, field_id, &substitutions);
2661 class_field_map.insert(
2662 field.ident.node.name, (field_id, true));
2666 // Make sure to give a type to the field even if there's
2667 // an error, so we can continue typechecking
2668 check_expr_coercable_to_type(
2671 expected_field_type);
2675 fcx.write_error(node_id);
2678 if check_completeness && !error_happened {
2679 // Make sure the programmer specified all the fields.
2680 assert!(fields_found <= field_types.len());
2681 if fields_found < field_types.len() {
2682 let mut missing_fields = Vec::new();
2683 for class_field in field_types.iter() {
2684 let name = class_field.name;
2685 let (_, seen) = *class_field_map.get(&name);
2687 missing_fields.push(
2688 format!("`{}`", token::get_name(name).get()))
2692 tcx.sess.span_err(span,
2694 "missing field{}: {fields}",
2695 if missing_fields.len() == 1 {""} else {"s"},
2696 fields = missing_fields.connect(", ")).as_slice());
2700 if !error_happened {
2701 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2702 class_id, substitutions));
2706 fn check_struct_constructor(fcx: &FnCtxt,
2708 span: codemap::Span,
2709 class_id: ast::DefId,
2710 fields: &[ast::Field],
2711 base_expr: Option<Gc<ast::Expr>>) {
2712 let tcx = fcx.ccx.tcx;
2714 // Look up the number of type parameters and the raw type, and
2715 // determine whether the class is region-parameterized.
2716 let item_type = ty::lookup_item_type(tcx, class_id);
2717 let raw_type = item_type.ty;
2719 // Generate the struct type.
2720 let substitutions = fcx.infcx().fresh_substs_for_type(
2721 span, &item_type.generics);
2722 let mut struct_type = raw_type.subst(tcx, &substitutions);
2724 // Look up and check the fields.
2725 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2726 check_struct_or_variant_fields(fcx,
2732 class_fields.as_slice(),
2734 base_expr.is_none());
2735 if ty::type_is_error(fcx.node_ty(id)) {
2736 struct_type = ty::mk_err();
2739 // Check the base expression if necessary.
2742 Some(base_expr) => {
2743 check_expr_has_type(fcx, &*base_expr, struct_type);
2744 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2745 struct_type = ty::mk_bot();
2750 // Write in the resulting type.
2751 fcx.write_ty(id, struct_type);
2754 fn check_struct_enum_variant(fcx: &FnCtxt,
2756 span: codemap::Span,
2757 enum_id: ast::DefId,
2758 variant_id: ast::DefId,
2759 fields: &[ast::Field]) {
2760 let tcx = fcx.ccx.tcx;
2762 // Look up the number of type parameters and the raw type, and
2763 // determine whether the enum is region-parameterized.
2764 let item_type = ty::lookup_item_type(tcx, enum_id);
2765 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2766 let enum_type = item_type.ty.subst(tcx, &substitutions);
2768 // Look up and check the enum variant fields.
2769 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2770 check_struct_or_variant_fields(fcx,
2776 variant_fields.as_slice(),
2779 fcx.write_ty(id, enum_type);
2782 let tcx = fcx.ccx.tcx;
2785 ast::ExprVstore(ev, vst) => {
2786 let typ = match ev.node {
2787 ast::ExprVec(ref args) => {
2788 let mutability = match vst {
2789 ast::ExprVstoreMutSlice => ast::MutMutable,
2790 _ => ast::MutImmutable,
2792 let mut any_error = false;
2793 let mut any_bot = false;
2794 let t: ty::t = fcx.infcx().next_ty_var();
2795 for e in args.iter() {
2796 check_expr_has_type(fcx, &**e, t);
2797 let arg_t = fcx.expr_ty(&**e);
2798 if ty::type_is_error(arg_t) {
2801 else if ty::type_is_bot(arg_t) {
2810 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2811 ty::mt{ ty: ty::mk_vec(tcx,
2812 ty::mt {ty: t, mutbl: mutability},
2814 mutbl: mutability })
2817 ast::ExprRepeat(ref element, ref count_expr) => {
2818 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2819 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2820 let mutability = match vst {
2821 ast::ExprVstoreMutSlice => ast::MutMutable,
2822 _ => ast::MutImmutable,
2824 let t = fcx.infcx().next_ty_var();
2825 check_expr_has_type(fcx, &**element, t);
2826 let arg_t = fcx.expr_ty(&**element);
2827 if ty::type_is_error(arg_t) {
2829 } else if ty::type_is_bot(arg_t) {
2832 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2833 ty::mt{ ty: ty::mk_vec(tcx,
2834 ty::mt {ty: t, mutbl: mutability},
2839 ast::ExprLit(_) => {
2840 let error = if vst == ast::ExprVstoreSlice {
2841 "`&\"string\"` has been removed; use `\"string\"` instead"
2843 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2845 tcx.sess.span_err(expr.span, error);
2848 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2850 fcx.write_ty(ev.id, typ);
2851 fcx.write_ty(id, typ);
2854 ast::ExprBox(ref place, ref subexpr) => {
2855 check_expr(fcx, &**place);
2856 check_expr(fcx, &**subexpr);
2858 let mut checked = false;
2860 ast::ExprPath(ref path) => {
2861 // FIXME(pcwalton): For now we hardcode the two permissible
2862 // places: the exchange heap and the managed heap.
2863 let definition = lookup_def(fcx, path.span, place.id);
2864 let def_id = definition.def_id();
2865 if tcx.lang_items.exchange_heap() == Some(def_id) {
2866 fcx.write_ty(id, ty::mk_uniq(tcx,
2867 fcx.expr_ty(&**subexpr)));
2869 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2870 fcx.write_ty(id, ty::mk_box(tcx,
2871 fcx.expr_ty(&**subexpr)));
2879 tcx.sess.span_err(expr.span,
2880 "only the managed heap and exchange heap are \
2881 currently supported");
2882 fcx.write_ty(id, ty::mk_err());
2886 ast::ExprLit(lit) => {
2887 let typ = check_lit(fcx, lit, expected);
2888 fcx.write_ty(id, typ);
2890 ast::ExprBinary(op, ref lhs, ref rhs) => {
2891 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2893 let lhs_ty = fcx.expr_ty(&**lhs);
2894 let rhs_ty = fcx.expr_ty(&**rhs);
2895 if ty::type_is_error(lhs_ty) ||
2896 ty::type_is_error(rhs_ty) {
2897 fcx.write_error(id);
2899 else if ty::type_is_bot(lhs_ty) ||
2900 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2904 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2905 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
2907 let lhs_t = fcx.expr_ty(&**lhs);
2908 let result_t = fcx.expr_ty(expr);
2909 demand::suptype(fcx, expr.span, result_t, lhs_t);
2911 let tcx = fcx.tcx();
2912 if !ty::expr_is_lval(tcx, &**lhs) {
2913 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2916 // Overwrite result of check_binop...this preserves existing behavior
2917 // but seems quite dubious with regard to user-defined methods
2918 // and so forth. - Niko
2919 if !ty::type_is_error(result_t)
2920 && !ty::type_is_bot(result_t) {
2921 fcx.write_nil(expr.id);
2924 ast::ExprUnary(unop, ref oprnd) => {
2925 let expected = expected.only_has_type();
2926 let expected_inner = expected.map(fcx, |sty| {
2928 ast::UnBox | ast::UnUniq => match *sty {
2929 ty::ty_box(ty) | ty::ty_uniq(ty) => {
2936 ast::UnNot | ast::UnNeg => {
2944 let lvalue_pref = match unop {
2945 ast::UnDeref => lvalue_pref,
2948 check_expr_with_expectation_and_lvalue_pref(
2949 fcx, &**oprnd, expected_inner, lvalue_pref);
2950 let mut oprnd_t = fcx.expr_ty(&**oprnd);
2951 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2954 oprnd_t = ty::mk_box(tcx, oprnd_t)
2957 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2960 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2961 oprnd_t = match ty::deref(oprnd_t, true) {
2963 None => match try_overloaded_deref(fcx, expr.span,
2964 Some(MethodCall::expr(expr.id)),
2965 Some(&**oprnd), oprnd_t, lvalue_pref) {
2968 let is_newtype = match ty::get(oprnd_t).sty {
2969 ty::ty_struct(did, ref substs) => {
2970 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2972 && fields.get(0).ident ==
2973 token::special_idents::unnamed_field
2978 // This is an obsolete struct deref
2979 tcx.sess.span_err(expr.span,
2980 "single-field tuple-structs can \
2981 no longer be dereferenced");
2983 fcx.type_error_message(expr.span, |actual| {
2984 format!("type `{}` cannot be \
2985 dereferenced", actual)
2994 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2996 if !(ty::type_is_integral(oprnd_t) ||
2997 ty::get(oprnd_t).sty == ty::ty_bool) {
2998 oprnd_t = check_user_unop(fcx, "!", "not",
2999 tcx.lang_items.not_trait(),
3000 expr, oprnd.clone(), oprnd_t);
3004 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3006 if !(ty::type_is_integral(oprnd_t) ||
3007 ty::type_is_fp(oprnd_t)) {
3008 oprnd_t = check_user_unop(fcx, "-", "neg",
3009 tcx.lang_items.neg_trait(),
3010 expr, oprnd.clone(), oprnd_t);
3015 fcx.write_ty(id, oprnd_t);
3017 ast::ExprAddrOf(mutbl, ref oprnd) => {
3018 let expected = expected.only_has_type();
3019 let hint = expected.map(fcx, |sty| {
3020 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3021 _ => NoExpectation }
3023 let lvalue_pref = match mutbl {
3024 ast::MutMutable => PreferMutLvalue,
3025 ast::MutImmutable => NoPreference
3027 check_expr_with_expectation_and_lvalue_pref(fcx,
3032 // Note: at this point, we cannot say what the best lifetime
3033 // is to use for resulting pointer. We want to use the
3034 // shortest lifetime possible so as to avoid spurious borrowck
3035 // errors. Moreover, the longest lifetime will depend on the
3036 // precise details of the value whose address is being taken
3037 // (and how long it is valid), which we don't know yet until type
3038 // inference is complete.
3040 // Therefore, here we simply generate a region variable. The
3041 // region inferencer will then select the ultimate value.
3042 // Finally, borrowck is charged with guaranteeing that the
3043 // value whose address was taken can actually be made to live
3044 // as long as it needs to live.
3045 let region = fcx.infcx().next_region_var(
3046 infer::AddrOfRegion(expr.span));
3048 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3049 let oprnd_t = if ty::type_is_error(tm.ty) {
3051 } else if ty::type_is_bot(tm.ty) {
3055 ty::mk_rptr(tcx, region, tm)
3057 fcx.write_ty(id, oprnd_t);
3059 ast::ExprPath(ref pth) => {
3060 let defn = lookup_def(fcx, pth.span, id);
3061 let pty = polytype_for_def(fcx, expr.span, defn);
3062 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3064 ast::ExprInlineAsm(ref ia) => {
3065 for &(_, ref input) in ia.inputs.iter() {
3066 check_expr(fcx, &**input);
3068 for &(_, ref out) in ia.outputs.iter() {
3069 check_expr(fcx, &**out);
3073 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3074 ast::ExprBreak(_) => { fcx.write_bot(id); }
3075 ast::ExprAgain(_) => { fcx.write_bot(id); }
3076 ast::ExprRet(ref expr_opt) => {
3077 let ret_ty = fcx.ret_ty;
3079 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3080 ret_ty, ty::mk_nil()) {
3081 Ok(_) => { /* fall through */ }
3085 "`return;` in function returning non-nil");
3089 check_expr_has_type(fcx, &**e, ret_ty);
3094 ast::ExprParen(a) => {
3095 check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
3096 fcx.write_ty(id, fcx.expr_ty(a));
3098 ast::ExprAssign(ref lhs, ref rhs) => {
3099 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3101 let tcx = fcx.tcx();
3102 if !ty::expr_is_lval(tcx, &**lhs) {
3103 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
3106 let lhs_ty = fcx.expr_ty(&**lhs);
3107 check_expr_has_type(fcx, &**rhs, lhs_ty);
3108 let rhs_ty = fcx.expr_ty(&**rhs);
3110 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3111 fcx.write_error(id);
3112 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3118 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3119 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3120 id, expr.span, expected);
3122 ast::ExprWhile(ref cond, ref body) => {
3123 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3124 check_block_no_value(fcx, &**body);
3125 let cond_ty = fcx.expr_ty(&**cond);
3126 let body_ty = fcx.node_ty(body.id);
3127 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3128 fcx.write_error(id);
3130 else if ty::type_is_bot(cond_ty) {
3137 ast::ExprForLoop(..) =>
3138 fail!("non-desugared expr_for_loop"),
3139 ast::ExprLoop(ref body, _) => {
3140 check_block_no_value(fcx, &**body);
3141 if !may_break(tcx, expr.id, body.clone()) {
3148 ast::ExprMatch(ref discrim, ref arms) => {
3149 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3151 ast::ExprFnBlock(ref decl, ref body) => {
3152 let region = astconv::opt_ast_region_to_region(fcx,
3158 ty::RegionTraitStore(region, ast::MutMutable),
3163 ast::ExprProc(ref decl, ref body) => {
3171 ast::ExprBlock(ref b) => {
3172 check_block_with_expected(fcx, &**b, expected);
3173 fcx.write_ty(id, fcx.node_ty(b.id));
3175 ast::ExprCall(ref f, ref args) => {
3176 // Index expressions need to be handled separately, to inform them
3177 // that they appear in call position.
3178 check_expr(fcx, &**f);
3179 let f_ty = fcx.expr_ty(&**f);
3181 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3182 check_call(fcx, expr, &**f, args.as_slice());
3183 let (args_bot, args_err) = args.iter().fold((false, false),
3184 |(rest_bot, rest_err), a| {
3185 // is this not working?
3186 let a_ty = fcx.expr_ty(&**a);
3187 (rest_bot || ty::type_is_bot(a_ty),
3188 rest_err || ty::type_is_error(a_ty))});
3189 if ty::type_is_error(f_ty) || args_err {
3190 fcx.write_error(id);
3192 else if ty::type_is_bot(f_ty) || args_bot {
3197 ast::ExprMethodCall(ident, ref tps, ref args) => {
3198 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3199 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3200 let (args_bot, args_err) = arg_tys.fold((false, false),
3201 |(rest_bot, rest_err), a| {
3202 (rest_bot || ty::type_is_bot(a),
3203 rest_err || ty::type_is_error(a))});
3205 fcx.write_error(id);
3206 } else if args_bot {
3210 ast::ExprCast(ref e, ref t) => {
3211 check_cast(fcx, &**e, &**t, id, expr.span);
3213 ast::ExprVec(ref args) => {
3214 let t: ty::t = fcx.infcx().next_ty_var();
3215 for e in args.iter() {
3216 check_expr_has_type(fcx, &**e, t);
3218 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3220 fcx.write_ty(id, typ);
3222 ast::ExprRepeat(ref element, ref count_expr) => {
3223 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3224 let count = ty::eval_repeat_count(fcx, &**count_expr);
3225 let t: ty::t = fcx.infcx().next_ty_var();
3226 check_expr_has_type(fcx, &**element, t);
3227 let element_ty = fcx.expr_ty(&**element);
3228 if ty::type_is_error(element_ty) {
3229 fcx.write_error(id);
3231 else if ty::type_is_bot(element_ty) {
3235 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3237 fcx.write_ty(id, t);
3240 ast::ExprTup(ref elts) => {
3241 let expected = expected.only_has_type();
3242 let flds = expected.map_to_option(fcx, |sty| {
3244 ty::ty_tup(ref flds) => Some((*flds).clone()),
3248 let mut bot_field = false;
3249 let mut err_field = false;
3251 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3252 let opt_hint = match flds {
3253 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3256 check_expr_with_expectation(fcx, *e, opt_hint);
3257 let t = fcx.expr_ty(*e);
3258 err_field = err_field || ty::type_is_error(t);
3259 bot_field = bot_field || ty::type_is_bot(t);
3264 } else if err_field {
3265 fcx.write_error(id);
3267 let typ = ty::mk_tup(tcx, elt_ts);
3268 fcx.write_ty(id, typ);
3271 ast::ExprStruct(ref path, ref fields, base_expr) => {
3272 // Resolve the path.
3273 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3275 Some(def::DefStruct(type_def_id)) => {
3276 check_struct_constructor(fcx, id, expr.span, type_def_id,
3277 fields.as_slice(), base_expr);
3279 Some(def::DefVariant(enum_id, variant_id, _)) => {
3280 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3281 variant_id, fields.as_slice());
3284 tcx.sess.span_bug(path.span,
3285 "structure constructor does not name a structure type");
3289 ast::ExprField(ref base, ref field, ref tys) => {
3290 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3292 ast::ExprIndex(ref base, ref idx) => {
3293 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3294 check_expr(fcx, &**idx);
3295 let raw_base_t = fcx.expr_ty(&**base);
3296 let idx_t = fcx.expr_ty(&**idx);
3297 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3298 fcx.write_ty(id, raw_base_t);
3299 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3300 fcx.write_ty(id, idx_t);
3302 let (base_t, autoderefs, field_ty) =
3303 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3304 lvalue_pref, |base_t, _| ty::index(base_t));
3307 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3308 fcx.write_ty(id, mt.ty);
3309 fcx.write_autoderef_adjustment(base.id, autoderefs);
3312 let resolved = structurally_resolved_type(fcx,
3315 let ret_ty = lookup_op_method(fcx,
3318 token::intern("index"),
3319 tcx.lang_items.index_trait(),
3320 [base.clone(), idx.clone()],
3323 fcx.type_error_message(expr.span,
3325 format!("cannot index a \
3332 fcx.write_ty(id, ret_ty);
3339 debug!("type of expr({}) {} is...", expr.id,
3340 syntax::print::pprust::expr_to_str(expr));
3341 debug!("... {}, expected is {}",
3342 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3349 fn only_has_type(self) -> Expectation {
3351 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3352 ExpectHasType(t) => ExpectHasType(t)
3356 // Resolves `expected` by a single level if it is a variable. If
3357 // there is no expected type or resolution is not possible (e.g.,
3358 // no constraints yet present), just returns `None`.
3359 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3364 ExpectCastableToType(t) => {
3365 ExpectCastableToType(
3366 fcx.infcx().resolve_type_vars_if_possible(t))
3368 ExpectHasType(t) => {
3370 fcx.infcx().resolve_type_vars_if_possible(t))
3375 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3376 match self.resolve(fcx) {
3377 NoExpectation => NoExpectation,
3378 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3382 fn map_to_option<O>(self,
3384 unpack: |&ty::sty| -> Option<O>)
3387 match self.resolve(fcx) {
3388 NoExpectation => None,
3389 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3394 impl Repr for Expectation {
3395 fn repr(&self, tcx: &ty::ctxt) -> String {
3397 NoExpectation => format!("NoExpectation"),
3398 ExpectHasType(t) => format!("ExpectHasType({})",
3400 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3406 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3407 if !type_is_uint(fcx, sp, t) {
3408 fcx.type_error_message(sp, |actual| {
3409 format!("mismatched types: expected `uint` type but found `{}`",
3415 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3416 if !type_is_integral(fcx, sp, t) {
3417 fcx.type_error_message(sp, |actual| {
3418 format!("mismatched types: expected integral type but found `{}`",
3424 pub fn check_decl_initializer(fcx: &FnCtxt,
3428 let local_ty = fcx.local_ty(init.span, nid);
3429 check_expr_coercable_to_type(fcx, init, local_ty)
3432 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3433 let tcx = fcx.ccx.tcx;
3435 let t = fcx.local_ty(local.span, local.id);
3436 fcx.write_ty(local.id, t);
3440 check_decl_initializer(fcx, local.id, &**init);
3441 let init_ty = fcx.expr_ty(&**init);
3442 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3443 fcx.write_ty(local.id, init_ty);
3449 let pcx = pat_ctxt {
3451 map: pat_id_map(&tcx.def_map, &*local.pat),
3453 _match::check_pat(&pcx, &*local.pat, t);
3454 let pat_ty = fcx.node_ty(local.pat.id);
3455 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3456 fcx.write_ty(local.id, pat_ty);
3460 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3462 let mut saw_bot = false;
3463 let mut saw_err = false;
3465 ast::StmtDecl(decl, id) => {
3468 ast::DeclLocal(ref l) => {
3469 check_decl_local(fcx, &**l);
3470 let l_t = fcx.node_ty(l.id);
3471 saw_bot = saw_bot || ty::type_is_bot(l_t);
3472 saw_err = saw_err || ty::type_is_error(l_t);
3474 ast::DeclItem(_) => {/* ignore for now */ }
3477 ast::StmtExpr(ref expr, id) => {
3479 // Check with expected type of ()
3480 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3481 let expr_ty = fcx.expr_ty(&**expr);
3482 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3483 saw_err = saw_err || ty::type_is_error(expr_ty);
3485 ast::StmtSemi(ref expr, id) => {
3487 check_expr(fcx, &**expr);
3488 let expr_ty = fcx.expr_ty(&**expr);
3489 saw_bot |= ty::type_is_bot(expr_ty);
3490 saw_err |= ty::type_is_error(expr_ty);
3492 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3495 fcx.write_bot(node_id);
3498 fcx.write_error(node_id);
3501 fcx.write_nil(node_id)
3505 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3506 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3507 let blkty = fcx.node_ty(blk.id);
3508 if ty::type_is_error(blkty) {
3509 fcx.write_error(blk.id);
3511 else if ty::type_is_bot(blkty) {
3512 fcx.write_bot(blk.id);
3515 let nilty = ty::mk_nil();
3516 demand::suptype(fcx, blk.span, nilty, blkty);
3520 fn check_block_with_expected(fcx: &FnCtxt,
3522 expected: Expectation) {
3524 let mut fcx_ps = fcx.ps.borrow_mut();
3525 let fn_style_state = fcx_ps.recurse(blk);
3526 replace(&mut *fcx_ps, fn_style_state)
3529 fcx.with_region_lb(blk.id, || {
3530 let mut warned = false;
3531 let mut last_was_bot = false;
3532 let mut any_bot = false;
3533 let mut any_err = false;
3534 for s in blk.stmts.iter() {
3535 check_stmt(fcx, &**s);
3536 let s_id = ast_util::stmt_id(&**s);
3537 let s_ty = fcx.node_ty(s_id);
3538 if last_was_bot && !warned && match s.node {
3539 ast::StmtDecl(decl, _) => {
3541 ast::DeclLocal(_) => true,
3545 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3551 .add_lint(lint::builtin::UNREACHABLE_CODE,
3554 "unreachable statement".to_string());
3557 if ty::type_is_bot(s_ty) {
3558 last_was_bot = true;
3560 any_bot = any_bot || ty::type_is_bot(s_ty);
3561 any_err = any_err || ty::type_is_error(s_ty);
3564 None => if any_err {
3565 fcx.write_error(blk.id);
3568 fcx.write_bot(blk.id);
3571 fcx.write_nil(blk.id);
3574 if any_bot && !warned {
3578 .add_lint(lint::builtin::UNREACHABLE_CODE,
3581 "unreachable expression".to_string());
3583 check_expr_with_expectation(fcx, e, expected);
3584 let ety = fcx.expr_ty(e);
3585 fcx.write_ty(blk.id, ety);
3587 fcx.write_error(blk.id);
3590 fcx.write_bot(blk.id);
3596 *fcx.ps.borrow_mut() = prev;
3599 pub fn check_const(ccx: &CrateCtxt,
3603 let inh = blank_inherited_fields(ccx);
3604 let rty = ty::node_id_to_type(ccx.tcx, id);
3605 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3606 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3607 check_const_with_ty(&fcx, sp, e, declty);
3610 pub fn check_const_with_ty(fcx: &FnCtxt,
3614 // Gather locals in statics (because of block expressions).
3615 // This is technically unnecessary because locals in static items are forbidden,
3616 // but prevents type checking from blowing up before const checking can properly
3618 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3621 let cty = fcx.expr_ty(e);
3622 demand::suptype(fcx, e.span, declty, cty);
3623 regionck::regionck_expr(fcx, e);
3624 writeback::resolve_type_vars_in_expr(fcx, e);
3627 /// Checks whether a type can be represented in memory. In particular, it
3628 /// identifies types that contain themselves without indirection through a
3629 /// pointer, which would mean their size is unbounded. This is different from
3630 /// the question of whether a type can be instantiated. See the definition of
3631 /// `check_instantiable`.
3632 pub fn check_representable(tcx: &ty::ctxt,
3634 item_id: ast::NodeId,
3635 designation: &str) -> bool {
3636 let rty = ty::node_id_to_type(tcx, item_id);
3638 // Check that it is possible to represent this type. This call identifies
3639 // (1) types that contain themselves and (2) types that contain a different
3640 // recursive type. It is only necessary to throw an error on those that
3641 // contain themselves. For case 2, there must be an inner type that will be
3642 // caught by case 1.
3643 match ty::is_type_representable(tcx, sp, rty) {
3644 ty::SelfRecursive => {
3646 sp, format!("illegal recursive {} type; \
3647 wrap the inner value in a box to make it representable",
3648 designation).as_slice());
3651 ty::Representable | ty::ContainsRecursive => (),
3656 /// Checks whether a type can be created without an instance of itself.
3657 /// This is similar but different from the question of whether a type
3658 /// can be represented. For example, the following type:
3660 /// enum foo { None, Some(foo) }
3662 /// is instantiable but is not representable. Similarly, the type
3664 /// enum foo { Some(@foo) }
3666 /// is representable, but not instantiable.
3667 pub fn check_instantiable(tcx: &ty::ctxt,
3669 item_id: ast::NodeId)
3671 let item_ty = ty::node_id_to_type(tcx, item_id);
3672 if !ty::is_instantiable(tcx, item_ty) {
3675 format!("this type cannot be instantiated without an \
3676 instance of itself; consider using \
3678 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3685 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3686 let t = ty::node_id_to_type(tcx, id);
3687 if ty::type_needs_subst(t) {
3688 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3691 match ty::get(t).sty {
3692 ty::ty_struct(did, ref substs) => {
3693 let fields = ty::lookup_struct_fields(tcx, did);
3694 if fields.is_empty() {
3695 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3698 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3699 if !fields.iter().all(
3700 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3701 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3704 if !ty::type_is_machine(e) {
3705 tcx.sess.span_err(sp, "SIMD vector element type should be \
3714 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3715 vs: &[ast::P<ast::Variant>]) {
3716 for &v in vs.iter() {
3718 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3719 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3720 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3721 let len = arg_tys.len();
3725 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3726 // Allow the last field in an enum to be unsized.
3727 // We want to do this so that we can support smart pointers.
3728 // A struct value with an unsized final field is itself
3729 // unsized and we must track this in the type system.
3730 if !ty::type_is_sized(ccx.tcx, *t) {
3734 args.get(i).ty.span,
3735 format!("type `{}` is dynamically sized. \
3736 dynamically sized types may only \
3737 appear as the final type in a \
3739 ppaux::ty_to_str(ccx.tcx,
3744 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3750 pub fn check_enum_variants(ccx: &CrateCtxt,
3752 vs: &[ast::P<ast::Variant>],
3755 fn disr_in_range(ccx: &CrateCtxt,
3757 disr: ty::Disr) -> bool {
3758 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3760 ast::TyU8 => disr as u8 as Disr == disr,
3761 ast::TyU16 => disr as u16 as Disr == disr,
3762 ast::TyU32 => disr as u32 as Disr == disr,
3763 ast::TyU64 => disr as u64 as Disr == disr,
3764 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3767 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3769 ast::TyI8 => disr as i8 as Disr == disr,
3770 ast::TyI16 => disr as i16 as Disr == disr,
3771 ast::TyI32 => disr as i32 as Disr == disr,
3772 ast::TyI64 => disr as i64 as Disr == disr,
3773 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3777 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3778 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3782 fn do_check(ccx: &CrateCtxt,
3783 vs: &[ast::P<ast::Variant>],
3785 hint: attr::ReprAttr)
3786 -> Vec<Rc<ty::VariantInfo>> {
3788 let rty = ty::node_id_to_type(ccx.tcx, id);
3789 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3790 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3791 let mut prev_disr_val: Option<ty::Disr> = None;
3793 for &v in vs.iter() {
3795 // If the discriminant value is specified explicitly in the enum check whether the
3796 // initialization expression is valid, otherwise use the last value plus one.
3797 let mut current_disr_val = match prev_disr_val {
3798 Some(prev_disr_val) => prev_disr_val + 1,
3799 None => ty::INITIAL_DISCRIMINANT_VALUE
3802 match v.node.disr_expr {
3804 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3806 let inh = blank_inherited_fields(ccx);
3807 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3808 let declty = match hint {
3809 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
3810 attr::ReprInt(_, attr::SignedInt(ity)) => {
3811 ty::mk_mach_int(ity)
3813 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
3814 ty::mk_mach_uint(ity)
3817 check_const_with_ty(&fcx, e.span, &*e, declty);
3818 // check_expr (from check_const pass) doesn't guarantee
3819 // that the expression is in a form that eval_const_expr can
3820 // handle, so we may still get an internal compiler error
3822 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3823 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3824 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3826 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3832 format!("expected constant: {}",
3840 // Check for duplicate discriminant values
3841 if disr_vals.contains(¤t_disr_val) {
3842 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3844 // Check for unrepresentable discriminant values
3846 attr::ReprAny | attr::ReprExtern => (),
3847 attr::ReprInt(sp, ity) => {
3848 if !disr_in_range(ccx, ity, current_disr_val) {
3849 ccx.tcx.sess.span_err(v.span,
3850 "discriminant value outside specified type");
3851 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3855 disr_vals.push(current_disr_val);
3857 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3859 prev_disr_val = Some(current_disr_val);
3861 variants.push(variant_info);
3867 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3868 if hint != attr::ReprAny && vs.len() <= 1 {
3869 let msg = if vs.len() == 1 {
3870 "unsupported representation for univariant enum"
3872 "unsupported representation for zero-variant enum"
3874 ccx.tcx.sess.span_err(sp, msg)
3877 let variants = do_check(ccx, vs, id, hint);
3879 // cache so that ty::enum_variants won't repeat this work
3880 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3882 check_representable(ccx.tcx, sp, id, "enum");
3884 // Check that it is possible to instantiate this enum:
3886 // This *sounds* like the same that as representable, but it's
3887 // not. See def'n of `check_instantiable()` for details.
3888 check_instantiable(ccx.tcx, sp, id);
3891 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3892 lookup_def_ccx(fcx.ccx, sp, id)
3895 // Returns the type parameter count and the type for the given definition.
3896 pub fn polytype_for_def(fcx: &FnCtxt,
3901 def::DefArg(nid, _) | def::DefLocal(nid, _) |
3902 def::DefBinding(nid, _) => {
3903 let typ = fcx.local_ty(sp, nid);
3904 return no_params(typ);
3906 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
3907 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
3908 def::DefStruct(id) => {
3909 return ty::lookup_item_type(fcx.ccx.tcx, id);
3911 def::DefUpvar(_, inner, _, _) => {
3912 return polytype_for_def(fcx, sp, *inner);
3917 def::DefTyParam(..)=> {
3918 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3920 def::DefMod(..) | def::DefForeignMod(..) => {
3921 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3923 def::DefUse(..) => {
3924 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3926 def::DefRegion(..) => {
3927 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3929 def::DefTyParamBinder(..) => {
3930 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3932 def::DefLabel(..) => {
3933 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3935 def::DefSelfTy(..) => {
3936 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3938 def::DefMethod(..) => {
3939 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3944 // Instantiates the given path, which must refer to an item with the given
3945 // number of type parameters and type.
3946 pub fn instantiate_path(fcx: &FnCtxt,
3951 node_id: ast::NodeId) {
3952 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
3953 path.repr(fcx.tcx()),
3954 def.repr(fcx.tcx()),
3956 polytype.repr(fcx.tcx()));
3958 // We need to extract the type parameters supplied by the user in
3959 // the path `path`. Due to the current setup, this is a bit of a
3960 // tricky-process; the problem is that resolve only tells us the
3961 // end-point of the path resolution, and not the intermediate steps.
3962 // Luckily, we can (at least for now) deduce the intermediate steps
3963 // just from the end-point.
3965 // There are basically three cases to consider:
3967 // 1. Reference to a *type*, such as a struct or enum:
3969 // mod a { struct Foo<T> { ... } }
3971 // Because we don't allow types to be declared within one
3972 // another, a path that leads to a type will always look like
3973 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
3974 // that only the final segment can have type parameters, and
3975 // they are located in the TypeSpace.
3977 // *Note:* Generally speaking, references to types don't
3978 // actually pass through this function, but rather the
3979 // `ast_ty_to_ty` function in `astconv`. However, in the case
3980 // of struct patterns (and maybe literals) we do invoke
3981 // `instantiate_path` to get the general type of an instance of
3982 // a struct. (In these cases, there are actually no type
3983 // parameters permitted at present, but perhaps we will allow
3984 // them in the future.)
3986 // 1b. Reference to a enum variant or tuple-like struct:
3988 // struct foo<T>(...)
3989 // enum E<T> { foo(...) }
3991 // In these cases, the parameters are declared in the type
3994 // 2. Reference to a *fn item*:
3998 // In this case, the path will again always have the form
3999 // `a::b::foo::<T>` where only the final segment should have
4000 // type parameters. However, in this case, those parameters are
4001 // declared on a value, and hence are in the `FnSpace`.
4003 // 3. Reference to a *method*:
4005 // impl<A> SomeStruct<A> {
4009 // Here we can have a path like
4010 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4011 // may appear in two places. The penultimate segment,
4012 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4013 // final segment, `foo::<B>` contains parameters in fn space.
4015 // The first step then is to categorize the segments appropriately.
4017 assert!(path.segments.len() >= 1);
4018 let mut segment_spaces;
4020 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4021 def::DefSelfTy(..) |
4022 def::DefStruct(..) |
4023 def::DefVariant(..) |
4024 def::DefTyParamBinder(..) |
4027 def::DefPrimTy(..) |
4028 def::DefTyParam(..) => {
4029 // Everything but the final segment should have no
4030 // parameters at all.
4031 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4032 segment_spaces.push(Some(subst::TypeSpace));
4035 // Case 2. Reference to a top-level value.
4037 def::DefStatic(..) => {
4038 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4039 segment_spaces.push(Some(subst::FnSpace));
4042 // Case 3. Reference to a method.
4043 def::DefStaticMethod(..) => {
4044 assert!(path.segments.len() >= 2);
4045 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4046 segment_spaces.push(Some(subst::TypeSpace));
4047 segment_spaces.push(Some(subst::FnSpace));
4050 // Other cases. Various nonsense that really shouldn't show up
4051 // here. If they do, an error will have been reported
4052 // elsewhere. (I hope)
4054 def::DefForeignMod(..) |
4057 def::DefMethod(..) |
4058 def::DefBinding(..) |
4060 def::DefRegion(..) |
4062 def::DefUpvar(..) => {
4063 segment_spaces = Vec::from_elem(path.segments.len(), None);
4066 assert_eq!(segment_spaces.len(), path.segments.len());
4068 debug!("segment_spaces={}", segment_spaces);
4070 // Next, examine the definition, and determine how many type
4071 // parameters we expect from each space.
4072 let type_defs = &polytype.generics.types;
4073 let region_defs = &polytype.generics.regions;
4075 // Now that we have categorized what space the parameters for each
4076 // segment belong to, let's sort out the parameters that the user
4077 // provided (if any) into their appropriate spaces. We'll also report
4078 // errors if type parameters are provided in an inappropriate place.
4079 let mut substs = Substs::empty();
4080 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4083 report_error_if_segment_contains_type_parameters(fcx, segment);
4087 push_explicit_parameters_from_segment_to_substs(fcx,
4097 // Now we have to compare the types that the user *actually*
4098 // provided against the types that were *expected*. If the user
4099 // did not provide any types, then we want to substitute inference
4100 // variables. If the user provided some types, we may still need
4101 // to add defaults. If the user provided *too many* types, that's
4103 for &space in ParamSpace::all().iter() {
4104 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4105 assert_eq!(substs.types.get_vec(space).len(),
4106 type_defs.get_vec(space).len());
4108 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4109 assert_eq!(substs.regions().get_vec(space).len(),
4110 region_defs.get_vec(space).len());
4113 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4117 fn report_error_if_segment_contains_type_parameters(
4119 segment: &ast::PathSegment)
4121 for typ in segment.types.iter() {
4122 fcx.tcx().sess.span_err(
4124 "type parameters may not appear here");
4128 for lifetime in segment.lifetimes.iter() {
4129 fcx.tcx().sess.span_err(
4131 "lifetime parameters may not appear here");
4136 fn push_explicit_parameters_from_segment_to_substs(
4138 space: subst::ParamSpace,
4139 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4140 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4141 segment: &ast::PathSegment,
4142 substs: &mut Substs)
4145 * Finds the parameters that the user provided and adds them
4146 * to `substs`. If too many parameters are provided, then
4147 * reports an error and clears the output vector.
4149 * We clear the output vector because that will cause the
4150 * `adjust_XXX_parameters()` later to use inference
4151 * variables. This seems less likely to lead to derived
4154 * Note that we *do not* check for *too few* parameters here.
4155 * Due to the presence of defaults etc that is more
4156 * complicated. I wanted however to do the reporting of *too
4157 * many* parameters here because we can easily use the precise
4158 * span of the N+1'th parameter.
4162 let type_count = type_defs.get_vec(space).len();
4163 assert_eq!(substs.types.get_vec(space).len(), 0);
4164 for (i, &typ) in segment.types.iter().enumerate() {
4165 let t = fcx.to_ty(&*typ);
4167 substs.types.push(space, t);
4168 } else if i == type_count {
4169 fcx.tcx().sess.span_err(
4172 "too many type parameters provided: \
4173 expected at most {} parameter(s) \
4174 but found {} parameter(s)",
4176 segment.types.len()).as_slice());
4177 substs.types.get_mut_vec(space).truncate(0);
4183 let region_count = region_defs.get_vec(space).len();
4184 assert_eq!(substs.regions().get_vec(space).len(), 0);
4185 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4186 let r = ast_region_to_region(fcx.tcx(), lifetime);
4187 if i < region_count {
4188 substs.mut_regions().push(space, r);
4189 } else if i == region_count {
4190 fcx.tcx().sess.span_err(
4193 "too many lifetime parameters provided: \
4194 expected {} parameter(s) but found {} parameter(s)",
4196 segment.lifetimes.len()).as_slice());
4197 substs.mut_regions().get_mut_vec(space).truncate(0);
4203 fn adjust_type_parameters(
4207 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4208 substs: &mut Substs)
4210 let provided_len = substs.types.get_vec(space).len();
4211 let desired = defs.get_vec(space).as_slice();
4212 let required_len = desired.iter()
4213 .take_while(|d| d.default.is_none())
4216 debug!("adjust_type_parameters(space={}, \
4225 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4226 assert!(provided_len <= desired.len());
4228 // Nothing specified at all: supply inference variables for
4230 if provided_len == 0 {
4231 let provided = substs.types.get_mut_vec(space);
4232 *provided = fcx.infcx().next_ty_vars(desired.len());
4236 // Too few parameters specified: report an error and use Err
4238 if provided_len < required_len {
4240 if desired.len() != required_len { "at least " } else { "" };
4241 fcx.tcx().sess.span_err(
4243 format!("too few type parameters provided: \
4244 expected {}{} parameter(s) \
4245 but found {} parameter(s)",
4248 provided_len).as_slice());
4249 let provided = substs.types.get_mut_vec(space);
4250 *provided = Vec::from_elem(desired.len(), ty::mk_err());
4254 // Otherwise, add in any optional parameters that the user
4255 // omitted. The case of *too many* parameters is handled
4257 // push_explicit_parameters_from_segment_to_substs(). Note
4258 // that the *default* type are expressed in terms of all prior
4259 // parameters, so we have to substitute as we go with the
4260 // partial substitution that we have built up.
4261 for i in range(provided_len, desired.len()) {
4262 let default = desired[i].default.unwrap();
4263 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4264 substs.types.push(space, default);
4266 assert_eq!(substs.types.get_vec(space).len(), desired.len());
4268 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4271 fn adjust_region_parameters(
4275 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4276 substs: &mut Substs)
4278 let provided = substs.mut_regions().get_mut_vec(space);
4279 let desired = defs.get_vec(space);
4281 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4282 assert!(provided.len() <= desired.len());
4284 // If nothing was provided, just use inference variables.
4285 if provided.len() == 0 {
4286 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4290 // If just the right number were provided, everybody is happy.
4291 if provided.len() == desired.len() {
4295 // Otherwise, too few were provided. Report an error and then
4296 // use inference variables.
4297 fcx.tcx().sess.span_err(
4300 "too few lifetime parameters provided: \
4301 expected {} parameter(s) \
4302 but found {} parameter(s)",
4304 provided.len()).as_slice());
4306 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4310 // Resolves `typ` by a single level if `typ` is a type variable. If no
4311 // resolution is possible, then an error is reported.
4312 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4313 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4314 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4316 fcx.type_error_message(sp, |_actual| {
4317 "the type of this value must be known in this \
4318 context".to_string()
4320 demand::suptype(fcx, sp, ty::mk_err(), tp);
4326 // Returns the one-level-deep structure of the given type.
4327 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4329 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4332 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4333 let typ_s = structurally_resolved_type(fcx, sp, typ);
4334 return ty::type_is_integral(typ_s);
4337 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4338 let typ_s = structurally_resolved_type(fcx, sp, typ);
4339 return ty::type_is_uint(typ_s);
4342 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4345 mk_inner: || -> ty::mt)
4348 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4349 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4351 ast::ExprLit(..) => {
4352 // string literals and *empty slices* live in static memory
4353 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4355 ast::ExprVec(ref elements) if elements.len() == 0 => {
4356 // string literals and *empty slices* live in static memory
4357 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4359 ast::ExprRepeat(..) |
4360 ast::ExprVec(..) => {
4361 // vector literals are temporaries on the stack
4362 match fcx.tcx().region_maps.temporary_scope(e.id) {
4363 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4364 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4368 fcx.ccx.tcx.sess.span_bug(e.span,
4369 "vstore with unexpected \
4377 // Returns true if b contains a break that can exit from b
4378 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4379 // First: is there an unlabeled break immediately
4381 (loop_query(&*b, |e| {
4383 ast::ExprBreak(_) => true,
4387 // Second: is there a labeled break with label
4388 // <id> nested anywhere inside the loop?
4389 (block_query(b, |e| {
4391 ast::ExprBreak(Some(_)) => {
4392 match cx.def_map.borrow().find(&e.id) {
4393 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4401 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4403 tps: &OwnedSlice<ast::TyParam>,
4405 debug!("check_bounds_are_used(n_tps={}, ty={})",
4406 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4408 // make a vector of booleans initially false, set to true when used
4409 if tps.len() == 0u { return; }
4410 let mut tps_used = Vec::from_elem(tps.len(), false);
4412 ty::walk_ty(ty, |t| {
4413 match ty::get(t).sty {
4414 ty::ty_param(ParamTy {idx, ..}) => {
4415 debug!("Found use of ty param num {}", idx);
4416 *tps_used.get_mut(idx) = true;
4422 for (i, b) in tps_used.iter().enumerate() {
4424 ccx.tcx.sess.span_err(
4426 format!("type parameter `{}` is unused",
4427 token::get_ident(tps.get(i).ident)).as_slice());
4432 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4433 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4434 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4438 let name = token::get_ident(it.ident);
4439 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4440 let split : Vec<&str> = name.get().split('_').collect();
4441 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4443 //We only care about the operation here
4444 match *split.get(1) {
4445 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4449 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4451 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4454 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4455 "min" | "umax" | "umin" => {
4456 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4460 (0, Vec::new(), ty::mk_nil())
4463 tcx.sess.span_err(it.span,
4464 format!("unrecognized atomic operation \
4473 "abort" => (0, Vec::new(), ty::mk_bot()),
4474 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4476 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4477 "init" => (1u, Vec::new(), param(ccx, 0u)),
4478 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4479 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4480 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4481 "move_val_init" => {
4484 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4489 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4490 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4493 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4495 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4497 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4499 mutbl: ast::MutImmutable
4501 (1u, Vec::new(), td_ptr)
4504 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4508 ty::mk_struct(ccx.tcx, did,
4509 subst::Substs::empty())),
4511 tcx.sess.span_fatal(it.span, msg.as_slice());
4516 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4518 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4520 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4521 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4522 Ok((_, vot)) => vot,
4523 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4526 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4528 mutbl: ast::MutImmutable
4530 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4535 ty::mk_ptr(tcx, ty::mt {
4537 mutbl: ast::MutImmutable
4541 ty::mk_ptr(tcx, ty::mt {
4543 mutbl: ast::MutImmutable
4546 "copy_memory" | "copy_nonoverlapping_memory" |
4547 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4550 ty::mk_ptr(tcx, ty::mt {
4552 mutbl: ast::MutMutable
4554 ty::mk_ptr(tcx, ty::mt {
4556 mutbl: ast::MutImmutable
4562 "set_memory" | "volatile_set_memory" => {
4565 ty::mk_ptr(tcx, ty::mt {
4567 mutbl: ast::MutMutable
4574 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4575 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4578 vec!( ty::mk_f32(), ty::mk_i32() ),
4583 vec!( ty::mk_f64(), ty::mk_i32() ),
4586 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4587 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4588 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4589 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4592 vec!( ty::mk_f32(), ty::mk_f32() ),
4597 vec!( ty::mk_f64(), ty::mk_f64() ),
4600 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4601 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4602 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4603 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4604 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4605 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4606 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4607 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4608 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4609 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4612 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4617 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4620 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4621 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4622 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4623 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4624 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4625 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4626 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4627 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4628 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4629 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4630 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4631 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4632 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4633 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4634 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4635 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4636 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4637 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4638 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4639 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4640 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4641 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4642 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4643 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4644 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4645 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4646 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4647 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4648 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4649 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4650 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4653 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4655 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4657 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4658 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4659 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4661 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4662 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4663 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4665 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4666 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4667 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4669 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4670 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4671 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4673 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4674 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4675 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4677 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4678 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4679 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4681 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4682 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4683 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4685 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4686 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4687 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4690 tcx.sess.span_err(it.span,
4691 format!("unrecognized intrinsic function: `{}`",
4692 *other).as_slice());
4697 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4698 fn_style: ast::UnsafeFn,
4699 abi: abi::RustIntrinsic,
4707 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4708 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4709 if i_n_tps != n_tps {
4710 tcx.sess.span_err(it.span,
4711 format!("intrinsic has wrong number of type \
4712 parameters: found {}, expected {}",
4716 require_same_types(tcx,
4723 format!("intrinsic has wrong type: expected `{}`",
4724 ppaux::ty_to_str(ccx.tcx, fty))