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::lang_items::IteratorItem;
83 use middle::pat_util::pat_id_map;
86 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
87 use middle::ty::{FnSig, VariantInfo};
88 use middle::ty::{Polytype};
89 use middle::ty::{ParamTy, Disr, ExprTyProvider};
91 use middle::ty_fold::TypeFolder;
92 use middle::typeck::astconv::AstConv;
93 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
94 use middle::typeck::astconv;
95 use middle::typeck::check::_match::pat_ctxt;
96 use middle::typeck::check::method::{AutoderefReceiver};
97 use middle::typeck::check::method::{AutoderefReceiverFlag};
98 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
99 use middle::typeck::check::method::{DontAutoderefReceiver};
100 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
101 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
102 use middle::typeck::check::regionmanip::relate_free_regions;
103 use middle::typeck::check::vtable::VtableContext;
104 use middle::typeck::CrateCtxt;
105 use middle::typeck::infer::{resolve_type, force_tvar};
106 use middle::typeck::infer;
107 use middle::typeck::rscope::RegionScope;
108 use middle::typeck::{lookup_def_ccx};
109 use middle::typeck::no_params;
110 use middle::typeck::{require_same_types, vtable_map};
111 use middle::typeck::{MethodCall, MethodMap};
112 use middle::typeck::{TypeAndSubsts};
113 use middle::lang_items::TypeIdLangItem;
115 use util::common::{block_query, indenter, loop_query};
117 use util::ppaux::{UserString, Repr};
118 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
120 use std::cell::{Cell, RefCell};
121 use std::collections::HashMap;
122 use std::mem::replace;
126 use syntax::ast::{Provided, Required};
129 use syntax::ast_util::{local_def, PostExpansionMethod};
130 use syntax::ast_util;
132 use syntax::codemap::Span;
134 use syntax::owned_slice::OwnedSlice;
135 use syntax::parse::token;
136 use syntax::print::pprust;
138 use syntax::visit::Visitor;
149 /// Fields that are part of a `FnCtxt` which are inherited by
150 /// closures defined within the function. For example:
153 /// bar(proc() { ... })
156 /// Here, the function `foo()` and the closure passed to
157 /// `bar()` will each have their own `FnCtxt`, but they will
158 /// share the inherited fields.
159 pub struct Inherited<'a> {
160 infcx: infer::InferCtxt<'a>,
161 locals: RefCell<NodeMap<ty::t>>,
162 param_env: ty::ParameterEnvironment,
165 node_types: RefCell<NodeMap<ty::t>>,
166 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
167 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
168 method_map: MethodMap,
169 vtable_map: vtable_map,
170 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
171 unboxed_closure_types: RefCell<DefIdMap<ty::ClosureTy>>,
174 /// When type-checking an expression, we propagate downward
175 /// whatever type hint we are able in the form of an `Expectation`.
177 /// We know nothing about what type this expression should have.
180 /// This expression should have the type given (or some subtype)
181 ExpectHasType(ty::t),
183 /// This expression will be cast to the `ty::t`
184 ExpectCastableToType(ty::t),
188 pub struct FnStyleState {
189 pub def: ast::NodeId,
190 pub fn_style: ast::FnStyle,
195 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
196 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
199 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
200 match self.fn_style {
201 // If this unsafe, then if the outer function was already marked as
202 // unsafe we shouldn't attribute the unsafe'ness to the block. This
203 // way the block can be warned about instead of ignoring this
204 // extraneous block (functions are never warned about).
205 ast::UnsafeFn if self.from_fn => *self,
208 let (fn_style, def) = match blk.rules {
209 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
210 ast::DefaultBlock => (fn_style, self.def),
212 FnStyleState{ def: def,
220 /// Whether `check_binop` is part of an assignment or not.
221 /// Used to know whether we allow user overloads and to print
222 /// better messages on error.
223 #[deriving(PartialEq)]
224 enum IsBinopAssignment{
230 pub struct FnCtxt<'a> {
231 // This flag is set to true if, during the writeback phase, we encounter
232 // a type error in this function.
233 writeback_errors: Cell<bool>,
235 // Number of errors that had been reported when we started
236 // checking this function. On exit, if we find that *more* errors
237 // have been reported, we will skip regionck and other work that
238 // expects the types within the function to be consistent.
239 err_count_on_creation: uint,
242 ps: RefCell<FnStyleState>,
244 // Sometimes we generate region pointers where the precise region
245 // to use is not known. For example, an expression like `&x.f`
246 // where `x` is of type `@T`: in this case, we will be rooting
247 // `x` onto the stack frame, and we could choose to root it until
248 // the end of (almost) any enclosing block or expression. We
249 // want to pick the narrowest block that encompasses all uses.
251 // What we do in such cases is to generate a region variable with
252 // `region_lb` as a lower bound. The regionck pass then adds
253 // other constraints based on how the variable is used and region
254 // inference selects the ultimate value. Finally, borrowck is
255 // charged with guaranteeing that the value whose address was taken
256 // can actually be made to live as long as it needs to live.
257 region_lb: Cell<ast::NodeId>,
259 inh: &'a Inherited<'a>,
261 ccx: &'a CrateCtxt<'a>,
264 impl<'a> Inherited<'a> {
265 fn new(tcx: &'a ty::ctxt,
266 param_env: ty::ParameterEnvironment)
269 infcx: infer::new_infer_ctxt(tcx),
270 locals: RefCell::new(NodeMap::new()),
271 param_env: param_env,
272 node_types: RefCell::new(NodeMap::new()),
273 item_substs: RefCell::new(NodeMap::new()),
274 adjustments: RefCell::new(NodeMap::new()),
275 method_map: RefCell::new(FnvHashMap::new()),
276 vtable_map: RefCell::new(FnvHashMap::new()),
277 upvar_borrow_map: RefCell::new(HashMap::new()),
278 unboxed_closure_types: RefCell::new(DefIdMap::new()),
283 // Used by check_const and check_enum_variants
284 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
285 inh: &'a Inherited<'a>,
287 region_bnd: ast::NodeId)
290 writeback_errors: Cell::new(false),
291 err_count_on_creation: ccx.tcx.sess.err_count(),
293 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
294 region_lb: Cell::new(region_bnd),
300 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
301 // It's kind of a kludge to manufacture a fake function context
302 // and statement context, but we might as well do write the code only once
303 let param_env = ty::ParameterEnvironment {
304 free_substs: subst::Substs::empty(),
305 bounds: subst::VecPerParamSpace::empty()
307 Inherited::new(ccx.tcx, param_env)
310 impl<'a> ExprTyProvider for FnCtxt<'a> {
311 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
315 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
320 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
322 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
323 fn visit_item(&mut self, i: &ast::Item, _: ()) {
324 check_item(self.ccx, i);
325 visit::walk_item(self, i, ());
329 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
331 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
332 fn visit_item(&mut self, i: &ast::Item, _: ()) {
333 check_item_sized(self.ccx, i);
334 visit::walk_item(self, i, ());
338 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
339 let mut visit = CheckItemTypesVisitor { ccx: ccx };
340 visit::walk_crate(&mut visit, krate, ());
342 ccx.tcx.sess.abort_if_errors();
344 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
345 visit::walk_crate(&mut visit, krate, ());
348 fn check_bare_fn(ccx: &CrateCtxt,
353 param_env: ty::ParameterEnvironment) {
354 // Compute the fty from point of view of inside fn
355 // (replace any type-scheme with a type)
356 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
358 match ty::get(fty).sty {
359 ty::ty_bare_fn(ref fn_ty) => {
360 let inh = Inherited::new(ccx.tcx, param_env);
361 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
362 decl, id, body, &inh);
364 vtable::resolve_in_block(&fcx, body);
365 regionck::regionck_fn(&fcx, body);
366 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
368 _ => ccx.tcx.sess.impossible_case(body.span,
369 "check_bare_fn: function type expected")
373 struct GatherLocalsVisitor<'a> {
377 impl<'a> GatherLocalsVisitor<'a> {
378 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
381 // infer the variable's type
382 let var_id = self.fcx.infcx().next_ty_var_id();
383 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
384 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
387 // take type that the user specified
388 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
394 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
395 // Add explicitly-declared locals.
396 fn visit_local(&mut self, local: &ast::Local, _: ()) {
397 let o_ty = match local.ty.node {
398 ast::TyInfer => None,
399 _ => Some(self.fcx.to_ty(&*local.ty))
401 self.assign(local.id, o_ty);
402 debug!("Local variable {} is assigned type {}",
403 self.fcx.pat_to_string(&*local.pat),
404 self.fcx.infcx().ty_to_string(
405 self.fcx.inh.locals.borrow().get_copy(&local.id)));
406 visit::walk_local(self, local, ());
409 // Add pattern bindings.
410 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
412 ast::PatIdent(_, ref path1, _)
413 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
414 self.assign(p.id, None);
415 debug!("Pattern binding {} is assigned to {}",
416 token::get_ident(path1.node),
417 self.fcx.infcx().ty_to_string(
418 self.fcx.inh.locals.borrow().get_copy(&p.id)));
422 visit::walk_pat(self, p, ());
426 fn visit_block(&mut self, b: &ast::Block, _: ()) {
427 // non-obvious: the `blk` variable maps to region lb, so
428 // we have to keep this up-to-date. This
429 // is... unfortunate. It'd be nice to not need this.
430 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
433 // Don't descend into fns and items
434 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
435 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
436 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
440 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
441 fn_style: ast::FnStyle,
446 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
449 * Helper used by check_bare_fn and check_expr_fn. Does the
450 * grungy work of checking a function body and returns the
451 * function context used for that purpose, since in the case of a
452 * fn item there is still a bit more to do.
455 * - inherited: other fields inherited from the enclosing fn (if any)
459 let err_count_on_creation = tcx.sess.err_count();
461 // First, we have to replace any bound regions in the fn type with free ones.
462 // The free region references will be bound the node_id of the body block.
463 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
464 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
467 relate_free_regions(tcx, &fn_sig);
469 let arg_tys = fn_sig.inputs.as_slice();
470 let ret_ty = fn_sig.output;
472 debug!("check_fn(arg_tys={}, ret_ty={})",
476 // Create the function context. This is either derived from scratch or,
477 // in the case of function expressions, based on the outer context.
479 writeback_errors: Cell::new(false),
480 err_count_on_creation: err_count_on_creation,
482 ps: RefCell::new(FnStyleState::function(fn_style, id)),
483 region_lb: Cell::new(body.id),
490 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
491 // Add formal parameters.
492 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
493 // Create type variables for each argument.
494 pat_util::pat_bindings(&tcx.def_map,
496 |_bm, pat_id, _sp, _path| {
497 visit.assign(pat_id, None);
500 // Check the pattern.
503 map: pat_id_map(&tcx.def_map, &*input.pat),
505 _match::check_pat(&pcx, &*input.pat, *arg_ty);
508 visit.visit_block(body, ());
511 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
513 // We unify the tail expr's type with the
514 // function result type, if there is a tail expr.
516 Some(ref tail_expr) => {
517 // Special case: we print a special error if there appears
518 // to be do-block/for-loop confusion
519 demand::suptype_with_fn(&fcx, tail_expr.span, false,
520 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
522 fcx.report_mismatched_return_types(sp, e, a, s);
528 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
529 fcx.write_ty(input.id, *arg);
535 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
536 assert!(field.id.krate == ast::LOCAL_CRATE);
537 let item = match tcx.map.find(struct_id.node) {
538 Some(ast_map::NodeItem(item)) => item,
539 None => fail!("node not in ast map: {}", struct_id.node),
540 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
544 ast::ItemStruct(struct_def, _) => {
545 match struct_def.fields.iter().find(|f| match f.node.kind {
546 ast::NamedField(ident, _) => ident.name == field.name,
552 .bug(format!("Could not find field {}",
553 token::get_name(field.name)).as_slice())
557 _ => tcx.sess.bug("Field found outside of a struct?"),
561 // Check struct fields are uniquely named wrt parents.
562 fn check_for_field_shadowing(tcx: &ty::ctxt,
564 let struct_fields = tcx.struct_fields.borrow();
565 let fields = struct_fields.get(&id);
567 let superstructs = tcx.superstructs.borrow();
568 let super_struct = superstructs.get(&id);
569 match *super_struct {
571 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
572 for f in fields.iter() {
573 match super_fields.iter().find(|sf| f.name == sf.name) {
574 Some(prev_field) => {
575 span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
576 "field `{}` hides field declared in super-struct",
577 token::get_name(f.name));
578 span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
579 "previously declared here");
589 fn check_fields_sized(tcx: &ty::ctxt,
590 struct_def: &ast::StructDef) {
591 let len = struct_def.fields.len();
595 for f in struct_def.fields.slice_to(len - 1).iter() {
596 let t = ty::node_id_to_type(tcx, f.node.id);
597 if !ty::type_is_sized(tcx, t) {
599 ast::NamedField(ident, _) => {
600 span_err!(tcx.sess, f.span, E0042,
601 "type `{}` is dynamically sized. \
602 dynamically sized types may only \
603 appear as the type of the final \
605 token::get_ident(ident));
607 ast::UnnamedField(_) => {
608 span_err!(tcx.sess, f.span, E0043,
609 "dynamically sized type in field");
616 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
619 check_representable(tcx, span, id, "struct");
620 check_instantiable(tcx, span, id);
622 // Check there are no overlapping fields in super-structs
623 check_for_field_shadowing(tcx, local_def(id));
625 if ty::lookup_simd(tcx, local_def(id)) {
626 check_simd(tcx, span, id);
630 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
631 debug!("check_item(it.id={}, it.ident={})",
633 ty::item_path_str(ccx.tcx, local_def(it.id)));
634 let _indenter = indenter();
637 ast::ItemEnum(ref enum_definition, _) => {
638 check_enum_variants_sized(ccx,
639 enum_definition.variants.as_slice());
641 ast::ItemStruct(..) => {
642 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
648 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
649 debug!("check_item(it.id={}, it.ident={})",
651 ty::item_path_str(ccx.tcx, local_def(it.id)));
652 let _indenter = indenter();
655 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
656 ast::ItemEnum(ref enum_definition, _) => {
657 check_enum_variants(ccx,
659 enum_definition.variants.as_slice(),
662 ast::ItemFn(ref decl, _, _, _, ref body) => {
663 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
665 let param_env = ty::construct_parameter_environment(ccx.tcx,
669 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
671 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
672 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
674 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
676 check_method_body(ccx, &impl_pty.generics, &**m);
679 match *opt_trait_ref {
680 Some(ref ast_trait_ref) => {
682 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
683 check_impl_methods_against_trait(ccx,
688 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
694 ast::ItemTrait(_, _, _, ref trait_methods) => {
695 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
696 for trait_method in (*trait_methods).iter() {
697 match *trait_method {
699 // Nothing to do, since required methods don't have
703 check_method_body(ccx, &trait_def.generics, &*m);
708 ast::ItemStruct(..) => {
709 check_struct(ccx, it.id, it.span);
711 ast::ItemTy(ref t, ref generics) => {
712 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
713 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
715 ast::ItemForeignMod(ref m) => {
716 if m.abi == abi::RustIntrinsic {
717 for item in m.items.iter() {
718 check_intrinsic_type(ccx, &**item);
721 for item in m.items.iter() {
722 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
723 if !pty.generics.types.is_empty() {
724 span_err!(ccx.tcx.sess, item.span, E0044,
725 "foreign items may not have type parameters");
729 ast::ForeignItemFn(ref fn_decl, _) => {
730 if fn_decl.variadic && m.abi != abi::C {
731 span_err!(ccx.tcx.sess, item.span, E0045,
732 "variadic function must have C calling convention");
740 _ => {/* nothing to do */ }
744 fn check_method_body(ccx: &CrateCtxt,
745 item_generics: &ty::Generics,
746 method: &ast::Method) {
748 * Type checks a method body.
751 * - `item_generics`: generics defined on the impl/trait that contains
753 * - `self_bound`: bound for the `Self` type parameter, if any
754 * - `method`: the method definition
757 debug!("check_method_body(item_generics={}, method.id={})",
758 item_generics.repr(ccx.tcx),
760 let method_def_id = local_def(method.id);
761 let method_ty = ty::method(ccx.tcx, method_def_id);
762 let method_generics = &method_ty.generics;
764 let param_env = ty::construct_parameter_environment(ccx.tcx,
766 method.pe_body().id);
768 let fty = ty::node_id_to_type(ccx.tcx, method.id);
771 &*method.pe_fn_decl(),
778 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
780 ast_trait_ref: &ast::TraitRef,
781 impl_trait_ref: &ty::TraitRef,
782 impl_methods: &[Gc<ast::Method>]) {
783 // Locate trait methods
785 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
787 // Check existing impl methods to see if they are both present in trait
788 // and compatible with trait signature
789 for impl_method in impl_methods.iter() {
790 let impl_method_def_id = local_def(impl_method.id);
791 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
793 // If this is an impl of a trait method, find the corresponding
794 // method definition in the trait.
795 let opt_trait_method_ty =
796 trait_methods.iter().
797 find(|tm| tm.ident.name == impl_method_ty.ident.name);
798 match opt_trait_method_ty {
799 Some(trait_method_ty) => {
800 compare_impl_method(ccx.tcx,
803 impl_method.pe_body().id,
805 &impl_trait_ref.substs);
808 // This is span_bug as it should have already been caught in resolve.
812 "method `{}` is not a member of trait `{}`",
813 token::get_ident(impl_method_ty.ident),
814 pprust::path_to_string(&ast_trait_ref.path)).as_slice());
819 // Check for missing methods from trait
820 let provided_methods = ty::provided_trait_methods(tcx,
821 impl_trait_ref.def_id);
822 let mut missing_methods = Vec::new();
823 for trait_method in trait_methods.iter() {
825 impl_methods.iter().any(
826 |m| m.pe_ident().name == trait_method.ident.name);
828 provided_methods.iter().any(
829 |m| m.ident.name == trait_method.ident.name);
830 if !is_implemented && !is_provided {
831 missing_methods.push(
832 format!("`{}`", token::get_ident(trait_method.ident)));
836 if !missing_methods.is_empty() {
837 span_err!(tcx.sess, impl_span, E0046,
838 "not all trait methods implemented, missing: {}",
839 missing_methods.connect(", "));
844 * Checks that a method from an impl/class conforms to the signature of
845 * the same method as declared in the trait.
849 * - impl_generics: the generics declared on the impl itself (not the method!)
850 * - impl_m: type of the method we are checking
851 * - impl_m_span: span to use for reporting errors
852 * - impl_m_body_id: id of the method body
853 * - trait_m: the method in the trait
854 * - trait_to_impl_substs: the substitutions used on the type of the trait
856 fn compare_impl_method(tcx: &ty::ctxt,
859 impl_m_body_id: ast::NodeId,
860 trait_m: &ty::Method,
861 trait_to_impl_substs: &subst::Substs) {
862 debug!("compare_impl_method()");
863 let infcx = infer::new_infer_ctxt(tcx);
865 // Try to give more informative error messages about self typing
866 // mismatches. Note that any mismatch will also be detected
867 // below, where we construct a canonical function type that
868 // includes the self parameter as a normal parameter. It's just
869 // that the error messages you get out of this code are a bit more
870 // inscrutable, particularly for cases where one method has no
872 match (&trait_m.explicit_self, &impl_m.explicit_self) {
873 (&ty::StaticExplicitSelfCategory,
874 &ty::StaticExplicitSelfCategory) => {}
875 (&ty::StaticExplicitSelfCategory, _) => {
878 format!("method `{}` has a `{}` declaration in the impl, \
879 but not in the trait",
880 token::get_ident(trait_m.ident),
881 ppaux::explicit_self_category_to_str(
882 &impl_m.explicit_self)).as_slice());
885 (_, &ty::StaticExplicitSelfCategory) => {
888 format!("method `{}` has a `{}` declaration in the trait, \
889 but not in the impl",
890 token::get_ident(trait_m.ident),
891 ppaux::explicit_self_category_to_str(
892 &trait_m.explicit_self)).as_slice());
896 // Let the type checker catch other errors below
900 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
901 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
902 if num_impl_m_type_params != num_trait_m_type_params {
903 span_err!(tcx.sess, impl_m_span, E0049,
904 "method `{}` has {} type parameter{} \
905 but its trait declaration has {} type parameter{}",
906 token::get_ident(trait_m.ident),
907 num_impl_m_type_params,
908 if num_impl_m_type_params == 1 {""} else {"s"},
909 num_trait_m_type_params,
910 if num_trait_m_type_params == 1 {""} else {"s"});
914 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
915 span_err!(tcx.sess, impl_m_span, E0050,
916 "method `{}` has {} parameter{} \
917 but the declaration in trait `{}` has {}",
918 token::get_ident(trait_m.ident),
919 impl_m.fty.sig.inputs.len(),
920 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
921 ty::item_path_str(tcx, trait_m.def_id),
922 trait_m.fty.sig.inputs.len());
926 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
927 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
929 // This code is best explained by example. Consider a trait:
932 // fn method<'a,M>(t: T, m: &'a M) -> Self;
937 // impl<'i, U> Trait<&'i U> for Foo {
938 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
941 // We wish to decide if those two method types are compatible.
943 // We start out with trait_to_impl_substs, that maps the trait type
944 // parameters to impl type parameters:
946 // trait_to_impl_substs = {T => &'i U, Self => Foo}
948 // We create a mapping `dummy_substs` that maps from the impl type
949 // parameters to fresh types and regions. For type parameters,
950 // this is the identity transform, but we could as well use any
951 // skolemized types. For regions, we convert from bound to free
952 // regions (Note: but only early-bound regions, i.e., those
953 // declared on the impl or used in type parameter bounds).
955 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
957 // Now we can apply skol_substs to the type of the impl method
958 // to yield a new function type in terms of our fresh, skolemized
961 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
963 // We now want to extract and substitute the type of the *trait*
964 // method and compare it. To do so, we must create a compound
965 // substitution by combining trait_to_impl_substs and
966 // impl_to_skol_substs, and also adding a mapping for the method
967 // type parameters. We extend the mapping to also include
968 // the method parameters.
970 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
972 // Applying this to the trait method type yields:
974 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
976 // This type is also the same but the name of the bound region ('a
977 // vs 'b). However, the normal subtyping rules on fn types handle
978 // this kind of equivalency just fine.
980 // Create mapping from impl to skolemized.
982 impl_m.generics.types.map(
983 |d| ty::mk_param_from_def(tcx, d));
985 impl_m.generics.regions.map(
986 |l| ty::free_region_from_def(impl_m_body_id, l));
987 let impl_to_skol_substs =
988 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
990 // Compute skolemized form of impl method ty.
991 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
992 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
994 // Compute skolemized form of trait method ty.
995 let trait_to_skol_substs =
997 .subst(tcx, &impl_to_skol_substs)
998 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
999 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
1000 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1001 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1004 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1005 // Check that the impl does not require any builtin-bounds
1006 // that the trait does not guarantee:
1008 impl_param_def.bounds.builtin_bounds -
1009 trait_param_def.bounds.builtin_bounds;
1010 if !extra_bounds.is_empty() {
1011 span_err!(tcx.sess, impl_m_span, E0051,
1012 "in method `{}`, type parameter {} requires `{}`, \
1013 which is not required by the corresponding type parameter \
1014 in the trait declaration",
1015 token::get_ident(trait_m.ident),
1017 extra_bounds.user_string(tcx));
1021 // Check that the trait bounds of the trait imply the bounds of its
1024 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1025 // traits, but I doubt that'll be wanted often, so meh.
1026 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1027 let impl_trait_bound =
1028 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1031 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1033 trait_bound.subst(tcx, &trait_to_skol_substs);
1034 let infcx = infer::new_infer_ctxt(tcx);
1035 match infer::mk_sub_trait_refs(&infcx,
1037 infer::Misc(impl_m_span),
1039 impl_trait_bound.clone()) {
1049 span_err!(tcx.sess, impl_m_span, E0052,
1050 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1051 required by the corresponding type parameter in the trait declaration",
1052 token::get_ident(trait_m.ident),
1054 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1059 // Check the impl method type IM is a subtype of the trait method
1060 // type TM. To see why this makes sense, think of a vtable. The
1061 // expected type of the function pointers in the vtable is the
1062 // type TM of the trait method. The actual type will be the type
1063 // IM of the impl method. Because we know that IM <: TM, that
1064 // means that anywhere a TM is expected, a IM will do instead. In
1065 // other words, anyone expecting to call a method with the type
1066 // from the trait, can safely call a method with the type from the
1068 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1069 impl_fty, trait_fty) {
1072 span_err!(tcx.sess, impl_m_span, E0053,
1073 "method `{}` has an incompatible type for trait: {}",
1074 token::get_ident(trait_m.ident),
1075 ty::type_err_to_str(tcx, terr));
1076 ty::note_and_explain_type_err(tcx, terr);
1080 // Finally, resolve all regions. This catches wily misuses of lifetime
1082 infcx.resolve_regions_and_report_errors();
1085 fn check_cast(fcx: &FnCtxt,
1090 // Find the type of `e`. Supply hints based on the type we are casting to,
1092 let t_1 = fcx.to_ty(t);
1093 let t_1 = structurally_resolved_type(fcx, span, t_1);
1095 if ty::type_is_scalar(t_1) {
1096 // Supply the type as a hint so as to influence integer
1097 // literals and other things that might care.
1098 check_expr_with_hint(fcx, e, t_1)
1103 let t_e = fcx.expr_ty(e);
1105 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1106 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1108 if ty::type_is_error(t_e) {
1109 fcx.write_error(id);
1112 if ty::type_is_bot(t_e) {
1117 if ty::type_is_trait(t_1) {
1118 // This will be looked up later on.
1119 fcx.write_ty(id, t_1);
1123 let t_1 = structurally_resolved_type(fcx, span, t_1);
1124 let t_e = structurally_resolved_type(fcx, span, t_e);
1126 if ty::type_is_nil(t_e) {
1127 fcx.type_error_message(span, |actual| {
1128 format!("cast from nil: `{}` as `{}`",
1130 fcx.infcx().ty_to_string(t_1))
1132 } else if ty::type_is_nil(t_1) {
1133 fcx.type_error_message(span, |actual| {
1134 format!("cast to nil: `{}` as `{}`",
1136 fcx.infcx().ty_to_string(t_1))
1140 let t_1_is_scalar = ty::type_is_scalar(t_1);
1141 let t_1_is_char = ty::type_is_char(t_1);
1142 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1143 let t_1_is_float = ty::type_is_floating_point(t_1);
1145 // casts to scalars other than `char` and `bare fn` are trivial
1146 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1147 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1149 fcx.type_error_message(span, |actual| {
1150 format!("illegal cast; cast through an \
1151 integer first: `{}` as `{}`",
1153 fcx.infcx().ty_to_string(t_1))
1156 // casts from C-like enums are allowed
1157 } else if t_1_is_char {
1158 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1159 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1160 fcx.type_error_message(span, |actual| {
1161 format!("only `u8` can be cast as \
1162 `char`, not `{}`", actual)
1165 } else if ty::get(t_1).sty == ty::ty_bool {
1166 span_err!(fcx.tcx().sess, span, E0054,
1167 "cannot cast as `bool`, compare with zero instead");
1168 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1169 fn types_compatible(fcx: &FnCtxt, sp: Span,
1170 t1: ty::t, t2: ty::t) -> bool {
1171 if !ty::type_is_vec(t1) {
1172 // If the type being casted from is not a vector, this special
1173 // case does not apply.
1176 if ty::type_needs_infer(t2) {
1177 // This prevents this special case from going off when casting
1178 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1183 let el = ty::sequence_element_type(fcx.tcx(), t1);
1184 infer::mk_eqty(fcx.infcx(),
1191 // Due to the limitations of LLVM global constants,
1192 // region pointers end up pointing at copies of
1193 // vector elements instead of the original values.
1194 // To allow unsafe pointers to work correctly, we
1195 // need to special-case obtaining an unsafe pointer
1196 // from a region pointer to a vector.
1198 /* this cast is only allowed from &[T] to *T or
1200 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1201 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1202 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1203 if types_compatible(fcx, e.span, mt1, mt2) => {
1204 /* this case is allowed */
1207 demand::coerce(fcx, e.span, t_1, &*e);
1210 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1212 If more type combinations should be supported than are
1213 supported here, then file an enhancement issue and
1214 record the issue number in this comment.
1216 fcx.type_error_message(span, |actual| {
1217 format!("non-scalar cast: `{}` as `{}`",
1219 fcx.infcx().ty_to_string(t_1))
1221 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1222 fcx.type_error_message(span, |actual| {
1223 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1226 fcx.infcx().ty_to_string(t_1))
1230 fcx.write_ty(id, t_1);
1233 impl<'a> AstConv for FnCtxt<'a> {
1234 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1236 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1237 ty::lookup_item_type(self.tcx(), id)
1240 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1241 ty::lookup_trait_def(self.tcx(), id)
1244 fn ty_infer(&self, _span: Span) -> ty::t {
1245 self.infcx().next_ty_var()
1249 impl<'a> FnCtxt<'a> {
1250 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1254 pub fn err_count_since_creation(&self) -> uint {
1255 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1258 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1260 infcx: self.infcx(),
1261 param_env: &self.inh.param_env,
1262 unboxed_closure_types: &self.inh.unboxed_closure_types,
1267 impl<'a> RegionScope for infer::InferCtxt<'a> {
1268 fn anon_regions(&self, span: Span, count: uint)
1269 -> Result<Vec<ty::Region> , ()> {
1270 Ok(Vec::from_fn(count, |_| {
1271 self.next_region_var(infer::MiscVariable(span))
1276 impl<'a> FnCtxt<'a> {
1277 pub fn tag(&self) -> String {
1278 format!("{}", self as *const FnCtxt)
1281 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1282 match self.inh.locals.borrow().find(&nid) {
1285 self.tcx().sess.span_bug(
1287 format!("no type for local variable {:?}",
1294 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1295 debug!("write_ty({}, {}) in fcx {}",
1296 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1297 self.inh.node_types.borrow_mut().insert(node_id, ty);
1300 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1301 if !substs.substs.is_noop() {
1302 debug!("write_substs({}, {}) in fcx {}",
1304 substs.repr(self.tcx()),
1307 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1311 pub fn write_ty_substs(&self,
1312 node_id: ast::NodeId,
1314 substs: ty::ItemSubsts) {
1315 let ty = ty.subst(self.tcx(), &substs.substs);
1316 self.write_ty(node_id, ty);
1317 self.write_substs(node_id, substs);
1320 pub fn write_autoderef_adjustment(&self,
1321 node_id: ast::NodeId,
1323 if derefs == 0 { return; }
1324 self.write_adjustment(
1326 ty::AutoDerefRef(ty::AutoDerefRef {
1332 pub fn write_adjustment(&self,
1333 node_id: ast::NodeId,
1334 adj: ty::AutoAdjustment) {
1335 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1336 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1339 pub fn write_nil(&self, node_id: ast::NodeId) {
1340 self.write_ty(node_id, ty::mk_nil());
1342 pub fn write_bot(&self, node_id: ast::NodeId) {
1343 self.write_ty(node_id, ty::mk_bot());
1345 pub fn write_error(&self, node_id: ast::NodeId) {
1346 self.write_ty(node_id, ty::mk_err());
1349 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1350 ast_ty_to_ty(self, self.infcx(), ast_t)
1353 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1354 pat.repr(self.tcx())
1357 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1358 match self.inh.node_types.borrow().find(&ex.id) {
1361 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1362 self.tag()).as_slice());
1367 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1368 match self.inh.node_types.borrow().find(&id) {
1371 self.tcx().sess.bug(
1372 format!("no type for node {}: {} in fcx {}",
1373 id, self.tcx().map.node_to_string(id),
1374 self.tag()).as_slice());
1379 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1380 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1381 Some(method) => method.substs.clone(),
1383 self.tcx().sess.bug(
1384 format!("no method entry for node {}: {} in fcx {}",
1385 id, self.tcx().map.node_to_string(id),
1386 self.tag()).as_slice());
1391 pub fn opt_node_ty_substs(&self,
1393 f: |&ty::ItemSubsts|) {
1394 match self.inh.item_substs.borrow().find(&id) {
1400 pub fn mk_subty(&self,
1401 a_is_expected: bool,
1402 origin: infer::TypeOrigin,
1405 -> Result<(), ty::type_err> {
1406 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1409 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1410 -> Result<(), ty::type_err> {
1411 infer::can_mk_subty(self.infcx(), sub, sup)
1414 pub fn mk_assignty(&self,
1418 -> Result<(), ty::type_err> {
1419 match infer::mk_coercety(self.infcx(),
1421 infer::ExprAssignable(expr.span),
1425 Err(ref e) => Err((*e)),
1426 Ok(Some(adjustment)) => {
1427 self.write_adjustment(expr.id, adjustment);
1433 pub fn mk_eqty(&self,
1434 a_is_expected: bool,
1435 origin: infer::TypeOrigin,
1438 -> Result<(), ty::type_err> {
1439 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1442 pub fn mk_subr(&self,
1443 a_is_expected: bool,
1444 origin: infer::SubregionOrigin,
1447 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1450 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1451 let old_region_lb = self.region_lb.get();
1452 self.region_lb.set(lb);
1454 self.region_lb.set(old_region_lb);
1458 pub fn type_error_message(&self,
1460 mk_msg: |String| -> String,
1462 err: Option<&ty::type_err>) {
1463 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1466 pub fn report_mismatched_return_types(&self,
1470 err: &ty::type_err) {
1472 if ty::type_is_error(e) || ty::type_is_error(a) {
1475 self.infcx().report_mismatched_types(sp, e, a, err)
1478 pub fn report_mismatched_types(&self,
1482 err: &ty::type_err) {
1483 self.infcx().report_mismatched_types(sp, e, a, err)
1487 pub enum LvaluePreference {
1492 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1493 expr_id: Option<ast::NodeId>,
1494 mut lvalue_pref: LvaluePreference,
1495 should_stop: |ty::t, uint| -> Option<T>)
1496 -> (ty::t, uint, Option<T>) {
1498 * Executes an autoderef loop for the type `t`. At each step, invokes
1499 * `should_stop` to decide whether to terminate the loop. Returns
1500 * the final type and number of derefs that it performed.
1502 * Note: this method does not modify the adjustments table. The caller is
1503 * responsible for inserting an AutoAdjustment record into the `fcx`
1504 * using one of the suitable methods.
1507 let mut t = base_ty;
1508 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1509 let resolved_t = structurally_resolved_type(fcx, sp, t);
1511 match should_stop(resolved_t, autoderefs) {
1512 Some(x) => return (resolved_t, autoderefs, Some(x)),
1516 // Otherwise, deref if type is derefable:
1517 let mt = match ty::deref(resolved_t, false) {
1518 Some(mt) => Some(mt),
1520 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1521 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1527 if mt.mutbl == ast::MutImmutable {
1528 lvalue_pref = NoPreference;
1531 None => return (resolved_t, autoderefs, None)
1535 // We've reached the recursion limit, error gracefully.
1536 span_err!(fcx.tcx().sess, sp, E0055,
1537 "reached the recursion limit while auto-dereferencing {}",
1538 base_ty.repr(fcx.tcx()));
1539 (ty::mk_err(), 0, None)
1542 /// Attempts to resolve a call expression as an overloaded call.
1543 fn try_overloaded_call(fcx: &FnCtxt,
1544 call_expression: &ast::Expr,
1545 callee: Gc<ast::Expr>,
1547 args: &[Gc<ast::Expr>])
1549 // Bail out if the callee is a bare function or a closure. We check those
1551 match *structure_of(fcx, callee.span, callee_type) {
1552 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
1556 // Try `FnOnce`, then `FnMut`, then `Fn`.
1557 for &(maybe_function_trait, method_name) in [
1558 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1559 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1560 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1562 let function_trait = match maybe_function_trait {
1564 Some(function_trait) => function_trait,
1566 let method_callee = match method::lookup_in_trait(
1568 call_expression.span,
1574 DontAutoderefReceiver,
1575 IgnoreStaticMethods) {
1577 Some(method_callee) => method_callee,
1579 let method_call = MethodCall::expr(call_expression.id);
1580 let output_type = check_method_argument_types(fcx,
1581 call_expression.span,
1587 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1588 write_call(fcx, call_expression, output_type);
1590 if !fcx.tcx().sess.features.overloaded_calls.get() {
1591 span_err!(fcx.tcx().sess, call_expression.span, E0056,
1592 "overloaded calls are experimental");
1593 span_note!(fcx.tcx().sess, call_expression.span,
1594 "add `#[feature(overloaded_calls)]` to \
1595 the crate attributes to enable");
1604 fn try_overloaded_deref(fcx: &FnCtxt,
1606 method_call: Option<MethodCall>,
1607 base_expr: Option<&ast::Expr>,
1609 lvalue_pref: LvaluePreference)
1611 // Try DerefMut first, if preferred.
1612 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1613 (PreferMutLvalue, Some(trait_did)) => {
1614 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1615 token::intern("deref_mut"), trait_did,
1616 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1621 // Otherwise, fall back to Deref.
1622 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1623 (None, Some(trait_did)) => {
1624 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1625 token::intern("deref"), trait_did,
1626 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1628 (method, _) => method
1633 let ref_ty = ty::ty_fn_ret(method.ty);
1635 Some(method_call) => {
1636 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1640 ty::deref(ref_ty, true)
1646 fn try_overloaded_index(fcx: &FnCtxt,
1647 method_call: Option<MethodCall>,
1649 base_expr: Gc<ast::Expr>,
1651 index_expr: Gc<ast::Expr>,
1652 lvalue_pref: LvaluePreference)
1654 // Try `IndexMut` first, if preferred.
1655 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1656 (PreferMutLvalue, Some(trait_did)) => {
1657 method::lookup_in_trait(fcx,
1660 token::intern("index_mut"),
1664 DontAutoderefReceiver,
1665 IgnoreStaticMethods)
1670 // Otherwise, fall back to `Index`.
1671 let method = match (method, fcx.tcx().lang_items.index_trait()) {
1672 (None, Some(trait_did)) => {
1673 method::lookup_in_trait(fcx,
1676 token::intern("index"),
1680 DontAutoderefReceiver,
1681 IgnoreStaticMethods)
1683 (method, _) => method,
1686 // Regardless of whether the lookup succeeds, check the method arguments
1687 // so that we have *some* type for each argument.
1688 let method_type = match method {
1689 Some(ref method) => method.ty,
1690 None => ty::mk_err()
1692 check_method_argument_types(fcx,
1696 [base_expr, index_expr],
1698 DontTupleArguments);
1702 let ref_ty = ty::ty_fn_ret(method.ty);
1704 Some(method_call) => {
1705 fcx.inh.method_map.borrow_mut().insert(method_call,
1710 ty::deref(ref_ty, true)
1716 /// Given the head of a `for` expression, looks up the `next` method in the
1717 /// `Iterator` trait. Fails if the expression does not implement `next`.
1719 /// The return type of this function represents the concrete element type
1720 /// `A` in the type `Iterator<A>` that the method returns.
1721 fn lookup_method_for_for_loop(fcx: &FnCtxt,
1722 iterator_expr: Gc<ast::Expr>,
1723 loop_id: ast::NodeId)
1725 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
1726 Ok(trait_did) => trait_did,
1727 Err(ref err_string) => {
1728 fcx.tcx().sess.span_err(iterator_expr.span,
1729 err_string.as_slice());
1734 let method = method::lookup_in_trait(fcx,
1736 Some(&*iterator_expr),
1737 token::intern("next"),
1739 fcx.expr_ty(&*iterator_expr),
1741 DontAutoderefReceiver,
1742 IgnoreStaticMethods);
1744 // Regardless of whether the lookup succeeds, check the method arguments
1745 // so that we have *some* type for each argument.
1746 let method_type = match method {
1747 Some(ref method) => method.ty,
1749 fcx.tcx().sess.span_err(iterator_expr.span,
1750 "`for` loop expression does not \
1751 implement the `Iterator` trait");
1755 let return_type = check_method_argument_types(fcx,
1761 DontTupleArguments);
1765 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
1768 // We expect the return type to be `Option` or something like it.
1769 // Grab the first parameter of its type substitution.
1770 let return_type = structurally_resolved_type(fcx,
1773 match ty::get(return_type).sty {
1774 ty::ty_enum(_, ref substs)
1775 if !substs.types.is_empty_in(subst::TypeSpace) => {
1776 *substs.types.get(subst::TypeSpace, 0)
1779 fcx.tcx().sess.span_err(iterator_expr.span,
1780 "`next` method of the `Iterator` \
1781 trait has an unexpected type");
1786 None => ty::mk_err()
1790 fn check_method_argument_types(fcx: &FnCtxt,
1792 method_fn_ty: ty::t,
1793 callee_expr: &ast::Expr,
1794 args: &[Gc<ast::Expr>],
1795 deref_args: DerefArgs,
1796 tuple_arguments: TupleArgumentsFlag)
1798 // HACK(eddyb) ignore provided self (it has special typeck rules).
1799 let args = if tuple_arguments == DontTupleArguments {
1804 if ty::type_is_error(method_fn_ty) {
1805 let err_inputs = err_args(args.len());
1806 check_argument_types(fcx,
1808 err_inputs.as_slice(),
1816 match ty::get(method_fn_ty).sty {
1817 ty::ty_bare_fn(ref fty) => {
1818 // HACK(eddyb) ignore self in the definition (see above).
1819 check_argument_types(fcx,
1821 fty.sig.inputs.slice_from(1),
1830 fcx.tcx().sess.span_bug(callee_expr.span,
1831 "method without bare fn type");
1837 fn check_argument_types(fcx: &FnCtxt,
1839 fn_inputs: &[ty::t],
1840 callee_expr: &ast::Expr,
1841 args: &[Gc<ast::Expr>],
1842 deref_args: DerefArgs,
1844 tuple_arguments: TupleArgumentsFlag) {
1847 * Generic function that factors out common logic from
1848 * function calls, method calls and overloaded operators.
1851 let tcx = fcx.ccx.tcx;
1853 // Grab the argument types, supplying fresh type variables
1854 // if the wrong number of arguments were supplied
1855 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1861 let expected_arg_count = fn_inputs.len();
1862 let formal_tys = if tuple_arguments == TupleArguments {
1863 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1864 match ty::get(tuple_type).sty {
1865 ty::ty_tup(ref arg_types) => {
1866 if arg_types.len() != args.len() {
1867 span_err!(tcx.sess, sp, E0057,
1868 "this function takes {} parameter{} but {} parameter{} supplied",
1870 if arg_types.len() == 1 {""} else {"s"},
1872 if args.len() == 1 {" was"} else {"s were"});
1873 err_args(args.len())
1875 (*arg_types).clone()
1879 if args.len() != 0 {
1880 span_err!(tcx.sess, sp, E0058,
1881 "this function takes 0 parameters but {} parameter{} supplied",
1883 if args.len() == 1 {" was"} else {"s were"});
1888 span_err!(tcx.sess, sp, E0059,
1889 "cannot use call notation; the first type parameter \
1890 for the function trait is neither a tuple nor unit");
1891 err_args(supplied_arg_count)
1894 } else if expected_arg_count == supplied_arg_count {
1895 fn_inputs.iter().map(|a| *a).collect()
1896 } else if variadic {
1897 if supplied_arg_count >= expected_arg_count {
1898 fn_inputs.iter().map(|a| *a).collect()
1900 span_err!(tcx.sess, sp, E0060,
1901 "this function takes at least {} parameter{} \
1902 but {} parameter{} supplied",
1904 if expected_arg_count == 1 {""} else {"s"},
1906 if supplied_arg_count == 1 {" was"} else {"s were"});
1907 err_args(supplied_arg_count)
1910 span_err!(tcx.sess, sp, E0061,
1911 "this function takes {} parameter{} but {} parameter{} supplied",
1913 if expected_arg_count == 1 {""} else {"s"},
1915 if supplied_arg_count == 1 {" was"} else {"s were"});
1916 err_args(supplied_arg_count)
1919 debug!("check_argument_types: formal_tys={:?}",
1920 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
1922 // Check the arguments.
1923 // We do this in a pretty awful way: first we typecheck any arguments
1924 // that are not anonymous functions, then we typecheck the anonymous
1925 // functions. This is so that we have more information about the types
1926 // of arguments when we typecheck the functions. This isn't really the
1927 // right way to do this.
1928 let xs = [false, true];
1929 for check_blocks in xs.iter() {
1930 let check_blocks = *check_blocks;
1931 debug!("check_blocks={}", check_blocks);
1933 // More awful hacks: before we check the blocks, try to do
1934 // an "opportunistic" vtable resolution of any trait
1935 // bounds on the call.
1937 vtable::early_resolve_expr(callee_expr, fcx, true);
1940 // For variadic functions, we don't have a declared type for all of
1941 // the arguments hence we only do our usual type checking with
1942 // the arguments who's types we do know.
1943 let t = if variadic {
1945 } else if tuple_arguments == TupleArguments {
1950 for (i, arg) in args.iter().take(t).enumerate() {
1951 let is_block = match arg.node {
1952 ast::ExprFnBlock(..) |
1954 ast::ExprUnboxedFn(..) => true,
1958 if is_block == check_blocks {
1959 debug!("checking the argument");
1960 let mut formal_ty = *formal_tys.get(i);
1964 match ty::get(formal_ty).sty {
1965 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1968 // So we hit this case when one implements the
1969 // operator traits but leaves an argument as
1970 // just T instead of &T. We'll catch it in the
1971 // mismatch impl/trait method phase no need to
1974 formal_ty = ty::mk_err();
1981 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1987 // We also need to make sure we at least write the ty of the other
1988 // arguments which we skipped above.
1990 for arg in args.iter().skip(expected_arg_count) {
1991 check_expr(fcx, &**arg);
1993 // There are a few types which get autopromoted when passed via varargs
1994 // in C but we just error out instead and require explicit casts.
1995 let arg_ty = structurally_resolved_type(fcx, arg.span,
1996 fcx.expr_ty(&**arg));
1997 match ty::get(arg_ty).sty {
1998 ty::ty_float(ast::TyF32) => {
1999 fcx.type_error_message(arg.span,
2001 format!("can't pass an {} to variadic \
2002 function, cast to c_double", t)
2005 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2006 fcx.type_error_message(arg.span, |t| {
2007 format!("can't pass {} to variadic \
2008 function, cast to c_int",
2012 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2013 fcx.type_error_message(arg.span, |t| {
2014 format!("can't pass {} to variadic \
2015 function, cast to c_uint",
2025 fn err_args(len: uint) -> Vec<ty::t> {
2026 Vec::from_fn(len, |_| ty::mk_err())
2029 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
2030 fcx.write_ty(call_expr.id, output);
2033 // AST fragment checking
2034 fn check_lit(fcx: &FnCtxt,
2036 expected: Expectation)
2039 let tcx = fcx.ccx.tcx;
2042 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2043 ast::LitBinary(..) => {
2044 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2046 ast::LitByte(_) => ty::mk_u8(),
2047 ast::LitChar(_) => ty::mk_char(),
2048 ast::LitInt(_, t) => ty::mk_mach_int(t),
2049 ast::LitUint(_, t) => ty::mk_mach_uint(t),
2050 ast::LitIntUnsuffixed(_) => {
2051 let opt_ty = expected.map_to_option(fcx, |sty| {
2053 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2054 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2055 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2056 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2057 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2061 opt_ty.unwrap_or_else(
2062 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2064 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2065 ast::LitFloatUnsuffixed(_) => {
2066 let opt_ty = expected.map_to_option(fcx, |sty| {
2068 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2072 opt_ty.unwrap_or_else(
2073 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2075 ast::LitNil => ty::mk_nil(),
2076 ast::LitBool(_) => ty::mk_bool()
2080 pub fn valid_range_bounds(ccx: &CrateCtxt,
2084 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2085 Some(val) => Some(val <= 0),
2090 pub fn check_expr_has_type(fcx: &FnCtxt,
2093 check_expr_with_unifier(
2094 fcx, expr, ExpectHasType(expected), NoPreference,
2095 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2098 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2101 check_expr_with_unifier(
2102 fcx, expr, ExpectHasType(expected), NoPreference,
2103 || demand::coerce(fcx, expr.span, expected, expr));
2106 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2107 check_expr_with_unifier(
2108 fcx, expr, ExpectHasType(expected), NoPreference,
2112 fn check_expr_with_expectation(fcx: &FnCtxt,
2114 expected: Expectation) {
2115 check_expr_with_unifier(
2116 fcx, expr, expected, NoPreference,
2120 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2122 expected: Expectation,
2123 lvalue_pref: LvaluePreference)
2125 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2128 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2129 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2132 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2133 lvalue_pref: LvaluePreference) {
2134 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2138 // determine the `self` type, using fresh variables for all variables
2139 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2140 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2142 pub fn impl_self_ty(vcx: &VtableContext,
2143 span: Span, // (potential) receiver for this impl
2146 let tcx = vcx.tcx();
2148 let ity = ty::lookup_item_type(tcx, did);
2149 let (n_tps, rps, raw_ty) =
2150 (ity.generics.types.len(subst::TypeSpace),
2151 ity.generics.regions.get_slice(subst::TypeSpace),
2154 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2155 let tps = vcx.infcx.next_ty_vars(n_tps);
2156 let substs = subst::Substs::new_type(tps, rps);
2157 let substd_ty = raw_ty.subst(tcx, &substs);
2159 TypeAndSubsts { substs: substs, ty: substd_ty }
2162 // Only for fields! Returns <none> for methods>
2163 // Indifferent to privacy flags
2164 pub fn lookup_field_ty(tcx: &ty::ctxt,
2165 class_id: ast::DefId,
2166 items: &[ty::field_ty],
2167 fieldname: ast::Name,
2168 substs: &subst::Substs) -> Option<ty::t> {
2170 let o_field = items.iter().find(|f| f.name == fieldname);
2171 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2174 // Controls whether the arguments are automatically referenced. This is useful
2175 // for overloaded binary and unary operators.
2176 pub enum DerefArgs {
2181 /// Controls whether the arguments are tupled. This is used for the call
2184 /// Tupling means that all call-side arguments are packed into a tuple and
2185 /// passed as a single parameter. For example, if tupling is enabled, this
2188 /// fn f(x: (int, int))
2190 /// Can be called as:
2197 #[deriving(Clone, Eq, PartialEq)]
2198 enum TupleArgumentsFlag {
2204 /// If an expression has any sub-expressions that result in a type error,
2205 /// inspecting that expression's type with `ty::type_is_error` will return
2206 /// true. Likewise, if an expression is known to diverge, inspecting its
2207 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2208 /// strict, _|_ can appear in the type of an expression that does not,
2209 /// itself, diverge: for example, fn() -> _|_.)
2210 /// Note that inspecting a type's structure *directly* may expose the fact
2211 /// that there are actually multiple representations for both `ty_err` and
2212 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2213 fn check_expr_with_unifier(fcx: &FnCtxt,
2215 expected: Expectation,
2216 lvalue_pref: LvaluePreference,
2219 debug!(">> typechecking");
2221 // A generic function for doing all of the checking for call expressions
2222 fn check_call(fcx: &FnCtxt,
2223 call_expr: &ast::Expr,
2225 args: &[Gc<ast::Expr>]) {
2226 // Store the type of `f` as the type of the callee
2227 let fn_ty = fcx.expr_ty(f);
2229 // Extract the function signature from `in_fty`.
2230 let fn_sty = structure_of(fcx, f.span, fn_ty);
2232 // This is the "default" function signature, used in case of error.
2233 // In that case, we check each argument against "error" in order to
2234 // set up all the node type bindings.
2235 let error_fn_sig = FnSig {
2236 binder_id: ast::CRATE_NODE_ID,
2237 inputs: err_args(args.len()),
2238 output: ty::mk_err(),
2242 let fn_sig = match *fn_sty {
2243 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2244 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2246 fcx.type_error_message(call_expr.span, |actual| {
2247 format!("expected function but found `{}`", actual)
2253 // Replace any bound regions that appear in the function
2254 // signature with region variables
2255 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2256 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2259 // Call the generic checker.
2260 check_argument_types(fcx,
2262 fn_sig.inputs.as_slice(),
2267 DontTupleArguments);
2269 write_call(fcx, call_expr, fn_sig.output);
2272 // Checks a method call.
2273 fn check_method_call(fcx: &FnCtxt,
2275 method_name: ast::SpannedIdent,
2276 args: &[Gc<ast::Expr>],
2277 tps: &[ast::P<ast::Ty>]) {
2278 let rcvr = args[0].clone();
2279 // We can't know if we need &mut self before we look up the method,
2280 // so treat the receiver as mutable just in case - only explicit
2281 // overloaded dereferences care about the distinction.
2282 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2284 // no need to check for bot/err -- callee does that
2285 let expr_t = structurally_resolved_type(fcx,
2287 fcx.expr_ty(&*rcvr));
2289 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2290 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2291 method_name.node.name,
2292 expr_t, tps.as_slice(),
2294 CheckTraitsAndInherentMethods,
2295 AutoderefReceiver, IgnoreStaticMethods) {
2297 let method_ty = method.ty;
2298 let method_call = MethodCall::expr(expr.id);
2299 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2303 debug!("(checking method call) failing expr is {}", expr.id);
2305 fcx.type_error_message(method_name.span,
2307 format!("type `{}` does not implement any \
2308 method in scope named `{}`",
2310 token::get_ident(method_name.node))
2315 // Add error type for the result
2316 fcx.write_error(expr.id);
2318 // Check for potential static matches (missing self parameters)
2322 method_name.node.name,
2326 CheckTraitsAndInherentMethods,
2327 DontAutoderefReceiver,
2328 ReportStaticMethods);
2334 // Call the generic checker.
2335 let ret_ty = check_method_argument_types(fcx,
2341 DontTupleArguments);
2343 write_call(fcx, expr, ret_ty);
2346 // A generic function for checking the then and else in an if
2348 fn check_then_else(fcx: &FnCtxt,
2349 cond_expr: &ast::Expr,
2350 then_blk: &ast::Block,
2351 opt_else_expr: Option<Gc<ast::Expr>>,
2354 expected: Expectation) {
2355 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2357 let branches_ty = match opt_else_expr {
2358 Some(ref else_expr) => {
2359 // Disregard "castable to" expectations because they
2360 // can lead us astray. Consider for example `if cond
2361 // {22} else {c} as u8` -- if we propagate the
2362 // "castable to u8" constraint to 22, it will pick the
2363 // type 22u8, which is overly constrained (c might not
2364 // be a u8). In effect, the problem is that the
2365 // "castable to" expectation is not the tightest thing
2366 // we can say, so we want to drop it in this case.
2367 // The tightest thing we can say is "must unify with
2368 // else branch". Note that in the case of a "has type"
2369 // constraint, this limitation does not hold.
2370 let expected = expected.only_has_type();
2372 check_block_with_expected(fcx, then_blk, expected);
2373 let then_ty = fcx.node_ty(then_blk.id);
2374 check_expr_with_expectation(fcx, &**else_expr, expected);
2375 let else_ty = fcx.expr_ty(&**else_expr);
2376 infer::common_supertype(fcx.infcx(),
2377 infer::IfExpression(sp),
2383 check_block_no_value(fcx, then_blk);
2388 let cond_ty = fcx.expr_ty(cond_expr);
2389 let if_ty = if ty::type_is_error(cond_ty) {
2391 } else if ty::type_is_bot(cond_ty) {
2397 fcx.write_ty(id, if_ty);
2400 fn lookup_op_method(fcx: &FnCtxt,
2404 trait_did: Option<ast::DefId>,
2405 args: &[Gc<ast::Expr>],
2406 autoderef_receiver: AutoderefReceiverFlag,
2407 unbound_method: ||) -> ty::t {
2408 let method = match trait_did {
2409 Some(trait_did) => {
2410 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2411 trait_did, self_t, [], autoderef_receiver,
2412 IgnoreStaticMethods)
2418 let method_ty = method.ty;
2419 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2420 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2421 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2422 check_method_argument_types(fcx,
2432 // Check the args anyway
2433 // so we get all the error messages
2434 let expected_ty = ty::mk_err();
2435 check_method_argument_types(fcx,
2441 DontTupleArguments);
2447 // could be either an expr_binop or an expr_assign_binop
2448 fn check_binop(fcx: &FnCtxt,
2453 is_binop_assignment: IsBinopAssignment) {
2454 let tcx = fcx.ccx.tcx;
2456 let lvalue_pref = match is_binop_assignment {
2457 BinopAssignment => PreferMutLvalue,
2458 SimpleBinop => NoPreference
2460 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2462 // Callee does bot / err checking
2463 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2464 fcx.expr_ty(&*lhs));
2466 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2467 // Shift is a special case: rhs must be uint, no matter what lhs is
2468 check_expr_has_type(fcx, &*rhs, ty::mk_uint());
2469 fcx.write_ty(expr.id, lhs_t);
2473 if ty::is_binopable(tcx, lhs_t, op) {
2474 let tvar = fcx.infcx().next_ty_var();
2475 demand::suptype(fcx, expr.span, tvar, lhs_t);
2476 check_expr_has_type(fcx, &*rhs, tvar);
2478 let result_t = match op {
2479 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2481 if ty::type_is_simd(tcx, lhs_t) {
2482 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2483 fcx.type_error_message(expr.span,
2485 format!("binary comparison \
2486 operation `{}` not \
2487 supported for floating \
2488 point SIMD vector `{}`",
2489 ast_util::binop_to_string(op),
2506 fcx.write_ty(expr.id, result_t);
2510 if op == ast::BiOr || op == ast::BiAnd {
2511 // This is an error; one of the operands must have the wrong
2513 fcx.write_error(expr.id);
2514 fcx.write_error(rhs.id);
2515 fcx.type_error_message(expr.span,
2517 format!("binary operation `{}` cannot be applied \
2519 ast_util::binop_to_string(op),
2526 // Check for overloaded operators if not an assignment.
2527 let result_t = if is_binop_assignment == SimpleBinop {
2528 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2530 fcx.type_error_message(expr.span,
2532 format!("binary assignment \
2534 cannot be applied to \
2536 ast_util::binop_to_string(op),
2541 check_expr(fcx, &*rhs);
2545 fcx.write_ty(expr.id, result_t);
2546 if ty::type_is_error(result_t) {
2547 fcx.write_ty(rhs.id, result_t);
2551 fn check_user_binop(fcx: &FnCtxt,
2553 lhs_expr: Gc<ast::Expr>,
2554 lhs_resolved_t: ty::t,
2556 rhs: Gc<ast::Expr>) -> ty::t {
2557 let tcx = fcx.ccx.tcx;
2558 let lang = &tcx.lang_items;
2559 let (name, trait_did) = match op {
2560 ast::BiAdd => ("add", lang.add_trait()),
2561 ast::BiSub => ("sub", lang.sub_trait()),
2562 ast::BiMul => ("mul", lang.mul_trait()),
2563 ast::BiDiv => ("div", lang.div_trait()),
2564 ast::BiRem => ("rem", lang.rem_trait()),
2565 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2566 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2567 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2568 ast::BiShl => ("shl", lang.shl_trait()),
2569 ast::BiShr => ("shr", lang.shr_trait()),
2570 ast::BiLt => ("lt", lang.ord_trait()),
2571 ast::BiLe => ("le", lang.ord_trait()),
2572 ast::BiGe => ("ge", lang.ord_trait()),
2573 ast::BiGt => ("gt", lang.ord_trait()),
2574 ast::BiEq => ("eq", lang.eq_trait()),
2575 ast::BiNe => ("ne", lang.eq_trait()),
2576 ast::BiAnd | ast::BiOr => {
2577 check_expr(fcx, &*rhs);
2578 return ty::mk_err();
2581 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2582 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2583 fcx.type_error_message(ex.span, |actual| {
2584 format!("binary operation `{}` cannot be applied to type `{}`",
2585 ast_util::binop_to_string(op),
2587 }, lhs_resolved_t, None)
2591 fn check_user_unop(fcx: &FnCtxt,
2594 trait_did: Option<ast::DefId>,
2596 rhs_expr: Gc<ast::Expr>,
2597 rhs_t: ty::t) -> ty::t {
2598 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2599 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2600 fcx.type_error_message(ex.span, |actual| {
2601 format!("cannot apply unary operator `{}` to type `{}`",
2607 fn check_unboxed_closure(fcx: &FnCtxt,
2610 body: ast::P<ast::Block>) {
2611 // The `RegionTraitStore` is a lie, but we ignore it so it doesn't
2614 // FIXME(pcwalton): Refactor this API.
2615 let mut fn_ty = astconv::ty_of_closure(
2620 ty::empty_builtin_bounds(),
2621 ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
2626 let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
2627 local_def(expr.id));
2628 fcx.write_ty(expr.id, closure_type);
2638 // Tuple up the arguments and insert the resulting function type into
2639 // the `unboxed_closure_types` table.
2640 fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
2643 .unboxed_closure_types
2645 .insert(local_def(expr.id), fn_ty);
2648 fn check_expr_fn(fcx: &FnCtxt,
2650 store: ty::TraitStore,
2652 body: ast::P<ast::Block>,
2653 expected: Expectation) {
2654 let tcx = fcx.ccx.tcx;
2656 // Find the expected input/output types (if any). Substitute
2657 // fresh bound regions for any bound regions we find in the
2658 // expected types so as to avoid capture.
2659 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2662 expected_bounds) = {
2663 match expected_sty {
2664 Some(ty::ty_closure(ref cenv)) => {
2666 replace_late_bound_regions_in_fn_sig(
2668 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2669 let onceness = match (&store, &cenv.store) {
2670 // As the closure type and onceness go, only three
2671 // combinations are legit:
2675 // If the actual and expected closure type disagree with
2676 // each other, set expected onceness to be always Once or
2677 // Many according to the actual type. Otherwise, it will
2678 // yield either an illegal "many proc" or a less known
2679 // "once closure" in the error message.
2680 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2681 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2683 (&ty::UniqTraitStore, _) => ast::Once,
2684 (&ty::RegionTraitStore(..), _) => ast::Many,
2686 (Some(sig), onceness, cenv.bounds)
2689 // Not an error! Means we're inferring the closure type
2690 let mut bounds = ty::empty_builtin_bounds();
2691 let onceness = match expr.node {
2692 ast::ExprProc(..) => {
2693 bounds.add(ty::BoundSend);
2698 (None, onceness, bounds)
2703 // construct the function type
2704 let fn_ty = astconv::ty_of_closure(fcx,
2713 let fty_sig = fn_ty.sig.clone();
2714 let fty = ty::mk_closure(tcx, fn_ty);
2715 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
2717 fcx.write_ty(expr.id, fty);
2719 // If the closure is a stack closure and hasn't had some non-standard
2720 // style inferred for it, then check it under its parent's style.
2721 // Otherwise, use its own
2722 let (inherited_style, id) = match store {
2723 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2724 fcx.ps.borrow().def),
2725 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2738 // Check field access expressions
2739 fn check_field(fcx: &FnCtxt,
2741 lvalue_pref: LvaluePreference,
2743 field: &ast::SpannedIdent,
2744 tys: &[ast::P<ast::Ty>]) {
2745 let tcx = fcx.ccx.tcx;
2746 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2747 let expr_t = structurally_resolved_type(fcx, expr.span,
2749 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2750 let (_, autoderefs, field_ty) =
2751 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2752 match ty::get(base_t).sty {
2753 ty::ty_struct(base_id, ref substs) => {
2754 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2755 let fields = ty::lookup_struct_fields(tcx, base_id);
2756 lookup_field_ty(tcx, base_id, fields.as_slice(),
2757 field.node.name, &(*substs))
2764 fcx.write_ty(expr.id, field_ty);
2765 fcx.write_autoderef_adjustment(base.id, autoderefs);
2771 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2772 match method::lookup(fcx,
2779 CheckTraitsAndInherentMethods,
2781 IgnoreStaticMethods) {
2783 fcx.type_error_message(
2786 format!("attempted to take value of method `{}` on type \
2787 `{}`", token::get_ident(field.node), actual)
2791 tcx.sess.span_note(field.span,
2792 "maybe a missing `()` to call it? If not, try an anonymous function.");
2796 fcx.type_error_message(
2799 format!("attempted access of field `{}` on \
2800 type `{}`, but no field with that \
2802 token::get_ident(field.node),
2809 fcx.write_error(expr.id);
2812 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2815 class_id: ast::DefId,
2816 node_id: ast::NodeId,
2817 substitutions: subst::Substs,
2818 field_types: &[ty::field_ty],
2819 ast_fields: &[ast::Field],
2820 check_completeness: bool) {
2821 let tcx = fcx.ccx.tcx;
2823 let mut class_field_map = HashMap::new();
2824 let mut fields_found = 0;
2825 for field in field_types.iter() {
2826 class_field_map.insert(field.name, (field.id, false));
2829 let mut error_happened = false;
2831 // Typecheck each field.
2832 for field in ast_fields.iter() {
2833 let mut expected_field_type = ty::mk_err();
2835 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2838 fcx.type_error_message(
2841 format!("structure `{}` has no field named `{}`",
2842 actual, token::get_ident(field.ident.node))
2846 error_happened = true;
2848 Some((_, true)) => {
2849 span_err!(fcx.tcx().sess, field.ident.span, E0062,
2850 "field `{}` specified more than once",
2851 token::get_ident(field.ident.node));
2852 error_happened = true;
2854 Some((field_id, false)) => {
2855 expected_field_type =
2856 ty::lookup_field_type(
2857 tcx, class_id, field_id, &substitutions);
2858 class_field_map.insert(
2859 field.ident.node.name, (field_id, true));
2863 // Make sure to give a type to the field even if there's
2864 // an error, so we can continue typechecking
2865 check_expr_coercable_to_type(
2868 expected_field_type);
2872 fcx.write_error(node_id);
2875 if check_completeness && !error_happened {
2876 // Make sure the programmer specified all the fields.
2877 assert!(fields_found <= field_types.len());
2878 if fields_found < field_types.len() {
2879 let mut missing_fields = Vec::new();
2880 for class_field in field_types.iter() {
2881 let name = class_field.name;
2882 let (_, seen) = *class_field_map.get(&name);
2884 missing_fields.push(
2885 format!("`{}`", token::get_name(name).get()))
2889 span_err!(tcx.sess, span, E0063,
2890 "missing field{}: {}",
2891 if missing_fields.len() == 1 {""} else {"s"},
2892 missing_fields.connect(", "));
2896 if !error_happened {
2897 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2898 class_id, substitutions));
2902 fn check_struct_constructor(fcx: &FnCtxt,
2904 span: codemap::Span,
2905 class_id: ast::DefId,
2906 fields: &[ast::Field],
2907 base_expr: Option<Gc<ast::Expr>>) {
2908 let tcx = fcx.ccx.tcx;
2910 // Look up the number of type parameters and the raw type, and
2911 // determine whether the class is region-parameterized.
2912 let item_type = ty::lookup_item_type(tcx, class_id);
2913 let raw_type = item_type.ty;
2915 // Generate the struct type.
2916 let substitutions = fcx.infcx().fresh_substs_for_type(
2917 span, &item_type.generics);
2918 let mut struct_type = raw_type.subst(tcx, &substitutions);
2920 // Look up and check the fields.
2921 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2922 check_struct_or_variant_fields(fcx,
2928 class_fields.as_slice(),
2930 base_expr.is_none());
2931 if ty::type_is_error(fcx.node_ty(id)) {
2932 struct_type = ty::mk_err();
2935 // Check the base expression if necessary.
2938 Some(base_expr) => {
2939 check_expr_has_type(fcx, &*base_expr, struct_type);
2940 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2941 struct_type = ty::mk_bot();
2946 // Write in the resulting type.
2947 fcx.write_ty(id, struct_type);
2950 fn check_struct_enum_variant(fcx: &FnCtxt,
2952 span: codemap::Span,
2953 enum_id: ast::DefId,
2954 variant_id: ast::DefId,
2955 fields: &[ast::Field]) {
2956 let tcx = fcx.ccx.tcx;
2958 // Look up the number of type parameters and the raw type, and
2959 // determine whether the enum is region-parameterized.
2960 let item_type = ty::lookup_item_type(tcx, enum_id);
2961 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2962 let enum_type = item_type.ty.subst(tcx, &substitutions);
2964 // Look up and check the enum variant fields.
2965 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2966 check_struct_or_variant_fields(fcx,
2972 variant_fields.as_slice(),
2975 fcx.write_ty(id, enum_type);
2978 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2980 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2981 expected: Expectation)
2982 -> (ExprCheckerWithTy, ty::t) {
2983 let tcx = fcx.ccx.tcx;
2984 let (coerce, t) = match expected {
2985 // If we're given an expected type, we can try to coerce to it
2986 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2987 // Otherwise we just leave the type to be resolved later
2988 _ => (false, fcx.infcx().next_ty_var())
2991 (check_expr_coercable_to_type, t)
2993 (check_expr_has_type, t)
2997 let tcx = fcx.ccx.tcx;
3000 ast::ExprVstore(ev, vst) => {
3001 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3002 let typ = match ev.node {
3003 ast::ExprVec(ref args) => {
3004 let mutability = match vst {
3005 ast::ExprVstoreMutSlice => ast::MutMutable,
3006 _ => ast::MutImmutable,
3008 let mut any_error = false;
3009 let mut any_bot = false;
3010 for e in args.iter() {
3011 check(fcx, &**e, t);
3012 let arg_t = fcx.expr_ty(&**e);
3013 if ty::type_is_error(arg_t) {
3016 else if ty::type_is_bot(arg_t) {
3025 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
3026 ty::mt{ ty: ty::mk_vec(tcx,
3027 ty::mt {ty: t, mutbl: mutability},
3029 mutbl: mutability })
3032 ast::ExprRepeat(ref element, ref count_expr) => {
3033 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3034 let _ = ty::eval_repeat_count(fcx, &**count_expr);
3035 let mutability = match vst {
3036 ast::ExprVstoreMutSlice => ast::MutMutable,
3037 _ => ast::MutImmutable,
3039 check(fcx, &**element, t);
3040 let arg_t = fcx.expr_ty(&**element);
3041 if ty::type_is_error(arg_t) {
3043 } else if ty::type_is_bot(arg_t) {
3046 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
3047 ty::mt{ ty: ty::mk_vec(tcx,
3048 ty::mt {ty: t, mutbl: mutability},
3053 ast::ExprLit(_) => {
3054 if vst == ast::ExprVstoreSlice {
3055 span_err!(tcx.sess, expr.span, E0064,
3056 "`&\"string\"` has been removed; use `\"string\"` instead");
3058 span_err!(tcx.sess, expr.span, E0065,
3059 "`box \"string\"` has been removed; use \
3060 `\"string\".to_string()` instead");
3064 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
3066 fcx.write_ty(ev.id, typ);
3067 fcx.write_ty(id, typ);
3070 ast::ExprBox(ref place, ref subexpr) => {
3071 check_expr(fcx, &**place);
3072 check_expr(fcx, &**subexpr);
3074 let mut checked = false;
3076 ast::ExprPath(ref path) => {
3077 // FIXME(pcwalton): For now we hardcode the two permissible
3078 // places: the exchange heap and the managed heap.
3079 let definition = lookup_def(fcx, path.span, place.id);
3080 let def_id = definition.def_id();
3081 if tcx.lang_items.exchange_heap() == Some(def_id) {
3082 fcx.write_ty(id, ty::mk_uniq(tcx,
3083 fcx.expr_ty(&**subexpr)));
3085 } else if tcx.lang_items.managed_heap() == Some(def_id) {
3086 fcx.write_ty(id, ty::mk_box(tcx,
3087 fcx.expr_ty(&**subexpr)));
3095 span_err!(tcx.sess, expr.span, E0066,
3096 "only the managed heap and exchange heap are currently supported");
3097 fcx.write_ty(id, ty::mk_err());
3101 ast::ExprLit(lit) => {
3102 let typ = check_lit(fcx, &*lit, expected);
3103 fcx.write_ty(id, typ);
3105 ast::ExprBinary(op, ref lhs, ref rhs) => {
3106 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
3108 let lhs_ty = fcx.expr_ty(&**lhs);
3109 let rhs_ty = fcx.expr_ty(&**rhs);
3110 if ty::type_is_error(lhs_ty) ||
3111 ty::type_is_error(rhs_ty) {
3112 fcx.write_error(id);
3114 else if ty::type_is_bot(lhs_ty) ||
3115 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3119 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3120 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3122 let lhs_t = fcx.expr_ty(&**lhs);
3123 let result_t = fcx.expr_ty(expr);
3124 demand::suptype(fcx, expr.span, result_t, lhs_t);
3126 let tcx = fcx.tcx();
3127 if !ty::expr_is_lval(tcx, &**lhs) {
3128 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3131 // Overwrite result of check_binop...this preserves existing behavior
3132 // but seems quite dubious with regard to user-defined methods
3133 // and so forth. - Niko
3134 if !ty::type_is_error(result_t)
3135 && !ty::type_is_bot(result_t) {
3136 fcx.write_nil(expr.id);
3139 ast::ExprUnary(unop, ref oprnd) => {
3140 let expected = expected.only_has_type();
3141 let expected_inner = expected.map(fcx, |sty| {
3143 ast::UnBox | ast::UnUniq => match *sty {
3144 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3151 ast::UnNot | ast::UnNeg => {
3159 let lvalue_pref = match unop {
3160 ast::UnDeref => lvalue_pref,
3163 check_expr_with_expectation_and_lvalue_pref(
3164 fcx, &**oprnd, expected_inner, lvalue_pref);
3165 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3166 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3169 oprnd_t = ty::mk_box(tcx, oprnd_t)
3172 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3175 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3176 oprnd_t = match ty::deref(oprnd_t, true) {
3178 None => match try_overloaded_deref(fcx, expr.span,
3179 Some(MethodCall::expr(expr.id)),
3180 Some(&**oprnd), oprnd_t, lvalue_pref) {
3183 let is_newtype = match ty::get(oprnd_t).sty {
3184 ty::ty_struct(did, ref substs) => {
3185 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3187 && fields.get(0).ident ==
3188 token::special_idents::unnamed_field
3193 // This is an obsolete struct deref
3194 span_err!(tcx.sess, expr.span, E0068,
3195 "single-field tuple-structs can \
3196 no longer be dereferenced");
3198 fcx.type_error_message(expr.span, |actual| {
3199 format!("type `{}` cannot be \
3200 dereferenced", actual)
3209 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3211 if !(ty::type_is_integral(oprnd_t) ||
3212 ty::get(oprnd_t).sty == ty::ty_bool) {
3213 oprnd_t = check_user_unop(fcx, "!", "not",
3214 tcx.lang_items.not_trait(),
3215 expr, oprnd.clone(), oprnd_t);
3219 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3221 if !(ty::type_is_integral(oprnd_t) ||
3222 ty::type_is_fp(oprnd_t)) {
3223 oprnd_t = check_user_unop(fcx, "-", "neg",
3224 tcx.lang_items.neg_trait(),
3225 expr, oprnd.clone(), oprnd_t);
3230 fcx.write_ty(id, oprnd_t);
3232 ast::ExprAddrOf(mutbl, ref oprnd) => {
3233 let expected = expected.only_has_type();
3234 let hint = expected.map(fcx, |sty| {
3235 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3236 _ => NoExpectation }
3238 let lvalue_pref = match mutbl {
3239 ast::MutMutable => PreferMutLvalue,
3240 ast::MutImmutable => NoPreference
3242 check_expr_with_expectation_and_lvalue_pref(fcx,
3247 // Note: at this point, we cannot say what the best lifetime
3248 // is to use for resulting pointer. We want to use the
3249 // shortest lifetime possible so as to avoid spurious borrowck
3250 // errors. Moreover, the longest lifetime will depend on the
3251 // precise details of the value whose address is being taken
3252 // (and how long it is valid), which we don't know yet until type
3253 // inference is complete.
3255 // Therefore, here we simply generate a region variable. The
3256 // region inferencer will then select the ultimate value.
3257 // Finally, borrowck is charged with guaranteeing that the
3258 // value whose address was taken can actually be made to live
3259 // as long as it needs to live.
3260 let region = fcx.infcx().next_region_var(
3261 infer::AddrOfRegion(expr.span));
3263 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3264 let oprnd_t = if ty::type_is_error(tm.ty) {
3266 } else if ty::type_is_bot(tm.ty) {
3270 ty::mk_rptr(tcx, region, tm)
3272 fcx.write_ty(id, oprnd_t);
3274 ast::ExprPath(ref pth) => {
3275 let defn = lookup_def(fcx, pth.span, id);
3276 let pty = polytype_for_def(fcx, expr.span, defn);
3277 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3279 ast::ExprInlineAsm(ref ia) => {
3280 for &(_, ref input) in ia.inputs.iter() {
3281 check_expr(fcx, &**input);
3283 for &(_, ref out) in ia.outputs.iter() {
3284 check_expr(fcx, &**out);
3288 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3289 ast::ExprBreak(_) => { fcx.write_bot(id); }
3290 ast::ExprAgain(_) => { fcx.write_bot(id); }
3291 ast::ExprRet(ref expr_opt) => {
3292 let ret_ty = fcx.ret_ty;
3294 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3295 ret_ty, ty::mk_nil()) {
3296 Ok(_) => { /* fall through */ }
3298 span_err!(tcx.sess, expr.span, E0069,
3299 "`return;` in function returning non-nil");
3303 check_expr_has_type(fcx, &**e, ret_ty);
3308 ast::ExprParen(a) => {
3309 check_expr_with_expectation_and_lvalue_pref(fcx,
3313 fcx.write_ty(id, fcx.expr_ty(&*a));
3315 ast::ExprAssign(ref lhs, ref rhs) => {
3316 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3318 let tcx = fcx.tcx();
3319 if !ty::expr_is_lval(tcx, &**lhs) {
3320 span_err!(tcx.sess, expr.span, E0070,
3321 "illegal left-hand side expression");
3324 let lhs_ty = fcx.expr_ty(&**lhs);
3325 check_expr_has_type(fcx, &**rhs, lhs_ty);
3326 let rhs_ty = fcx.expr_ty(&**rhs);
3328 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3329 fcx.write_error(id);
3330 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3336 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3337 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3338 id, expr.span, expected);
3340 ast::ExprWhile(ref cond, ref body) => {
3341 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3342 check_block_no_value(fcx, &**body);
3343 let cond_ty = fcx.expr_ty(&**cond);
3344 let body_ty = fcx.node_ty(body.id);
3345 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3346 fcx.write_error(id);
3348 else if ty::type_is_bot(cond_ty) {
3355 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3356 check_expr(fcx, &**head);
3357 let typ = lookup_method_for_for_loop(fcx, *head, expr.id);
3358 vtable::early_resolve_expr(expr, fcx, true);
3360 let pcx = pat_ctxt {
3362 map: pat_id_map(&tcx.def_map, &**pat),
3364 _match::check_pat(&pcx, &**pat, typ);
3366 check_block_no_value(fcx, &**block);
3369 ast::ExprLoop(ref body, _) => {
3370 check_block_no_value(fcx, &**body);
3371 if !may_break(tcx, expr.id, body.clone()) {
3378 ast::ExprMatch(ref discrim, ref arms) => {
3379 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3381 ast::ExprFnBlock(ref decl, ref body) => {
3382 let region = astconv::opt_ast_region_to_region(fcx,
3388 ty::RegionTraitStore(region, ast::MutMutable),
3393 ast::ExprUnboxedFn(ref decl, ref body) => {
3394 check_unboxed_closure(fcx,
3399 ast::ExprProc(ref decl, ref body) => {
3407 ast::ExprBlock(ref b) => {
3408 check_block_with_expected(fcx, &**b, expected);
3409 fcx.write_ty(id, fcx.node_ty(b.id));
3411 ast::ExprCall(ref f, ref args) => {
3412 // Index expressions need to be handled separately, to inform them
3413 // that they appear in call position.
3414 check_expr(fcx, &**f);
3415 let f_ty = fcx.expr_ty(&**f);
3417 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3418 check_call(fcx, expr, &**f, args.as_slice());
3419 let (args_bot, args_err) = args.iter().fold((false, false),
3420 |(rest_bot, rest_err), a| {
3421 // is this not working?
3422 let a_ty = fcx.expr_ty(&**a);
3423 (rest_bot || ty::type_is_bot(a_ty),
3424 rest_err || ty::type_is_error(a_ty))});
3425 if ty::type_is_error(f_ty) || args_err {
3426 fcx.write_error(id);
3428 else if ty::type_is_bot(f_ty) || args_bot {
3433 ast::ExprMethodCall(ident, ref tps, ref args) => {
3434 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3435 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3436 let (args_bot, args_err) = arg_tys.fold((false, false),
3437 |(rest_bot, rest_err), a| {
3438 (rest_bot || ty::type_is_bot(a),
3439 rest_err || ty::type_is_error(a))});
3441 fcx.write_error(id);
3442 } else if args_bot {
3446 ast::ExprCast(ref e, ref t) => {
3447 check_cast(fcx, &**e, &**t, id, expr.span);
3449 ast::ExprVec(ref args) => {
3450 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3451 for e in args.iter() {
3452 check(fcx, &**e, t);
3454 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3456 fcx.write_ty(id, typ);
3458 ast::ExprRepeat(ref element, ref count_expr) => {
3459 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3460 let count = ty::eval_repeat_count(fcx, &**count_expr);
3461 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3462 check(fcx, &**element, t);
3463 let element_ty = fcx.expr_ty(&**element);
3464 if ty::type_is_error(element_ty) {
3465 fcx.write_error(id);
3467 else if ty::type_is_bot(element_ty) {
3471 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3473 fcx.write_ty(id, t);
3476 ast::ExprTup(ref elts) => {
3477 let expected = expected.only_has_type();
3478 let flds = expected.map_to_option(fcx, |sty| {
3480 ty::ty_tup(ref flds) => Some((*flds).clone()),
3484 let mut bot_field = false;
3485 let mut err_field = false;
3487 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3488 let opt_hint = match flds {
3489 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3492 check_expr_with_expectation(fcx, &**e, opt_hint);
3493 let t = fcx.expr_ty(&**e);
3494 err_field = err_field || ty::type_is_error(t);
3495 bot_field = bot_field || ty::type_is_bot(t);
3500 } else if err_field {
3501 fcx.write_error(id);
3503 let typ = ty::mk_tup(tcx, elt_ts);
3504 fcx.write_ty(id, typ);
3507 ast::ExprStruct(ref path, ref fields, base_expr) => {
3508 // Resolve the path.
3509 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3510 let struct_id = match def {
3511 Some(def::DefVariant(enum_id, variant_id, _)) => {
3512 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3513 variant_id, fields.as_slice());
3517 // Verify that this was actually a struct.
3518 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3519 match ty::get(typ.ty).sty {
3520 ty::ty_struct(struct_did, _) => {
3521 check_struct_constructor(fcx,
3529 span_err!(tcx.sess, path.span, E0071,
3530 "`{}` does not name a structure",
3531 pprust::path_to_string(path));
3538 tcx.sess.span_bug(path.span,
3539 "structure constructor wasn't resolved")
3543 // Turn the path into a type and verify that that type unifies with
3544 // the resulting structure type. This is needed to handle type
3545 // parameters correctly.
3546 let actual_structure_type = fcx.expr_ty(&*expr);
3547 if !ty::type_is_error(actual_structure_type) {
3548 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
3552 match fcx.mk_subty(false,
3553 infer::Misc(path.span),
3554 actual_structure_type,
3555 type_and_substs.ty) {
3557 Err(type_error) => {
3558 let type_error_description =
3559 ty::type_err_to_str(tcx, &type_error);
3562 .span_err(path.span,
3563 format!("structure constructor specifies a \
3564 structure of type `{}`, but this \
3565 structure has type `{}`: {}",
3567 .ty_to_string(type_and_substs.ty),
3570 actual_structure_type),
3571 type_error_description).as_slice());
3572 ty::note_and_explain_type_err(tcx, &type_error);
3577 ast::ExprField(ref base, ref field, ref tys) => {
3578 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3580 ast::ExprIndex(ref base, ref idx) => {
3581 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3582 check_expr(fcx, &**idx);
3583 let raw_base_t = fcx.expr_ty(&**base);
3584 let idx_t = fcx.expr_ty(&**idx);
3585 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3586 fcx.write_ty(id, raw_base_t);
3587 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3588 fcx.write_ty(id, idx_t);
3590 let (_, autoderefs, field_ty) =
3591 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3592 lvalue_pref, |base_t, _| ty::index(base_t));
3595 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3596 fcx.write_ty(id, mt.ty);
3597 fcx.write_autoderef_adjustment(base.id, autoderefs);
3600 // This is an overloaded method.
3601 let base_t = structurally_resolved_type(fcx,
3604 let method_call = MethodCall::expr(expr.id);
3605 match try_overloaded_index(fcx,
3612 Some(mt) => fcx.write_ty(id, mt.ty),
3614 fcx.type_error_message(expr.span,
3624 fcx.write_ty(id, ty::mk_err())
3633 debug!("type of expr({}) {} is...", expr.id,
3634 syntax::print::pprust::expr_to_string(expr));
3635 debug!("... {}, expected is {}",
3636 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3637 expected.repr(tcx));
3643 fn only_has_type(self) -> Expectation {
3645 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3646 ExpectHasType(t) => ExpectHasType(t)
3650 // Resolves `expected` by a single level if it is a variable. If
3651 // there is no expected type or resolution is not possible (e.g.,
3652 // no constraints yet present), just returns `None`.
3653 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3658 ExpectCastableToType(t) => {
3659 ExpectCastableToType(
3660 fcx.infcx().resolve_type_vars_if_possible(t))
3662 ExpectHasType(t) => {
3664 fcx.infcx().resolve_type_vars_if_possible(t))
3669 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3670 match self.resolve(fcx) {
3671 NoExpectation => NoExpectation,
3672 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3676 fn map_to_option<O>(self,
3678 unpack: |&ty::sty| -> Option<O>)
3681 match self.resolve(fcx) {
3682 NoExpectation => None,
3683 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3688 impl Repr for Expectation {
3689 fn repr(&self, tcx: &ty::ctxt) -> String {
3691 NoExpectation => format!("NoExpectation"),
3692 ExpectHasType(t) => format!("ExpectHasType({})",
3694 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3700 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3701 if !type_is_uint(fcx, sp, t) {
3702 fcx.type_error_message(sp, |actual| {
3703 format!("mismatched types: expected `uint` type but found `{}`",
3709 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3710 if !type_is_integral(fcx, sp, t) {
3711 fcx.type_error_message(sp, |actual| {
3712 format!("mismatched types: expected integral type but found `{}`",
3718 pub fn check_decl_initializer(fcx: &FnCtxt,
3722 let local_ty = fcx.local_ty(init.span, nid);
3723 check_expr_coercable_to_type(fcx, init, local_ty)
3726 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3727 let tcx = fcx.ccx.tcx;
3729 let t = fcx.local_ty(local.span, local.id);
3730 fcx.write_ty(local.id, t);
3734 check_decl_initializer(fcx, local.id, &**init);
3735 let init_ty = fcx.expr_ty(&**init);
3736 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3737 fcx.write_ty(local.id, init_ty);
3743 let pcx = pat_ctxt {
3745 map: pat_id_map(&tcx.def_map, &*local.pat),
3747 _match::check_pat(&pcx, &*local.pat, t);
3748 let pat_ty = fcx.node_ty(local.pat.id);
3749 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3750 fcx.write_ty(local.id, pat_ty);
3754 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3756 let mut saw_bot = false;
3757 let mut saw_err = false;
3759 ast::StmtDecl(decl, id) => {
3762 ast::DeclLocal(ref l) => {
3763 check_decl_local(fcx, &**l);
3764 let l_t = fcx.node_ty(l.id);
3765 saw_bot = saw_bot || ty::type_is_bot(l_t);
3766 saw_err = saw_err || ty::type_is_error(l_t);
3768 ast::DeclItem(_) => {/* ignore for now */ }
3771 ast::StmtExpr(ref expr, id) => {
3773 // Check with expected type of ()
3774 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3775 let expr_ty = fcx.expr_ty(&**expr);
3776 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3777 saw_err = saw_err || ty::type_is_error(expr_ty);
3779 ast::StmtSemi(ref expr, id) => {
3781 check_expr(fcx, &**expr);
3782 let expr_ty = fcx.expr_ty(&**expr);
3783 saw_bot |= ty::type_is_bot(expr_ty);
3784 saw_err |= ty::type_is_error(expr_ty);
3786 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3789 fcx.write_bot(node_id);
3792 fcx.write_error(node_id);
3795 fcx.write_nil(node_id)
3799 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3800 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3801 let blkty = fcx.node_ty(blk.id);
3802 if ty::type_is_error(blkty) {
3803 fcx.write_error(blk.id);
3805 else if ty::type_is_bot(blkty) {
3806 fcx.write_bot(blk.id);
3809 let nilty = ty::mk_nil();
3810 demand::suptype(fcx, blk.span, nilty, blkty);
3814 fn check_block_with_expected(fcx: &FnCtxt,
3816 expected: Expectation) {
3818 let mut fcx_ps = fcx.ps.borrow_mut();
3819 let fn_style_state = fcx_ps.recurse(blk);
3820 replace(&mut *fcx_ps, fn_style_state)
3823 fcx.with_region_lb(blk.id, || {
3824 let mut warned = false;
3825 let mut last_was_bot = false;
3826 let mut any_bot = false;
3827 let mut any_err = false;
3828 for s in blk.stmts.iter() {
3829 check_stmt(fcx, &**s);
3830 let s_id = ast_util::stmt_id(&**s);
3831 let s_ty = fcx.node_ty(s_id);
3832 if last_was_bot && !warned && match s.node {
3833 ast::StmtDecl(decl, _) => {
3835 ast::DeclLocal(_) => true,
3839 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3845 .add_lint(lint::builtin::UNREACHABLE_CODE,
3848 "unreachable statement".to_string());
3851 if ty::type_is_bot(s_ty) {
3852 last_was_bot = true;
3854 any_bot = any_bot || ty::type_is_bot(s_ty);
3855 any_err = any_err || ty::type_is_error(s_ty);
3858 None => if any_err {
3859 fcx.write_error(blk.id);
3862 fcx.write_bot(blk.id);
3865 fcx.write_nil(blk.id);
3868 if any_bot && !warned {
3872 .add_lint(lint::builtin::UNREACHABLE_CODE,
3875 "unreachable expression".to_string());
3877 check_expr_with_expectation(fcx, &*e, expected);
3878 let ety = fcx.expr_ty(&*e);
3879 fcx.write_ty(blk.id, ety);
3881 fcx.write_error(blk.id);
3884 fcx.write_bot(blk.id);
3890 *fcx.ps.borrow_mut() = prev;
3893 pub fn check_const(ccx: &CrateCtxt,
3897 let inh = blank_inherited_fields(ccx);
3898 let rty = ty::node_id_to_type(ccx.tcx, id);
3899 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3900 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3901 check_const_with_ty(&fcx, sp, e, declty);
3904 pub fn check_const_with_ty(fcx: &FnCtxt,
3908 // Gather locals in statics (because of block expressions).
3909 // This is technically unnecessary because locals in static items are forbidden,
3910 // but prevents type checking from blowing up before const checking can properly
3912 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3915 let cty = fcx.expr_ty(e);
3916 demand::suptype(fcx, e.span, declty, cty);
3917 regionck::regionck_expr(fcx, e);
3918 writeback::resolve_type_vars_in_expr(fcx, e);
3921 /// Checks whether a type can be represented in memory. In particular, it
3922 /// identifies types that contain themselves without indirection through a
3923 /// pointer, which would mean their size is unbounded. This is different from
3924 /// the question of whether a type can be instantiated. See the definition of
3925 /// `check_instantiable`.
3926 pub fn check_representable(tcx: &ty::ctxt,
3928 item_id: ast::NodeId,
3929 designation: &str) -> bool {
3930 let rty = ty::node_id_to_type(tcx, item_id);
3932 // Check that it is possible to represent this type. This call identifies
3933 // (1) types that contain themselves and (2) types that contain a different
3934 // recursive type. It is only necessary to throw an error on those that
3935 // contain themselves. For case 2, there must be an inner type that will be
3936 // caught by case 1.
3937 match ty::is_type_representable(tcx, sp, rty) {
3938 ty::SelfRecursive => {
3939 span_err!(tcx.sess, sp, E0072,
3940 "illegal recursive {} type; \
3941 wrap the inner value in a box to make it representable",
3945 ty::Representable | ty::ContainsRecursive => (),
3950 /// Checks whether a type can be created without an instance of itself.
3951 /// This is similar but different from the question of whether a type
3952 /// can be represented. For example, the following type:
3954 /// enum foo { None, Some(foo) }
3956 /// is instantiable but is not representable. Similarly, the type
3958 /// enum foo { Some(@foo) }
3960 /// is representable, but not instantiable.
3961 pub fn check_instantiable(tcx: &ty::ctxt,
3963 item_id: ast::NodeId)
3965 let item_ty = ty::node_id_to_type(tcx, item_id);
3966 if !ty::is_instantiable(tcx, item_ty) {
3967 span_err!(tcx.sess, sp, E0073,
3968 "this type cannot be instantiated without an \
3969 instance of itself; consider using `Option<{}>`",
3970 ppaux::ty_to_string(tcx, item_ty));
3977 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3978 let t = ty::node_id_to_type(tcx, id);
3979 if ty::type_needs_subst(t) {
3980 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
3983 match ty::get(t).sty {
3984 ty::ty_struct(did, ref substs) => {
3985 let fields = ty::lookup_struct_fields(tcx, did);
3986 if fields.is_empty() {
3987 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
3990 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3991 if !fields.iter().all(
3992 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3993 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
3996 if !ty::type_is_machine(e) {
3997 span_err!(tcx.sess, sp, E0077,
3998 "SIMD vector element type should be machine type");
4006 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4007 vs: &[ast::P<ast::Variant>]) {
4008 for &v in vs.iter() {
4010 ast::TupleVariantKind(ref args) if args.len() > 0 => {
4011 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4012 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4013 let len = arg_tys.len();
4017 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4018 // Allow the last field in an enum to be unsized.
4019 // We want to do this so that we can support smart pointers.
4020 // A struct value with an unsized final field is itself
4021 // unsized and we must track this in the type system.
4022 if !ty::type_is_sized(ccx.tcx, *t) {
4023 span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4024 "type `{}` is dynamically sized. dynamically sized types may only \
4025 appear as the final type in a variant",
4026 ppaux::ty_to_string(ccx.tcx, *t));
4030 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
4036 pub fn check_enum_variants(ccx: &CrateCtxt,
4038 vs: &[ast::P<ast::Variant>],
4041 fn disr_in_range(ccx: &CrateCtxt,
4043 disr: ty::Disr) -> bool {
4044 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4046 ast::TyU8 => disr as u8 as Disr == disr,
4047 ast::TyU16 => disr as u16 as Disr == disr,
4048 ast::TyU32 => disr as u32 as Disr == disr,
4049 ast::TyU64 => disr as u64 as Disr == disr,
4050 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4053 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4055 ast::TyI8 => disr as i8 as Disr == disr,
4056 ast::TyI16 => disr as i16 as Disr == disr,
4057 ast::TyI32 => disr as i32 as Disr == disr,
4058 ast::TyI64 => disr as i64 as Disr == disr,
4059 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4063 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4064 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4068 fn do_check(ccx: &CrateCtxt,
4069 vs: &[ast::P<ast::Variant>],
4071 hint: attr::ReprAttr)
4072 -> Vec<Rc<ty::VariantInfo>> {
4074 let rty = ty::node_id_to_type(ccx.tcx, id);
4075 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4076 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4077 let mut prev_disr_val: Option<ty::Disr> = None;
4079 for &v in vs.iter() {
4081 // If the discriminant value is specified explicitly in the enum check whether the
4082 // initialization expression is valid, otherwise use the last value plus one.
4083 let mut current_disr_val = match prev_disr_val {
4084 Some(prev_disr_val) => prev_disr_val + 1,
4085 None => ty::INITIAL_DISCRIMINANT_VALUE
4088 match v.node.disr_expr {
4090 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
4092 let inh = blank_inherited_fields(ccx);
4093 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4094 let declty = match hint {
4095 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
4096 attr::ReprInt(_, attr::SignedInt(ity)) => {
4097 ty::mk_mach_int(ity)
4099 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4100 ty::mk_mach_uint(ity)
4103 check_const_with_ty(&fcx, e.span, &*e, declty);
4104 // check_expr (from check_const pass) doesn't guarantee
4105 // that the expression is in a form that eval_const_expr can
4106 // handle, so we may still get an internal compiler error
4108 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
4109 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4110 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4112 span_err!(ccx.tcx.sess, e.span, E0079,
4113 "expected signed integer constant");
4116 span_err!(ccx.tcx.sess, e.span, E0080,
4117 "expected constant: {}", *err);
4124 // Check for duplicate discriminant values
4125 if disr_vals.contains(¤t_disr_val) {
4126 span_err!(ccx.tcx.sess, v.span, E0081,
4127 "discriminant value already exists");
4129 // Check for unrepresentable discriminant values
4131 attr::ReprAny | attr::ReprExtern => (),
4132 attr::ReprInt(sp, ity) => {
4133 if !disr_in_range(ccx, ity, current_disr_val) {
4134 span_err!(ccx.tcx.sess, v.span, E0082,
4135 "discriminant value outside specified type");
4136 span_note!(ccx.tcx.sess, sp,
4137 "discriminant type specified here");
4141 disr_vals.push(current_disr_val);
4143 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
4145 prev_disr_val = Some(current_disr_val);
4147 variants.push(variant_info);
4153 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
4154 if hint != attr::ReprAny && vs.len() <= 1 {
4156 span_err!(ccx.tcx.sess, sp, E0083,
4157 "unsupported representation for univariant enum");
4159 span_err!(ccx.tcx.sess, sp, E0084,
4160 "unsupported representation for zero-variant enum");
4164 let variants = do_check(ccx, vs, id, hint);
4166 // cache so that ty::enum_variants won't repeat this work
4167 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4169 check_representable(ccx.tcx, sp, id, "enum");
4171 // Check that it is possible to instantiate this enum:
4173 // This *sounds* like the same that as representable, but it's
4174 // not. See def'n of `check_instantiable()` for details.
4175 check_instantiable(ccx.tcx, sp, id);
4178 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4179 lookup_def_ccx(fcx.ccx, sp, id)
4182 // Returns the type parameter count and the type for the given definition.
4183 pub fn polytype_for_def(fcx: &FnCtxt,
4188 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4189 def::DefBinding(nid, _) => {
4190 let typ = fcx.local_ty(sp, nid);
4191 return no_params(typ);
4193 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4194 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4195 def::DefStruct(id) => {
4196 return ty::lookup_item_type(fcx.ccx.tcx, id);
4198 def::DefUpvar(_, inner, _, _) => {
4199 return polytype_for_def(fcx, sp, *inner);
4204 def::DefTyParam(..)=> {
4205 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4207 def::DefMod(..) | def::DefForeignMod(..) => {
4208 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4210 def::DefUse(..) => {
4211 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4213 def::DefRegion(..) => {
4214 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4216 def::DefTyParamBinder(..) => {
4217 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4219 def::DefLabel(..) => {
4220 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4222 def::DefSelfTy(..) => {
4223 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4225 def::DefMethod(..) => {
4226 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4231 // Instantiates the given path, which must refer to an item with the given
4232 // number of type parameters and type.
4233 pub fn instantiate_path(fcx: &FnCtxt,
4238 node_id: ast::NodeId) {
4239 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4240 path.repr(fcx.tcx()),
4241 def.repr(fcx.tcx()),
4243 polytype.repr(fcx.tcx()));
4245 // We need to extract the type parameters supplied by the user in
4246 // the path `path`. Due to the current setup, this is a bit of a
4247 // tricky-process; the problem is that resolve only tells us the
4248 // end-point of the path resolution, and not the intermediate steps.
4249 // Luckily, we can (at least for now) deduce the intermediate steps
4250 // just from the end-point.
4252 // There are basically three cases to consider:
4254 // 1. Reference to a *type*, such as a struct or enum:
4256 // mod a { struct Foo<T> { ... } }
4258 // Because we don't allow types to be declared within one
4259 // another, a path that leads to a type will always look like
4260 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4261 // that only the final segment can have type parameters, and
4262 // they are located in the TypeSpace.
4264 // *Note:* Generally speaking, references to types don't
4265 // actually pass through this function, but rather the
4266 // `ast_ty_to_ty` function in `astconv`. However, in the case
4267 // of struct patterns (and maybe literals) we do invoke
4268 // `instantiate_path` to get the general type of an instance of
4269 // a struct. (In these cases, there are actually no type
4270 // parameters permitted at present, but perhaps we will allow
4271 // them in the future.)
4273 // 1b. Reference to a enum variant or tuple-like struct:
4275 // struct foo<T>(...)
4276 // enum E<T> { foo(...) }
4278 // In these cases, the parameters are declared in the type
4281 // 2. Reference to a *fn item*:
4285 // In this case, the path will again always have the form
4286 // `a::b::foo::<T>` where only the final segment should have
4287 // type parameters. However, in this case, those parameters are
4288 // declared on a value, and hence are in the `FnSpace`.
4290 // 3. Reference to a *method*:
4292 // impl<A> SomeStruct<A> {
4296 // Here we can have a path like
4297 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4298 // may appear in two places. The penultimate segment,
4299 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4300 // final segment, `foo::<B>` contains parameters in fn space.
4302 // The first step then is to categorize the segments appropriately.
4304 assert!(path.segments.len() >= 1);
4305 let mut segment_spaces;
4307 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4308 def::DefSelfTy(..) |
4309 def::DefStruct(..) |
4310 def::DefVariant(..) |
4311 def::DefTyParamBinder(..) |
4314 def::DefPrimTy(..) |
4315 def::DefTyParam(..) => {
4316 // Everything but the final segment should have no
4317 // parameters at all.
4318 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4319 segment_spaces.push(Some(subst::TypeSpace));
4322 // Case 2. Reference to a top-level value.
4324 def::DefStatic(..) => {
4325 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4326 segment_spaces.push(Some(subst::FnSpace));
4329 // Case 3. Reference to a method.
4330 def::DefStaticMethod(..) => {
4331 assert!(path.segments.len() >= 2);
4332 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4333 segment_spaces.push(Some(subst::TypeSpace));
4334 segment_spaces.push(Some(subst::FnSpace));
4337 // Other cases. Various nonsense that really shouldn't show up
4338 // here. If they do, an error will have been reported
4339 // elsewhere. (I hope)
4341 def::DefForeignMod(..) |
4344 def::DefMethod(..) |
4345 def::DefBinding(..) |
4347 def::DefRegion(..) |
4349 def::DefUpvar(..) => {
4350 segment_spaces = Vec::from_elem(path.segments.len(), None);
4353 assert_eq!(segment_spaces.len(), path.segments.len());
4355 debug!("segment_spaces={}", segment_spaces);
4357 // Next, examine the definition, and determine how many type
4358 // parameters we expect from each space.
4359 let type_defs = &polytype.generics.types;
4360 let region_defs = &polytype.generics.regions;
4362 // Now that we have categorized what space the parameters for each
4363 // segment belong to, let's sort out the parameters that the user
4364 // provided (if any) into their appropriate spaces. We'll also report
4365 // errors if type parameters are provided in an inappropriate place.
4366 let mut substs = Substs::empty();
4367 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4370 report_error_if_segment_contains_type_parameters(fcx, segment);
4374 push_explicit_parameters_from_segment_to_substs(fcx,
4384 // Now we have to compare the types that the user *actually*
4385 // provided against the types that were *expected*. If the user
4386 // did not provide any types, then we want to substitute inference
4387 // variables. If the user provided some types, we may still need
4388 // to add defaults. If the user provided *too many* types, that's
4390 for &space in ParamSpace::all().iter() {
4391 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4392 assert_eq!(substs.types.len(space), type_defs.len(space));
4394 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4395 assert_eq!(substs.regions().len(space), region_defs.len(space));
4398 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4402 fn report_error_if_segment_contains_type_parameters(
4404 segment: &ast::PathSegment)
4406 for typ in segment.types.iter() {
4407 span_err!(fcx.tcx().sess, typ.span, E0085,
4408 "type parameters may not appear here");
4412 for lifetime in segment.lifetimes.iter() {
4413 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4414 "lifetime parameters may not appear here");
4419 fn push_explicit_parameters_from_segment_to_substs(
4421 space: subst::ParamSpace,
4422 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4423 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4424 segment: &ast::PathSegment,
4425 substs: &mut Substs)
4428 * Finds the parameters that the user provided and adds them
4429 * to `substs`. If too many parameters are provided, then
4430 * reports an error and clears the output vector.
4432 * We clear the output vector because that will cause the
4433 * `adjust_XXX_parameters()` later to use inference
4434 * variables. This seems less likely to lead to derived
4437 * Note that we *do not* check for *too few* parameters here.
4438 * Due to the presence of defaults etc that is more
4439 * complicated. I wanted however to do the reporting of *too
4440 * many* parameters here because we can easily use the precise
4441 * span of the N+1'th parameter.
4445 let type_count = type_defs.len(space);
4446 assert_eq!(substs.types.len(space), 0);
4447 for (i, &typ) in segment.types.iter().enumerate() {
4448 let t = fcx.to_ty(&*typ);
4450 substs.types.push(space, t);
4451 } else if i == type_count {
4452 span_err!(fcx.tcx().sess, typ.span, E0087,
4453 "too many type parameters provided: \
4454 expected at most {} parameter(s) \
4455 but found {} parameter(s)",
4456 type_count, segment.types.len());
4457 substs.types.truncate(space, 0);
4463 let region_count = region_defs.len(space);
4464 assert_eq!(substs.regions().len(space), 0);
4465 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4466 let r = ast_region_to_region(fcx.tcx(), lifetime);
4467 if i < region_count {
4468 substs.mut_regions().push(space, r);
4469 } else if i == region_count {
4470 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4471 "too many lifetime parameters provided: \
4472 expected {} parameter(s) but found {} parameter(s)",
4474 segment.lifetimes.len());
4475 substs.mut_regions().truncate(space, 0);
4481 fn adjust_type_parameters(
4485 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4486 substs: &mut Substs)
4488 let provided_len = substs.types.len(space);
4489 let desired = defs.get_slice(space);
4490 let required_len = desired.iter()
4491 .take_while(|d| d.default.is_none())
4494 debug!("adjust_type_parameters(space={}, \
4503 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4504 assert!(provided_len <= desired.len());
4506 // Nothing specified at all: supply inference variables for
4508 if provided_len == 0 {
4509 substs.types.replace(space,
4510 fcx.infcx().next_ty_vars(desired.len()));
4514 // Too few parameters specified: report an error and use Err
4516 if provided_len < required_len {
4518 if desired.len() != required_len { "at least " } else { "" };
4519 span_err!(fcx.tcx().sess, span, E0089,
4520 "too few type parameters provided: expected {}{} parameter(s) \
4521 but found {} parameter(s)",
4522 qualifier, required_len, provided_len);
4523 substs.types.replace(space,
4524 Vec::from_elem(desired.len(), ty::mk_err()));
4528 // Otherwise, add in any optional parameters that the user
4529 // omitted. The case of *too many* parameters is handled
4531 // push_explicit_parameters_from_segment_to_substs(). Note
4532 // that the *default* type are expressed in terms of all prior
4533 // parameters, so we have to substitute as we go with the
4534 // partial substitution that we have built up.
4535 for i in range(provided_len, desired.len()) {
4536 let default = desired[i].default.unwrap();
4537 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4538 substs.types.push(space, default);
4540 assert_eq!(substs.types.len(space), desired.len());
4542 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4545 fn adjust_region_parameters(
4549 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4550 substs: &mut Substs)
4552 let provided_len = substs.mut_regions().len(space);
4553 let desired = defs.get_slice(space);
4555 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4556 assert!(provided_len <= desired.len());
4558 // If nothing was provided, just use inference variables.
4559 if provided_len == 0 {
4560 substs.mut_regions().replace(
4562 fcx.infcx().region_vars_for_defs(span, desired));
4566 // If just the right number were provided, everybody is happy.
4567 if provided_len == desired.len() {
4571 // Otherwise, too few were provided. Report an error and then
4572 // use inference variables.
4573 span_err!(fcx.tcx().sess, span, E0090,
4574 "too few lifetime parameters provided: expected {} parameter(s) \
4575 but found {} parameter(s)",
4576 desired.len(), provided_len);
4578 substs.mut_regions().replace(
4580 fcx.infcx().region_vars_for_defs(span, desired));
4584 // Resolves `typ` by a single level if `typ` is a type variable. If no
4585 // resolution is possible, then an error is reported.
4586 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4587 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4588 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4590 fcx.type_error_message(sp, |_actual| {
4591 "the type of this value must be known in this \
4592 context".to_string()
4594 demand::suptype(fcx, sp, ty::mk_err(), tp);
4600 // Returns the one-level-deep structure of the given type.
4601 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4603 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4606 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4607 let typ_s = structurally_resolved_type(fcx, sp, typ);
4608 return ty::type_is_integral(typ_s);
4611 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4612 let typ_s = structurally_resolved_type(fcx, sp, typ);
4613 return ty::type_is_uint(typ_s);
4616 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4619 mk_inner: || -> ty::mt)
4622 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4623 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4625 ast::ExprLit(..) => {
4626 // string literals and *empty slices* live in static memory
4627 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4629 ast::ExprVec(ref elements) if elements.len() == 0 => {
4630 // string literals and *empty slices* live in static memory
4631 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4633 ast::ExprRepeat(..) |
4634 ast::ExprVec(..) => {
4635 // vector literals are temporaries on the stack
4636 match fcx.tcx().region_maps.temporary_scope(e.id) {
4637 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4638 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4642 fcx.ccx.tcx.sess.span_bug(e.span,
4643 "vstore with unexpected \
4651 // Returns true if b contains a break that can exit from b
4652 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4653 // First: is there an unlabeled break immediately
4655 (loop_query(&*b, |e| {
4657 ast::ExprBreak(_) => true,
4661 // Second: is there a labeled break with label
4662 // <id> nested anywhere inside the loop?
4663 (block_query(b, |e| {
4665 ast::ExprBreak(Some(_)) => {
4666 match cx.def_map.borrow().find(&e.id) {
4667 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4675 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4677 tps: &OwnedSlice<ast::TyParam>,
4679 debug!("check_bounds_are_used(n_tps={}, ty={})",
4680 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4682 // make a vector of booleans initially false, set to true when used
4683 if tps.len() == 0u { return; }
4684 let mut tps_used = Vec::from_elem(tps.len(), false);
4686 ty::walk_ty(ty, |t| {
4687 match ty::get(t).sty {
4688 ty::ty_param(ParamTy {idx, ..}) => {
4689 debug!("Found use of ty param num {}", idx);
4690 *tps_used.get_mut(idx) = true;
4696 for (i, b) in tps_used.iter().enumerate() {
4698 span_err!(ccx.tcx.sess, span, E0091,
4699 "type parameter `{}` is unused",
4700 token::get_ident(tps.get(i).ident));
4705 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4706 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4707 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4711 let name = token::get_ident(it.ident);
4712 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4713 let split : Vec<&str> = name.get().split('_').collect();
4714 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4716 //We only care about the operation here
4717 match *split.get(1) {
4718 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4722 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4724 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4727 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4728 "min" | "umax" | "umin" => {
4729 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4733 (0, Vec::new(), ty::mk_nil())
4736 span_err!(tcx.sess, it.span, E0092,
4737 "unrecognized atomic operation function: `{}`", op);
4744 "abort" => (0, Vec::new(), ty::mk_bot()),
4745 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4747 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4748 "init" => (1u, Vec::new(), param(ccx, 0u)),
4749 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4750 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4751 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4752 "move_val_init" => {
4755 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4760 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4761 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4764 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4766 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4768 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4770 mutbl: ast::MutImmutable
4772 (1u, Vec::new(), td_ptr)
4775 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4779 ty::mk_struct(ccx.tcx, did,
4780 subst::Substs::empty())),
4782 tcx.sess.span_fatal(it.span, msg.as_slice());
4787 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4789 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4791 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4792 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4793 Ok((_, vot)) => vot,
4794 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4797 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4799 mutbl: ast::MutImmutable
4801 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4806 ty::mk_ptr(tcx, ty::mt {
4808 mutbl: ast::MutImmutable
4812 ty::mk_ptr(tcx, ty::mt {
4814 mutbl: ast::MutImmutable
4817 "copy_memory" | "copy_nonoverlapping_memory" |
4818 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4821 ty::mk_ptr(tcx, ty::mt {
4823 mutbl: ast::MutMutable
4825 ty::mk_ptr(tcx, ty::mt {
4827 mutbl: ast::MutImmutable
4833 "set_memory" | "volatile_set_memory" => {
4836 ty::mk_ptr(tcx, ty::mt {
4838 mutbl: ast::MutMutable
4845 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4846 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4849 vec!( ty::mk_f32(), ty::mk_i32() ),
4854 vec!( ty::mk_f64(), ty::mk_i32() ),
4857 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4858 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4859 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4860 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4863 vec!( ty::mk_f32(), ty::mk_f32() ),
4868 vec!( ty::mk_f64(), ty::mk_f64() ),
4871 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4872 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4873 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4874 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4875 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4876 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4877 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4878 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4879 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4880 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4883 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4888 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4891 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4892 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4893 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4894 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4895 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4896 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4897 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4898 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4899 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4900 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4901 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4902 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4903 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4904 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4905 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4906 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4907 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4908 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4909 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4910 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4911 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4912 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4913 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4914 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4915 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4916 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4917 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4918 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4919 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4920 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4921 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4924 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4926 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4928 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4929 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4930 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4932 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4933 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4934 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4936 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4937 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4938 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4940 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4941 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4942 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4944 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4945 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4946 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4948 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4949 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4950 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4952 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4953 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4954 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4956 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4957 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4958 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4961 span_err!(tcx.sess, it.span, E0093,
4962 "unrecognized intrinsic function: `{}`", *other);
4967 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4968 fn_style: ast::UnsafeFn,
4969 abi: abi::RustIntrinsic,
4977 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4978 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4979 if i_n_tps != n_tps {
4980 span_err!(tcx.sess, it.span, E0094,
4981 "intrinsic has wrong number of type \
4982 parameters: found {}, expected {}",
4985 require_same_types(tcx,
4992 format!("intrinsic has wrong type: expected `{}`",
4993 ppaux::ty_to_string(ccx.tcx, fty))