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::mem_categorization::McResult;
84 use middle::mem_categorization;
85 use middle::pat_util::pat_id_map;
88 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
90 use middle::ty::{FnSig, VariantInfo};
91 use middle::ty::{Polytype};
92 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
94 use middle::ty_fold::TypeFolder;
95 use middle::typeck::astconv::AstConv;
96 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
97 use middle::typeck::astconv;
98 use middle::typeck::check::_match::pat_ctxt;
99 use middle::typeck::check::method::{AutoderefReceiver};
100 use middle::typeck::check::method::{AutoderefReceiverFlag};
101 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
102 use middle::typeck::check::method::{DontAutoderefReceiver};
103 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
104 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
105 use middle::typeck::CrateCtxt;
106 use middle::typeck::infer::{resolve_type, force_tvar};
107 use middle::typeck::infer;
108 use middle::typeck::rscope::RegionScope;
109 use middle::typeck::{lookup_def_ccx};
110 use middle::typeck::no_params;
111 use middle::typeck::{require_same_types};
112 use middle::typeck::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
113 use middle::typeck::{TypeAndSubsts};
115 use middle::lang_items::TypeIdLangItem;
117 use util::common::{block_query, indenter, loop_query};
119 use util::ppaux::{UserString, Repr};
120 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
122 use std::cell::{Cell, RefCell};
123 use std::collections::HashMap;
124 use std::collections::hashmap::{Occupied, Vacant};
125 use std::mem::replace;
128 use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
131 use syntax::ast_util::{local_def, PostExpansionMethod};
132 use syntax::ast_util;
134 use syntax::codemap::Span;
136 use syntax::owned_slice::OwnedSlice;
137 use syntax::parse::token;
138 use syntax::print::pprust;
141 use syntax::visit::Visitor;
145 pub mod vtable2; // New trait code
153 /// Fields that are part of a `FnCtxt` which are inherited by
154 /// closures defined within the function. For example:
157 /// bar(proc() { ... })
160 /// Here, the function `foo()` and the closure passed to
161 /// `bar()` will each have their own `FnCtxt`, but they will
162 /// share the inherited fields.
163 pub struct Inherited<'a, 'tcx: 'a> {
164 infcx: infer::InferCtxt<'a, 'tcx>,
165 locals: RefCell<NodeMap<ty::t>>,
166 param_env: ty::ParameterEnvironment,
169 node_types: RefCell<NodeMap<ty::t>>,
170 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
171 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
172 method_map: MethodMap,
173 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
174 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
175 object_cast_map: ObjectCastMap,
177 // A mapping from each fn's id to its signature, with all bound
178 // regions replaced with free ones. Unlike the other tables, this
179 // one is never copied into the tcx: it is only used by regionck.
180 fn_sig_map: RefCell<NodeMap<Vec<ty::t>>>,
182 // A set of constraints that regionck must validate. Each
183 // constraint has the form `T:'a`, meaning "some type `T` must
184 // outlive the lifetime 'a". These constraints derive from
185 // instantiated type parameters. So if you had a struct defined
188 // struct Foo<T:'static> { ... }
190 // then in some expression `let x = Foo { ... }` it will
191 // instantiate the type parameter `T` with a fresh type `$0`. At
192 // the same time, it will record a region obligation of
193 // `$0:'static`. This will get checked later by regionck. (We
194 // can't generally check these things right away because we have
195 // to wait until types are resolved.)
197 // These are stored in a map keyed to the id of the innermost
198 // enclosing fn body / static initializer expression. This is
199 // because the location where the obligation was incurred can be
200 // relevant with respect to which sublifetime assumptions are in
201 // place. The reason that we store under the fn-id, and not
202 // something more fine-grained, is so that it is easier for
203 // regionck to be sure that it has found *all* the region
204 // obligations (otherwise, it's easy to fail to walk to a
205 // particular node-id).
206 region_obligations: RefCell<NodeMap<Vec<RegionObligation>>>,
208 // Tracks trait obligations incurred during this function body.
209 fulfillment_cx: RefCell<traits::FulfillmentContext>,
212 struct RegionObligation {
213 sub_region: ty::Region,
215 origin: infer::SubregionOrigin,
218 /// When type-checking an expression, we propagate downward
219 /// whatever type hint we are able in the form of an `Expectation`.
221 /// We know nothing about what type this expression should have.
224 /// This expression should have the type given (or some subtype)
225 ExpectHasType(ty::t),
227 /// This expression will be cast to the `ty::t`
228 ExpectCastableToType(ty::t),
232 pub struct FnStyleState {
233 pub def: ast::NodeId,
234 pub fn_style: ast::FnStyle,
239 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
240 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
243 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
244 match self.fn_style {
245 // If this unsafe, then if the outer function was already marked as
246 // unsafe we shouldn't attribute the unsafe'ness to the block. This
247 // way the block can be warned about instead of ignoring this
248 // extraneous block (functions are never warned about).
249 ast::UnsafeFn if self.from_fn => *self,
252 let (fn_style, def) = match blk.rules {
253 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
254 ast::DefaultBlock => (fn_style, self.def),
256 FnStyleState{ def: def,
264 /// Whether `check_binop` is part of an assignment or not.
265 /// Used to know whether we allow user overloads and to print
266 /// better messages on error.
267 #[deriving(PartialEq)]
268 enum IsBinopAssignment{
274 pub struct FnCtxt<'a, 'tcx: 'a> {
275 body_id: ast::NodeId,
277 // This flag is set to true if, during the writeback phase, we encounter
278 // a type error in this function.
279 writeback_errors: Cell<bool>,
281 // Number of errors that had been reported when we started
282 // checking this function. On exit, if we find that *more* errors
283 // have been reported, we will skip regionck and other work that
284 // expects the types within the function to be consistent.
285 err_count_on_creation: uint,
289 ps: RefCell<FnStyleState>,
291 inh: &'a Inherited<'a, 'tcx>,
293 ccx: &'a CrateCtxt<'a, 'tcx>,
296 impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
297 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
300 fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
303 fn node_method_ty(&self, method_call: typeck::MethodCall)
305 self.inh.method_map.borrow().find(&method_call).map(|m| m.ty)
307 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
308 &self.inh.adjustments
310 fn is_method_call(&self, id: ast::NodeId) -> bool {
311 self.inh.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
313 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
314 self.tcx().temporary_scope(rvalue_id)
316 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
317 self.inh.upvar_borrow_map.borrow().get_copy(&upvar_id)
319 fn capture_mode(&self, closure_expr_id: ast::NodeId)
320 -> ast::CaptureClause {
321 self.ccx.tcx.capture_mode(closure_expr_id)
323 fn unboxed_closures<'a>(&'a self) -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
324 &self.inh.unboxed_closures
328 impl<'a, 'tcx> Inherited<'a, 'tcx> {
329 fn new(tcx: &'a ty::ctxt<'tcx>,
330 param_env: ty::ParameterEnvironment)
331 -> Inherited<'a, 'tcx> {
333 infcx: infer::new_infer_ctxt(tcx),
334 locals: RefCell::new(NodeMap::new()),
335 param_env: param_env,
336 node_types: RefCell::new(NodeMap::new()),
337 item_substs: RefCell::new(NodeMap::new()),
338 adjustments: RefCell::new(NodeMap::new()),
339 method_map: RefCell::new(FnvHashMap::new()),
340 object_cast_map: RefCell::new(NodeMap::new()),
341 upvar_borrow_map: RefCell::new(HashMap::new()),
342 unboxed_closures: RefCell::new(DefIdMap::new()),
343 fn_sig_map: RefCell::new(NodeMap::new()),
344 region_obligations: RefCell::new(NodeMap::new()),
345 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
350 // Used by check_const and check_enum_variants
351 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
352 inh: &'a Inherited<'a, 'tcx>,
354 body_id: ast::NodeId)
355 -> FnCtxt<'a, 'tcx> {
358 writeback_errors: Cell::new(false),
359 err_count_on_creation: ccx.tcx.sess.err_count(),
361 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
367 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
368 -> Inherited<'a, 'tcx> {
369 // It's kind of a kludge to manufacture a fake function context
370 // and statement context, but we might as well do write the code only once
371 let param_env = ty::empty_parameter_environment();
372 Inherited::new(ccx.tcx, param_env)
375 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
377 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
378 fn visit_item(&mut self, i: &ast::Item) {
379 check_item(self.ccx, i);
380 visit::walk_item(self, i);
384 pub fn check_item_types(ccx: &CrateCtxt) {
385 let krate = ccx.tcx.map.krate();
386 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
387 visit::walk_crate(&mut visit, krate);
389 // If types are not well-formed, it leads to all manner of errors
390 // downstream, so stop reporting errors at this point.
391 ccx.tcx.sess.abort_if_errors();
393 let mut visit = CheckItemTypesVisitor { ccx: ccx };
394 visit::walk_crate(&mut visit, krate);
396 ccx.tcx.sess.abort_if_errors();
399 fn check_bare_fn(ccx: &CrateCtxt,
404 param_env: ty::ParameterEnvironment) {
405 // Compute the fty from point of view of inside fn
406 // (replace any type-scheme with a type)
407 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
409 match ty::get(fty).sty {
410 ty::ty_bare_fn(ref fn_ty) => {
411 let inh = Inherited::new(ccx.tcx, param_env);
412 let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
413 decl, id, body, &inh);
415 vtable2::select_all_fcx_obligations_or_error(&fcx);
416 regionck::regionck_fn(&fcx, id, body);
417 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
419 _ => ccx.tcx.sess.impossible_case(body.span,
420 "check_bare_fn: function type expected")
424 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
425 fcx: &'a FnCtxt<'a, 'tcx>
428 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
429 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<ty::t>) -> ty::t {
432 // infer the variable's type
433 let var_id = self.fcx.infcx().next_ty_var_id();
434 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
435 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
439 // take type that the user specified
440 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
447 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
448 // Add explicitly-declared locals.
449 fn visit_local(&mut self, local: &ast::Local) {
450 let o_ty = match local.ty.node {
451 ast::TyInfer => None,
452 _ => Some(self.fcx.to_ty(&*local.ty))
454 self.assign(local.span, local.id, o_ty);
455 debug!("Local variable {} is assigned type {}",
456 self.fcx.pat_to_string(&*local.pat),
457 self.fcx.infcx().ty_to_string(
458 self.fcx.inh.locals.borrow().get_copy(&local.id)));
459 visit::walk_local(self, local);
462 // Add pattern bindings.
463 fn visit_pat(&mut self, p: &ast::Pat) {
465 ast::PatIdent(_, ref path1, _)
466 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
467 let var_ty = self.assign(p.span, p.id, None);
469 self.fcx.require_type_is_sized(var_ty, p.span,
470 traits::VariableType(p.id));
472 debug!("Pattern binding {} is assigned to {} with type {}",
473 token::get_ident(path1.node),
474 self.fcx.infcx().ty_to_string(
475 self.fcx.inh.locals.borrow().get_copy(&p.id)),
476 var_ty.repr(self.fcx.tcx()));
480 visit::walk_pat(self, p);
483 fn visit_block(&mut self, b: &ast::Block) {
484 // non-obvious: the `blk` variable maps to region lb, so
485 // we have to keep this up-to-date. This
486 // is... unfortunate. It'd be nice to not need this.
487 visit::walk_block(self, b);
490 // Since an expr occurs as part of the type fixed size arrays we
491 // need to record the type for that node
492 fn visit_ty(&mut self, t: &ast::Ty) {
494 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
495 self.visit_ty(&**ty);
496 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
498 _ => visit::walk_ty(self, t)
502 // Don't descend into fns and items
503 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
504 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
505 fn visit_item(&mut self, _: &ast::Item) { }
509 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
510 fn_style: ast::FnStyle,
511 fn_style_id: ast::NodeId,
516 inherited: &'a Inherited<'a, 'tcx>)
517 -> FnCtxt<'a, 'tcx> {
519 * Helper used by check_bare_fn and check_expr_fn. Does the
520 * grungy work of checking a function body and returns the
521 * function context used for that purpose, since in the case of a
522 * fn item there is still a bit more to do.
525 * - inherited: other fields inherited from the enclosing fn (if any)
529 let err_count_on_creation = tcx.sess.err_count();
531 // First, we have to replace any bound regions in the fn type with free ones.
532 // The free region references will be bound the node_id of the body block.
533 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
534 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
537 let arg_tys = fn_sig.inputs.as_slice();
538 let ret_ty = fn_sig.output;
540 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
545 // Create the function context. This is either derived from scratch or,
546 // in the case of function expressions, based on the outer context.
549 writeback_errors: Cell::new(false),
550 err_count_on_creation: err_count_on_creation,
552 ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)),
557 // Remember return type so that regionck can access it later.
558 let fn_sig_tys: Vec<ty::t> =
560 .chain([ret_ty].iter())
563 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
565 fn_sig_tys.repr(tcx));
568 .insert(fn_id, fn_sig_tys);
571 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
573 // Add formal parameters.
574 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
575 // Create type variables for each argument.
576 pat_util::pat_bindings(
579 |_bm, pat_id, sp, _path| {
580 let var_ty = visit.assign(sp, pat_id, None);
581 fcx.require_type_is_sized(var_ty, sp,
582 traits::VariableType(pat_id));
585 // Check the pattern.
588 map: pat_id_map(&tcx.def_map, &*input.pat),
590 _match::check_pat(&pcx, &*input.pat, *arg_ty);
593 visit.visit_block(body);
596 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
598 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
599 fcx.write_ty(input.id, *arg);
605 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
606 assert!(field.id.krate == ast::LOCAL_CRATE);
607 let item = match tcx.map.find(struct_id.node) {
608 Some(ast_map::NodeItem(item)) => item,
609 None => fail!("node not in ast map: {}", struct_id.node),
610 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
614 ast::ItemStruct(ref struct_def, _) => {
615 match struct_def.fields.iter().find(|f| match f.node.kind {
616 ast::NamedField(ident, _) => ident.name == field.name,
622 .bug(format!("Could not find field {}",
623 token::get_name(field.name)).as_slice())
627 _ => tcx.sess.bug("Field found outside of a struct?"),
631 // Check struct fields are uniquely named wrt parents.
632 fn check_for_field_shadowing(tcx: &ty::ctxt,
634 let struct_fields = tcx.struct_fields.borrow();
635 let fields = struct_fields.get(&id);
637 let superstructs = tcx.superstructs.borrow();
638 let super_struct = superstructs.get(&id);
639 match *super_struct {
641 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
642 for f in fields.iter() {
643 match super_fields.iter().find(|sf| f.name == sf.name) {
644 Some(prev_field) => {
645 span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
646 "field `{}` hides field declared in super-struct",
647 token::get_name(f.name));
648 span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
649 "previously declared here");
659 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
662 check_representable(tcx, span, id, "struct");
663 check_instantiable(tcx, span, id);
665 // Check there are no overlapping fields in super-structs
666 check_for_field_shadowing(tcx, local_def(id));
668 if ty::lookup_simd(tcx, local_def(id)) {
669 check_simd(tcx, span, id);
673 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
674 debug!("check_item(it.id={}, it.ident={})",
676 ty::item_path_str(ccx.tcx, local_def(it.id)));
677 let _indenter = indenter();
680 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
681 ast::ItemEnum(ref enum_definition, _) => {
682 check_enum_variants(ccx,
684 enum_definition.variants.as_slice(),
687 ast::ItemFn(ref decl, _, _, _, ref body) => {
688 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
689 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
690 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
692 ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
693 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
695 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
696 for impl_item in impl_items.iter() {
698 ast::MethodImplItem(ref m) => {
699 check_method_body(ccx, &impl_pty.generics, &**m);
701 ast::TypeImplItem(_) => {
702 // Nothing to do here.
707 match *opt_trait_ref {
708 Some(ref ast_trait_ref) => {
710 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
711 check_impl_items_against_trait(ccx,
715 impl_items.as_slice());
721 ast::ItemTrait(_, _, _, ref trait_methods) => {
722 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
723 for trait_method in trait_methods.iter() {
724 match *trait_method {
725 RequiredMethod(..) => {
726 // Nothing to do, since required methods don't have
729 ProvidedMethod(ref m) => {
730 check_method_body(ccx, &trait_def.generics, &**m);
732 TypeTraitItem(_) => {
738 ast::ItemStruct(..) => {
739 check_struct(ccx, it.id, it.span);
741 ast::ItemTy(ref t, ref generics) => {
742 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
743 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
745 ast::ItemForeignMod(ref m) => {
746 if m.abi == abi::RustIntrinsic {
747 for item in m.items.iter() {
748 check_intrinsic_type(ccx, &**item);
751 for item in m.items.iter() {
752 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
753 if !pty.generics.types.is_empty() {
754 span_err!(ccx.tcx.sess, item.span, E0044,
755 "foreign items may not have type parameters");
759 ast::ForeignItemFn(ref fn_decl, _) => {
760 if fn_decl.variadic && m.abi != abi::C {
761 span_err!(ccx.tcx.sess, item.span, E0045,
762 "variadic function must have C calling convention");
770 _ => {/* nothing to do */ }
774 fn check_method_body(ccx: &CrateCtxt,
775 item_generics: &ty::Generics,
776 method: &ast::Method) {
778 * Type checks a method body.
781 * - `item_generics`: generics defined on the impl/trait that contains
783 * - `self_bound`: bound for the `Self` type parameter, if any
784 * - `method`: the method definition
787 debug!("check_method_body(item_generics={}, method.id={})",
788 item_generics.repr(ccx.tcx),
790 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
792 let fty = ty::node_id_to_type(ccx.tcx, method.id);
795 &*method.pe_fn_decl(),
802 fn check_impl_items_against_trait(ccx: &CrateCtxt,
804 ast_trait_ref: &ast::TraitRef,
805 impl_trait_ref: &ty::TraitRef,
806 impl_items: &[ast::ImplItem]) {
807 // Locate trait methods
809 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
811 // Check existing impl methods to see if they are both present in trait
812 // and compatible with trait signature
813 for impl_item in impl_items.iter() {
815 ast::MethodImplItem(ref impl_method) => {
816 let impl_method_def_id = local_def(impl_method.id);
817 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
820 // If this is an impl of a trait method, find the
821 // corresponding method definition in the trait.
822 let opt_trait_method_ty =
825 ti.ident().name == impl_item_ty.ident()
828 match opt_trait_method_ty {
829 Some(trait_method_ty) => {
830 match (trait_method_ty, &impl_item_ty) {
831 (&ty::MethodTraitItem(ref trait_method_ty),
832 &ty::MethodTraitItem(ref impl_method_ty)) => {
833 compare_impl_method(ccx.tcx,
836 impl_method.pe_body().id,
838 &impl_trait_ref.substs);
841 // This is span_bug as it should have already been
842 // caught in resolve.
844 .span_bug(impl_method.span,
845 format!("item `{}` is of a \
846 different kind from \
849 impl_item_ty.ident()),
850 pprust::path_to_string(
851 &ast_trait_ref.path))
857 // This is span_bug as it should have already been
858 // caught in resolve.
862 "method `{}` is not a member of trait `{}`",
863 token::get_ident(impl_item_ty.ident()),
864 pprust::path_to_string(
865 &ast_trait_ref.path)).as_slice());
869 ast::TypeImplItem(ref typedef) => {
870 let typedef_def_id = local_def(typedef.id);
871 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
874 // If this is an impl of an associated type, find the
875 // corresponding type definition in the trait.
876 let opt_associated_type =
879 ti.ident().name == typedef_ty.ident().name
881 match opt_associated_type {
882 Some(associated_type) => {
883 match (associated_type, &typedef_ty) {
884 (&ty::TypeTraitItem(_),
885 &ty::TypeTraitItem(_)) => {}
887 // This is `span_bug` as it should have
888 // already been caught in resolve.
890 .span_bug(typedef.span,
891 format!("item `{}` is of a \
892 different kind from \
896 pprust::path_to_string(
897 &ast_trait_ref.path))
903 // This is `span_bug` as it should have already been
904 // caught in resolve.
908 "associated type `{}` is not a member of \
910 token::get_ident(typedef_ty.ident()),
911 pprust::path_to_string(
912 &ast_trait_ref.path)).as_slice());
919 // Check for missing items from trait
920 let provided_methods = ty::provided_trait_methods(tcx,
921 impl_trait_ref.def_id);
922 let mut missing_methods = Vec::new();
923 for trait_item in trait_items.iter() {
925 ty::MethodTraitItem(ref trait_method) => {
927 impl_items.iter().any(|ii| {
929 ast::MethodImplItem(ref m) => {
930 m.pe_ident().name == trait_method.ident.name
932 ast::TypeImplItem(_) => false,
936 provided_methods.iter().any(
937 |m| m.ident.name == trait_method.ident.name);
938 if !is_implemented && !is_provided {
939 missing_methods.push(
941 token::get_ident(trait_method.ident)));
944 ty::TypeTraitItem(ref associated_type) => {
945 let is_implemented = impl_items.iter().any(|ii| {
947 ast::TypeImplItem(ref typedef) => {
948 typedef.ident.name == associated_type.ident.name
950 ast::MethodImplItem(_) => false,
954 missing_methods.push(
956 token::get_ident(associated_type.ident)));
962 if !missing_methods.is_empty() {
963 span_err!(tcx.sess, impl_span, E0046,
964 "not all trait items implemented, missing: {}",
965 missing_methods.connect(", "));
970 * Checks that a method from an impl conforms to the signature of
971 * the same method as declared in the trait.
975 * - impl_generics: the generics declared on the impl itself (not the method!)
976 * - impl_m: type of the method we are checking
977 * - impl_m_span: span to use for reporting errors
978 * - impl_m_body_id: id of the method body
979 * - trait_m: the method in the trait
980 * - trait_to_impl_substs: the substitutions used on the type of the trait
982 fn compare_impl_method(tcx: &ty::ctxt,
985 impl_m_body_id: ast::NodeId,
986 trait_m: &ty::Method,
987 trait_to_impl_substs: &subst::Substs) {
988 debug!("compare_impl_method(trait_to_impl_substs={})",
989 trait_to_impl_substs.repr(tcx));
990 let infcx = infer::new_infer_ctxt(tcx);
992 // Try to give more informative error messages about self typing
993 // mismatches. Note that any mismatch will also be detected
994 // below, where we construct a canonical function type that
995 // includes the self parameter as a normal parameter. It's just
996 // that the error messages you get out of this code are a bit more
997 // inscrutable, particularly for cases where one method has no
999 match (&trait_m.explicit_self, &impl_m.explicit_self) {
1000 (&ty::StaticExplicitSelfCategory,
1001 &ty::StaticExplicitSelfCategory) => {}
1002 (&ty::StaticExplicitSelfCategory, _) => {
1005 format!("method `{}` has a `{}` declaration in the impl, \
1006 but not in the trait",
1007 token::get_ident(trait_m.ident),
1008 ppaux::explicit_self_category_to_str(
1009 &impl_m.explicit_self)).as_slice());
1012 (_, &ty::StaticExplicitSelfCategory) => {
1015 format!("method `{}` has a `{}` declaration in the trait, \
1016 but not in the impl",
1017 token::get_ident(trait_m.ident),
1018 ppaux::explicit_self_category_to_str(
1019 &trait_m.explicit_self)).as_slice());
1023 // Let the type checker catch other errors below
1027 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
1028 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
1029 if num_impl_m_type_params != num_trait_m_type_params {
1030 span_err!(tcx.sess, impl_m_span, E0049,
1031 "method `{}` has {} type parameter{} \
1032 but its trait declaration has {} type parameter{}",
1033 token::get_ident(trait_m.ident),
1034 num_impl_m_type_params,
1035 if num_impl_m_type_params == 1 {""} else {"s"},
1036 num_trait_m_type_params,
1037 if num_trait_m_type_params == 1 {""} else {"s"});
1041 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
1042 span_err!(tcx.sess, impl_m_span, E0050,
1043 "method `{}` has {} parameter{} \
1044 but the declaration in trait `{}` has {}",
1045 token::get_ident(trait_m.ident),
1046 impl_m.fty.sig.inputs.len(),
1047 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
1048 ty::item_path_str(tcx, trait_m.def_id),
1049 trait_m.fty.sig.inputs.len());
1053 // This code is best explained by example. Consider a trait:
1056 // fn method<'a,M>(t: T, m: &'a M) -> Self;
1061 // impl<'i, U> Trait<&'i U> for Foo {
1062 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
1065 // We wish to decide if those two method types are compatible.
1067 // We start out with trait_to_impl_substs, that maps the trait type
1068 // parameters to impl type parameters:
1070 // trait_to_impl_substs = {T => &'i U, Self => Foo}
1072 // We create a mapping `dummy_substs` that maps from the impl type
1073 // parameters to fresh types and regions. For type parameters,
1074 // this is the identity transform, but we could as well use any
1075 // skolemized types. For regions, we convert from bound to free
1076 // regions (Note: but only early-bound regions, i.e., those
1077 // declared on the impl or used in type parameter bounds).
1079 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1081 // Now we can apply skol_substs to the type of the impl method
1082 // to yield a new function type in terms of our fresh, skolemized
1085 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1087 // We now want to extract and substitute the type of the *trait*
1088 // method and compare it. To do so, we must create a compound
1089 // substitution by combining trait_to_impl_substs and
1090 // impl_to_skol_substs, and also adding a mapping for the method
1091 // type parameters. We extend the mapping to also include
1092 // the method parameters.
1094 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1096 // Applying this to the trait method type yields:
1098 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1100 // This type is also the same but the name of the bound region ('a
1101 // vs 'b). However, the normal subtyping rules on fn types handle
1102 // this kind of equivalency just fine.
1104 // Create mapping from impl to skolemized.
1106 impl_m.generics.types.map(
1107 |d| ty::mk_param_from_def(tcx, d));
1109 impl_m.generics.regions.map(
1110 |l| ty::free_region_from_def(impl_m_body_id, l));
1111 let impl_to_skol_substs =
1112 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1114 // Create mapping from trait to skolemized.
1115 let trait_to_skol_substs =
1116 trait_to_impl_substs
1117 .subst(tcx, &impl_to_skol_substs)
1118 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
1119 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
1121 // Check region bounds.
1122 if !check_region_bounds_on_impl_method(tcx,
1127 &trait_to_skol_substs,
1128 &impl_to_skol_substs) {
1133 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
1134 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
1135 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1136 // Check that the impl does not require any builtin-bounds
1137 // that the trait does not guarantee:
1139 impl_param_def.bounds.builtin_bounds -
1140 trait_param_def.bounds.builtin_bounds;
1141 if !extra_bounds.is_empty() {
1142 span_err!(tcx.sess, impl_m_span, E0051,
1143 "in method `{}`, type parameter {} requires `{}`, \
1144 which is not required by the corresponding type parameter \
1145 in the trait declaration",
1146 token::get_ident(trait_m.ident),
1148 extra_bounds.user_string(tcx));
1152 // Check that the trait bounds of the trait imply the bounds of its
1155 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1156 // traits, but I doubt that'll be wanted often, so meh.
1157 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1158 debug!("compare_impl_method(): impl-trait-bound subst");
1159 let impl_trait_bound =
1160 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1163 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1164 debug!("compare_impl_method(): trait-bound subst");
1166 trait_bound.subst(tcx, &trait_to_skol_substs);
1167 let infcx = infer::new_infer_ctxt(tcx);
1168 match infer::mk_sub_trait_refs(&infcx,
1170 infer::Misc(impl_m_span),
1172 impl_trait_bound.clone()) {
1182 span_err!(tcx.sess, impl_m_span, E0052,
1183 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1184 required by the corresponding type parameter in the trait declaration",
1185 token::get_ident(trait_m.ident),
1187 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1192 // Compute skolemized form of impl and trait method tys.
1193 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1194 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1195 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1196 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1198 // Check the impl method type IM is a subtype of the trait method
1199 // type TM. To see why this makes sense, think of a vtable. The
1200 // expected type of the function pointers in the vtable is the
1201 // type TM of the trait method. The actual type will be the type
1202 // IM of the impl method. Because we know that IM <: TM, that
1203 // means that anywhere a TM is expected, a IM will do instead. In
1204 // other words, anyone expecting to call a method with the type
1205 // from the trait, can safely call a method with the type from the
1207 debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
1209 trait_fty.repr(tcx));
1210 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1211 impl_fty, trait_fty) {
1214 span_err!(tcx.sess, impl_m_span, E0053,
1215 "method `{}` has an incompatible type for trait: {}",
1216 token::get_ident(trait_m.ident),
1217 ty::type_err_to_str(tcx, terr));
1218 ty::note_and_explain_type_err(tcx, terr);
1222 // Finally, resolve all regions. This catches wily misuses of lifetime
1224 infcx.resolve_regions_and_report_errors();
1226 fn check_region_bounds_on_impl_method(tcx: &ty::ctxt,
1228 impl_m: &ty::Method,
1229 trait_generics: &ty::Generics,
1230 impl_generics: &ty::Generics,
1231 trait_to_skol_substs: &Substs,
1232 impl_to_skol_substs: &Substs)
1237 Check that region bounds on impl method are the same as those
1238 on the trait. In principle, it could be ok for there to be
1239 fewer region bounds on the impl method, but this leads to an
1240 annoying corner case that is painful to handle (described
1241 below), so for now we can just forbid it.
1244 `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1248 fn method2<'b:'a>();
1251 impl<'a> Foo<'a> for ... {
1252 fn method1<'b:'a>() { .. case 1, definitely bad .. }
1253 fn method2<'b>() { .. case 2, could be ok .. }
1256 The "definitely bad" case is case #1. Here, the impl adds an
1257 extra constraint not present in the trait.
1259 The "maybe bad" case is case #2. Here, the impl adds an extra
1260 constraint not present in the trait. We could in principle
1261 allow this, but it interacts in a complex way with early/late
1262 bound resolution of lifetimes. Basically the presence or
1263 absence of a lifetime bound affects whether the lifetime is
1264 early/late bound, and right now the code breaks if the trait
1265 has an early bound lifetime parameter and the method does not.
1269 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1270 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1272 debug!("check_region_bounds_on_impl_method: \
1275 trait_generics.repr(tcx),
1276 impl_generics.repr(tcx));
1278 // Must have same number of early-bound lifetime parameters.
1279 // Unfortunately, if the user screws up the bounds, then this
1280 // will change classification between early and late. E.g.,
1281 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1282 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1283 // in trait but 0 in the impl. But if we report "expected 2
1284 // but found 0" it's confusing, because it looks like there
1285 // are zero. Since I don't quite know how to phrase things at
1286 // the moment, give a kind of vague error message.
1287 if trait_params.len() != impl_params.len() {
1290 format!("lifetime parameters or bounds on method `{}` do \
1291 not match the trait declaration",
1292 token::get_ident(impl_m.ident)).as_slice());
1296 // Each parameter `'a:'b+'c+'d` in trait should have the same
1297 // set of bounds in the impl, after subst.
1298 for (trait_param, impl_param) in
1299 trait_params.iter().zip(
1303 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1305 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1307 debug!("check_region_bounds_on_impl_method: \
1312 trait_param.repr(tcx),
1313 impl_param.repr(tcx),
1314 trait_bounds.repr(tcx),
1315 impl_bounds.repr(tcx));
1317 // Collect the set of bounds present in trait but not in
1319 let missing: Vec<ty::Region> =
1321 .filter(|&b| !impl_bounds.contains(b))
1325 // Collect set present in impl but not in trait.
1326 let extra: Vec<ty::Region> =
1328 .filter(|&b| !trait_bounds.contains(b))
1332 debug!("missing={} extra={}",
1333 missing.repr(tcx), extra.repr(tcx));
1335 let err = if missing.len() != 0 || extra.len() != 0 {
1339 "the lifetime parameter `{}` declared in the impl \
1340 has a distinct set of bounds \
1341 from its counterpart `{}` \
1342 declared in the trait",
1343 impl_param.name.user_string(tcx),
1344 trait_param.name.user_string(tcx)).as_slice());
1350 if missing.len() != 0 {
1353 format!("the impl is missing the following bounds: `{}`",
1354 missing.user_string(tcx)).as_slice());
1357 if extra.len() != 0 {
1360 format!("the impl has the following extra bounds: `{}`",
1361 extra.user_string(tcx)).as_slice());
1373 fn check_cast(fcx: &FnCtxt,
1374 cast_expr: &ast::Expr,
1377 let id = cast_expr.id;
1378 let span = cast_expr.span;
1380 // Find the type of `e`. Supply hints based on the type we are casting to,
1382 let t_1 = fcx.to_ty(t);
1383 let t_1 = structurally_resolved_type(fcx, span, t_1);
1385 if ty::type_is_scalar(t_1) {
1386 // Supply the type as a hint so as to influence integer
1387 // literals and other things that might care.
1388 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1))
1393 let t_e = fcx.expr_ty(e);
1395 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1396 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1398 if ty::type_is_error(t_e) {
1399 fcx.write_error(id);
1403 if ty::type_is_bot(t_e) {
1408 if !ty::type_is_sized(fcx.tcx(), t_1) {
1409 let tstr = fcx.infcx().ty_to_string(t_1);
1410 fcx.type_error_message(span, |actual| {
1411 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1413 match ty::get(t_e).sty {
1414 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1415 let mtstr = match mt {
1416 ast::MutMutable => "mut ",
1417 ast::MutImmutable => ""
1419 if ty::type_is_trait(t_1) {
1420 span_note!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1422 span_note!(fcx.tcx().sess, span,
1423 "consider using an implicit coercion to `&{}{}` instead",
1427 ty::ty_uniq(..) => {
1428 span_note!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1431 span_note!(fcx.tcx().sess, e.span,
1432 "consider using a box or reference as appropriate");
1435 fcx.write_error(id);
1439 if ty::type_is_trait(t_1) {
1440 // This will be looked up later on.
1441 vtable2::check_object_cast(fcx, cast_expr, e, t_1);
1442 fcx.write_ty(id, t_1);
1446 let t_1 = structurally_resolved_type(fcx, span, t_1);
1447 let t_e = structurally_resolved_type(fcx, span, t_e);
1449 if ty::type_is_nil(t_e) {
1450 fcx.type_error_message(span, |actual| {
1451 format!("cast from nil: `{}` as `{}`",
1453 fcx.infcx().ty_to_string(t_1))
1455 } else if ty::type_is_nil(t_1) {
1456 fcx.type_error_message(span, |actual| {
1457 format!("cast to nil: `{}` as `{}`",
1459 fcx.infcx().ty_to_string(t_1))
1463 let t_1_is_scalar = ty::type_is_scalar(t_1);
1464 let t_1_is_char = ty::type_is_char(t_1);
1465 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1466 let t_1_is_float = ty::type_is_floating_point(t_1);
1468 // casts to scalars other than `char` and `bare fn` are trivial
1469 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1470 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1472 fcx.type_error_message(span, |actual| {
1473 format!("illegal cast; cast through an \
1474 integer first: `{}` as `{}`",
1476 fcx.infcx().ty_to_string(t_1))
1479 // casts from C-like enums are allowed
1480 } else if t_1_is_char {
1481 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1482 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1483 fcx.type_error_message(span, |actual| {
1484 format!("only `u8` can be cast as \
1485 `char`, not `{}`", actual)
1488 } else if ty::get(t_1).sty == ty::ty_bool {
1489 span_err!(fcx.tcx().sess, span, E0054,
1490 "cannot cast as `bool`, compare with zero instead");
1491 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1492 fn types_compatible(fcx: &FnCtxt, sp: Span,
1493 t1: ty::t, t2: ty::t) -> bool {
1494 match ty::get(t1).sty {
1495 ty::ty_vec(_, Some(_)) => {}
1498 if ty::type_needs_infer(t2) {
1499 // This prevents this special case from going off when casting
1500 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1505 let el = ty::sequence_element_type(fcx.tcx(), t1);
1506 infer::mk_eqty(fcx.infcx(),
1513 // Due to the limitations of LLVM global constants,
1514 // region pointers end up pointing at copies of
1515 // vector elements instead of the original values.
1516 // To allow unsafe pointers to work correctly, we
1517 // need to special-case obtaining an unsafe pointer
1518 // from a region pointer to a vector.
1520 /* this cast is only allowed from &[T, ..n] to *T or
1522 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1523 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1524 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1525 if types_compatible(fcx, e.span, mt1, mt2) => {
1526 /* this case is allowed */
1529 demand::coerce(fcx, e.span, t_1, &*e);
1532 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1534 If more type combinations should be supported than are
1535 supported here, then file an enhancement issue and
1536 record the issue number in this comment.
1538 fcx.type_error_message(span, |actual| {
1539 format!("non-scalar cast: `{}` as `{}`",
1541 fcx.infcx().ty_to_string(t_1))
1543 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1544 fcx.type_error_message(span, |actual| {
1545 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1548 fcx.infcx().ty_to_string(t_1))
1552 fcx.write_ty(id, t_1);
1555 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1556 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1558 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1559 ty::lookup_item_type(self.tcx(), id)
1562 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1563 ty::lookup_trait_def(self.tcx(), id)
1566 fn ty_infer(&self, _span: Span) -> ty::t {
1567 self.infcx().next_ty_var()
1570 fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
1575 fn associated_type_binding(&self,
1581 self.tcx().sess.span_err(span, "unsupported associated type binding");
1586 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1587 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1589 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
1593 pub fn err_count_since_creation(&self) -> uint {
1594 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1598 impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
1599 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1600 Some(self.next_region_var(infer::MiscVariable(span)))
1603 fn anon_regions(&self, span: Span, count: uint)
1604 -> Result<Vec<ty::Region> , ()> {
1605 Ok(Vec::from_fn(count, |_| {
1606 self.next_region_var(infer::MiscVariable(span))
1611 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1612 pub fn tag(&self) -> String {
1613 format!("{}", self as *const FnCtxt)
1616 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1617 match self.inh.locals.borrow().find(&nid) {
1620 self.tcx().sess.span_bug(
1622 format!("no type for local variable {:?}",
1629 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1630 debug!("write_ty({}, {}) in fcx {}",
1631 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1632 self.inh.node_types.borrow_mut().insert(node_id, ty);
1635 pub fn write_object_cast(&self,
1637 trait_ref: Rc<ty::TraitRef>) {
1638 debug!("write_object_cast key={} trait_ref={}",
1639 key, trait_ref.repr(self.tcx()));
1640 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1643 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1644 if !substs.substs.is_noop() {
1645 debug!("write_substs({}, {}) in fcx {}",
1647 substs.repr(self.tcx()),
1650 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1654 pub fn write_ty_substs(&self,
1655 node_id: ast::NodeId,
1657 substs: ty::ItemSubsts) {
1658 let ty = ty.subst(self.tcx(), &substs.substs);
1659 self.write_ty(node_id, ty);
1660 self.write_substs(node_id, substs);
1663 pub fn write_autoderef_adjustment(&self,
1664 node_id: ast::NodeId,
1667 if derefs == 0 { return; }
1668 self.write_adjustment(
1671 ty::AdjustDerefRef(ty::AutoDerefRef {
1677 pub fn write_adjustment(&self,
1678 node_id: ast::NodeId,
1680 adj: ty::AutoAdjustment) {
1681 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1683 // Careful: adjustments can imply trait obligations if we are
1684 // casting from a concrete type to an object type. I think
1685 // it'd probably be nicer to move the logic that creates the
1686 // obligation into the code that creates the adjustment, but
1687 // that's a bit awkward, so instead we go digging and pull the
1688 // obligation out here.
1689 self.register_adjustment_obligations(span, &adj);
1690 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1693 fn register_adjustment_obligations(&self,
1695 adj: &ty::AutoAdjustment) {
1697 ty::AdjustAddEnv(..) => { }
1698 ty::AdjustDerefRef(ref d_r) => {
1701 self.register_autoref_obligations(span, a_r);
1709 fn register_autoref_obligations(&self,
1711 autoref: &ty::AutoRef) {
1713 ty::AutoUnsize(ref unsize) => {
1714 self.register_unsize_obligations(span, unsize);
1716 ty::AutoPtr(_, _, None) |
1717 ty::AutoUnsafe(_, None) => {
1719 ty::AutoPtr(_, _, Some(ref a_r)) |
1720 ty::AutoUnsafe(_, Some(ref a_r)) => {
1721 self.register_autoref_obligations(span, &**a_r)
1723 ty::AutoUnsizeUniq(ref unsize) => {
1724 self.register_unsize_obligations(span, unsize);
1729 fn register_unsize_obligations(&self,
1731 unsize: &ty::UnsizeKind) {
1732 debug!("register_unsize_obligations: unsize={:?}", unsize);
1735 ty::UnsizeLength(..) => {}
1736 ty::UnsizeStruct(ref u, _) => {
1737 self.register_unsize_obligations(span, &**u)
1739 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1740 vtable2::register_object_cast_obligations(self,
1748 pub fn instantiate_item_type(&self,
1754 * Returns the type of `def_id` with all generics replaced by
1755 * by fresh type/region variables. Also returns the
1756 * substitution from the type parameters on `def_id` to the
1757 * fresh variables. Registers any trait obligations specified
1758 * on `def_id` at the same time.
1762 ty::lookup_item_type(self.tcx(), def_id);
1764 self.infcx().fresh_substs_for_generics(
1766 &polytype.generics);
1767 self.add_obligations_for_parameters(
1768 traits::ObligationCause::new(
1770 traits::ItemObligation(def_id)),
1772 &polytype.generics);
1774 polytype.ty.subst(self.tcx(), &substs);
1782 pub fn write_nil(&self, node_id: ast::NodeId) {
1783 self.write_ty(node_id, ty::mk_nil());
1785 pub fn write_bot(&self, node_id: ast::NodeId) {
1786 self.write_ty(node_id, ty::mk_bot());
1788 pub fn write_error(&self, node_id: ast::NodeId) {
1789 self.write_ty(node_id, ty::mk_err());
1792 pub fn require_type_meets(&self,
1795 code: traits::ObligationCauseCode,
1796 bound: ty::BuiltinBound)
1798 self.register_obligation(
1799 traits::obligation_for_builtin_bound(
1801 traits::ObligationCause::new(span, code),
1806 pub fn require_type_is_sized(&self,
1809 code: traits::ObligationCauseCode)
1811 self.require_type_meets(ty, span, code, ty::BoundSized);
1814 pub fn require_expr_have_sized_type(&self,
1816 code: traits::ObligationCauseCode)
1818 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1821 pub fn register_obligation(&self,
1822 obligation: traits::Obligation)
1824 debug!("register_obligation({})",
1825 obligation.repr(self.tcx()));
1827 self.inh.fulfillment_cx
1829 .register_obligation(self.tcx(), obligation);
1832 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1833 let t = ast_ty_to_ty(self, self.infcx(), ast_t);
1835 let mut bounds_checker = wf::BoundsChecker::new(self,
1839 bounds_checker.check_ty(t);
1844 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1845 pat.repr(self.tcx())
1848 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1849 match self.inh.node_types.borrow().find(&ex.id) {
1852 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1853 self.tag()).as_slice());
1858 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1859 match self.inh.node_types.borrow().find(&id) {
1862 self.tcx().sess.bug(
1863 format!("no type for node {}: {} in fcx {}",
1864 id, self.tcx().map.node_to_string(id),
1865 self.tag()).as_slice());
1870 pub fn opt_node_ty_substs(&self,
1872 f: |&ty::ItemSubsts|) {
1873 match self.inh.item_substs.borrow().find(&id) {
1879 pub fn mk_subty(&self,
1880 a_is_expected: bool,
1881 origin: infer::TypeOrigin,
1884 -> Result<(), ty::type_err> {
1885 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1888 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1889 -> Result<(), ty::type_err> {
1890 infer::can_mk_subty(self.infcx(), sub, sup)
1893 pub fn can_mk_eqty(&self, sub: ty::t, sup: ty::t)
1894 -> Result<(), ty::type_err> {
1895 infer::can_mk_eqty(self.infcx(), sub, sup)
1898 pub fn mk_assignty(&self,
1902 -> Result<(), ty::type_err> {
1903 match infer::mk_coercety(self.infcx(),
1905 infer::ExprAssignable(expr.span),
1909 Err(ref e) => Err((*e)),
1910 Ok(Some(adjustment)) => {
1911 self.write_adjustment(expr.id, expr.span, adjustment);
1917 pub fn mk_eqty(&self,
1918 a_is_expected: bool,
1919 origin: infer::TypeOrigin,
1922 -> Result<(), ty::type_err> {
1923 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1926 pub fn mk_subr(&self,
1927 origin: infer::SubregionOrigin,
1930 infer::mk_subr(self.infcx(), origin, sub, sup)
1933 pub fn type_error_message(&self,
1935 mk_msg: |String| -> String,
1937 err: Option<&ty::type_err>) {
1938 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1941 pub fn report_mismatched_types(&self,
1945 err: &ty::type_err) {
1946 self.infcx().report_mismatched_types(sp, e, a, err)
1949 pub fn register_region_obligation(&self,
1950 origin: infer::SubregionOrigin,
1955 * Registers an obligation for checking later, during
1956 * regionck, that the type `ty` must outlive the region `r`.
1959 let mut region_obligations = self.inh.region_obligations.borrow_mut();
1960 let region_obligation = RegionObligation { sub_region: r,
1964 match region_obligations.entry(self.body_id) {
1965 Vacant(entry) => { entry.set(vec![region_obligation]); },
1966 Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
1970 pub fn add_obligations_for_parameters(&self,
1971 cause: traits::ObligationCause,
1973 generics: &ty::Generics)
1976 * Given a set of generic parameter definitions (`generics`)
1977 * and the values provided for each of them (`substs`),
1978 * creates and registers suitable region obligations.
1980 * For example, if there is a function:
1982 * fn foo<'a,T:'a>(...)
1988 * Then we will create a fresh region variable `'$0` and a
1989 * fresh type variable `$1` for `'a` and `T`. This routine
1990 * will add a region obligation `$1:'$0` and register it
1994 debug!("add_obligations_for_parameters(substs={}, generics={})",
1995 substs.repr(self.tcx()),
1996 generics.repr(self.tcx()));
1998 self.add_trait_obligations_for_generics(cause, substs, generics);
1999 self.add_region_obligations_for_generics(cause, substs, generics);
2002 fn add_trait_obligations_for_generics(&self,
2003 cause: traits::ObligationCause,
2005 generics: &ty::Generics) {
2007 traits::obligations_for_generics(self.tcx(),
2011 obligations.map_move(|o| self.register_obligation(o));
2014 fn add_region_obligations_for_generics(&self,
2015 cause: traits::ObligationCause,
2017 generics: &ty::Generics)
2019 assert_eq!(generics.types.iter().len(),
2020 substs.types.iter().len());
2021 for (type_def, &type_param) in
2022 generics.types.iter().zip(
2023 substs.types.iter())
2025 let param_ty = ty::ParamTy { space: type_def.space,
2026 idx: type_def.index,
2027 def_id: type_def.def_id };
2028 let bounds = type_def.bounds.subst(self.tcx(), substs);
2029 self.add_region_obligations_for_type_parameter(
2030 cause.span, param_ty, &bounds, type_param);
2033 assert_eq!(generics.regions.iter().len(),
2034 substs.regions().iter().len());
2035 for (region_def, ®ion_param) in
2036 generics.regions.iter().zip(
2037 substs.regions().iter())
2039 let bounds = region_def.bounds.subst(self.tcx(), substs);
2040 self.add_region_obligations_for_region_parameter(
2041 cause.span, bounds.as_slice(), region_param);
2045 fn add_region_obligations_for_type_parameter(&self,
2047 param_ty: ty::ParamTy,
2048 param_bound: &ty::ParamBounds,
2051 // For each declared region bound `T:r`, `T` must outlive `r`.
2053 ty::required_region_bounds(
2055 param_bound.region_bounds.as_slice(),
2056 param_bound.builtin_bounds,
2057 param_bound.trait_bounds.as_slice());
2058 for &r in region_bounds.iter() {
2059 let origin = infer::RelateParamBound(span, param_ty, ty);
2060 self.register_region_obligation(origin, ty, r);
2064 fn add_region_obligations_for_region_parameter(&self,
2066 region_bounds: &[ty::Region],
2067 region_param: ty::Region)
2069 for &b in region_bounds.iter() {
2070 // For each bound `region:b`, `b <= region` must hold
2071 // (i.e., `region` must outlive `b`).
2072 let origin = infer::RelateRegionParamBound(span);
2073 self.mk_subr(origin, b, region_param);
2078 pub enum LvaluePreference {
2083 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
2084 expr_id: Option<ast::NodeId>,
2085 mut lvalue_pref: LvaluePreference,
2086 should_stop: |ty::t, uint| -> Option<T>)
2087 -> (ty::t, uint, Option<T>) {
2089 * Executes an autoderef loop for the type `t`. At each step, invokes
2090 * `should_stop` to decide whether to terminate the loop. Returns
2091 * the final type and number of derefs that it performed.
2093 * Note: this method does not modify the adjustments table. The caller is
2094 * responsible for inserting an AutoAdjustment record into the `fcx`
2095 * using one of the suitable methods.
2098 let mut t = base_ty;
2099 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
2100 let resolved_t = structurally_resolved_type(fcx, sp, t);
2102 if ty::type_is_bot(resolved_t) {
2103 return (resolved_t, autoderefs, None);
2106 match should_stop(resolved_t, autoderefs) {
2107 Some(x) => return (resolved_t, autoderefs, Some(x)),
2111 // Otherwise, deref if type is derefable:
2112 let mt = match ty::deref(resolved_t, false) {
2113 Some(mt) => Some(mt),
2115 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
2116 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2122 if mt.mutbl == ast::MutImmutable {
2123 lvalue_pref = NoPreference;
2126 None => return (resolved_t, autoderefs, None)
2130 // We've reached the recursion limit, error gracefully.
2131 span_err!(fcx.tcx().sess, sp, E0055,
2132 "reached the recursion limit while auto-dereferencing {}",
2133 base_ty.repr(fcx.tcx()));
2134 (ty::mk_err(), 0, None)
2137 /// Attempts to resolve a call expression as an overloaded call.
2138 fn try_overloaded_call<'a>(fcx: &FnCtxt,
2139 call_expression: &ast::Expr,
2142 args: &[&'a P<ast::Expr>])
2144 // Bail out if the callee is a bare function or a closure. We check those
2146 match *structure_of(fcx, callee.span, callee_type) {
2147 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
2151 // Try `FnOnce`, then `FnMut`, then `Fn`.
2152 for &(maybe_function_trait, method_name) in [
2153 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2154 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2155 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
2157 let function_trait = match maybe_function_trait {
2159 Some(function_trait) => function_trait,
2161 let method_callee = match method::lookup_in_trait(
2163 call_expression.span,
2169 DontAutoderefReceiver,
2170 IgnoreStaticMethods) {
2172 Some(method_callee) => method_callee,
2174 let method_call = MethodCall::expr(call_expression.id);
2175 let output_type = check_method_argument_types(fcx,
2176 call_expression.span,
2182 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2183 write_call(fcx, call_expression, output_type);
2185 if !fcx.tcx().sess.features.borrow().overloaded_calls {
2186 span_err!(fcx.tcx().sess, call_expression.span, E0056,
2187 "overloaded calls are experimental");
2188 span_note!(fcx.tcx().sess, call_expression.span,
2189 "add `#![feature(overloaded_calls)]` to \
2190 the crate attributes to enable");
2199 fn try_overloaded_deref(fcx: &FnCtxt,
2201 method_call: Option<MethodCall>,
2202 base_expr: Option<&ast::Expr>,
2204 lvalue_pref: LvaluePreference)
2206 // Try DerefMut first, if preferred.
2207 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2208 (PreferMutLvalue, Some(trait_did)) => {
2209 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2210 token::intern("deref_mut"), trait_did,
2211 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2216 // Otherwise, fall back to Deref.
2217 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2218 (None, Some(trait_did)) => {
2219 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2220 token::intern("deref"), trait_did,
2221 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2223 (method, _) => method
2226 make_return_type(fcx, method_call, method)
2229 fn get_method_ty(method: &Option<MethodCallee>) -> ty::t {
2231 &Some(ref method) => method.ty,
2232 &None => ty::mk_err()
2236 fn make_return_type(fcx: &FnCtxt,
2237 method_call: Option<MethodCall>,
2238 method: Option<MethodCallee>)
2242 let ref_ty = ty::ty_fn_ret(method.ty);
2244 Some(method_call) => {
2245 fcx.inh.method_map.borrow_mut().insert(method_call,
2250 ty::deref(ref_ty, true)
2256 fn try_overloaded_slice(fcx: &FnCtxt,
2257 method_call: Option<MethodCall>,
2259 base_expr: &ast::Expr,
2261 start_expr: &Option<P<ast::Expr>>,
2262 end_expr: &Option<P<ast::Expr>>,
2263 mutbl: &ast::Mutability)
2265 let method = if mutbl == &ast::MutMutable {
2266 // Try `SliceMut` first, if preferred.
2267 match fcx.tcx().lang_items.slice_mut_trait() {
2268 Some(trait_did) => {
2269 let method_name = match (start_expr, end_expr) {
2270 (&Some(_), &Some(_)) => "slice_mut_",
2271 (&Some(_), &None) => "slice_from_mut_",
2272 (&None, &Some(_)) => "slice_to_mut_",
2273 (&None, &None) => "as_mut_slice_",
2276 method::lookup_in_trait(fcx,
2279 token::intern(method_name),
2283 DontAutoderefReceiver,
2284 IgnoreStaticMethods)
2289 // Otherwise, fall back to `Slice`.
2290 // FIXME(#17293) this will not coerce base_expr, so we miss the Slice
2291 // trait for `&mut [T]`.
2292 match fcx.tcx().lang_items.slice_trait() {
2293 Some(trait_did) => {
2294 let method_name = match (start_expr, end_expr) {
2295 (&Some(_), &Some(_)) => "slice_",
2296 (&Some(_), &None) => "slice_from_",
2297 (&None, &Some(_)) => "slice_to_",
2298 (&None, &None) => "as_slice_",
2301 method::lookup_in_trait(fcx,
2304 token::intern(method_name),
2308 DontAutoderefReceiver,
2309 IgnoreStaticMethods)
2316 // Regardless of whether the lookup succeeds, check the method arguments
2317 // so that we have *some* type for each argument.
2318 let method_type = get_method_ty(&method);
2320 let mut args = vec![];
2321 start_expr.as_ref().map(|x| args.push(x));
2322 end_expr.as_ref().map(|x| args.push(x));
2324 check_method_argument_types(fcx,
2330 DontTupleArguments);
2334 let result_ty = ty::ty_fn_ret(method.ty);
2336 Some(method_call) => {
2337 fcx.inh.method_map.borrow_mut().insert(method_call,
2342 Some(ty::mt { ty: result_ty, mutbl: ast::MutImmutable })
2348 fn try_overloaded_index(fcx: &FnCtxt,
2349 method_call: Option<MethodCall>,
2351 base_expr: &ast::Expr,
2353 index_expr: &P<ast::Expr>,
2354 lvalue_pref: LvaluePreference)
2356 // Try `IndexMut` first, if preferred.
2357 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2358 (PreferMutLvalue, Some(trait_did)) => {
2359 method::lookup_in_trait(fcx,
2362 token::intern("index_mut"),
2366 DontAutoderefReceiver,
2367 IgnoreStaticMethods)
2372 // Otherwise, fall back to `Index`.
2373 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2374 (None, Some(trait_did)) => {
2375 method::lookup_in_trait(fcx,
2378 token::intern("index"),
2382 DontAutoderefReceiver,
2383 IgnoreStaticMethods)
2385 (method, _) => method,
2388 // Regardless of whether the lookup succeeds, check the method arguments
2389 // so that we have *some* type for each argument.
2390 let method_type = get_method_ty(&method);
2391 check_method_argument_types(fcx,
2397 DontTupleArguments);
2399 make_return_type(fcx, method_call, method)
2402 /// Given the head of a `for` expression, looks up the `next` method in the
2403 /// `Iterator` trait. Fails if the expression does not implement `next`.
2405 /// The return type of this function represents the concrete element type
2406 /// `A` in the type `Iterator<A>` that the method returns.
2407 fn lookup_method_for_for_loop(fcx: &FnCtxt,
2408 iterator_expr: &ast::Expr,
2409 loop_id: ast::NodeId)
2411 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2412 Ok(trait_did) => trait_did,
2413 Err(ref err_string) => {
2414 fcx.tcx().sess.span_err(iterator_expr.span,
2415 err_string.as_slice());
2420 let expr_type = fcx.expr_ty(&*iterator_expr);
2421 let method = method::lookup_in_trait(fcx,
2423 Some(&*iterator_expr),
2424 token::intern("next"),
2428 DontAutoderefReceiver,
2429 IgnoreStaticMethods);
2431 // Regardless of whether the lookup succeeds, check the method arguments
2432 // so that we have *some* type for each argument.
2433 let method_type = match method {
2434 Some(ref method) => method.ty,
2436 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
2438 if !ty::type_is_error(true_expr_type) {
2439 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2440 fcx.tcx().sess.span_err(iterator_expr.span,
2441 format!("`for` loop expression has type `{}` which does \
2442 not implement the `Iterator` trait",
2443 ty_string).as_slice());
2448 let return_type = check_method_argument_types(fcx,
2454 DontTupleArguments);
2458 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2461 // We expect the return type to be `Option` or something like it.
2462 // Grab the first parameter of its type substitution.
2463 let return_type = structurally_resolved_type(fcx,
2466 match ty::get(return_type).sty {
2467 ty::ty_enum(_, ref substs)
2468 if !substs.types.is_empty_in(subst::TypeSpace) => {
2469 *substs.types.get(subst::TypeSpace, 0)
2472 fcx.tcx().sess.span_err(iterator_expr.span,
2473 "`next` method of the `Iterator` \
2474 trait has an unexpected type");
2479 None => ty::mk_err()
2483 fn check_method_argument_types<'a>(fcx: &FnCtxt,
2485 method_fn_ty: ty::t,
2486 callee_expr: &ast::Expr,
2487 args_no_rcvr: &[&'a P<ast::Expr>],
2488 deref_args: DerefArgs,
2489 tuple_arguments: TupleArgumentsFlag)
2491 if ty::type_is_error(method_fn_ty) {
2492 let err_inputs = err_args(args_no_rcvr.len());
2493 check_argument_types(fcx,
2495 err_inputs.as_slice(),
2503 match ty::get(method_fn_ty).sty {
2504 ty::ty_bare_fn(ref fty) => {
2505 // HACK(eddyb) ignore self in the definition (see above).
2506 check_argument_types(fcx,
2508 fty.sig.inputs.slice_from(1),
2517 fcx.tcx().sess.span_bug(callee_expr.span,
2518 "method without bare fn type");
2524 fn check_argument_types<'a>(fcx: &FnCtxt,
2526 fn_inputs: &[ty::t],
2527 _callee_expr: &ast::Expr,
2528 args: &[&'a P<ast::Expr>],
2529 deref_args: DerefArgs,
2531 tuple_arguments: TupleArgumentsFlag) {
2534 * Generic function that factors out common logic from
2535 * function calls, method calls and overloaded operators.
2538 let tcx = fcx.ccx.tcx;
2540 // Grab the argument types, supplying fresh type variables
2541 // if the wrong number of arguments were supplied
2542 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2548 let expected_arg_count = fn_inputs.len();
2549 let formal_tys = if tuple_arguments == TupleArguments {
2550 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2551 match ty::get(tuple_type).sty {
2552 ty::ty_tup(ref arg_types) => {
2553 if arg_types.len() != args.len() {
2554 span_err!(tcx.sess, sp, E0057,
2555 "this function takes {} parameter{} but {} parameter{} supplied",
2557 if arg_types.len() == 1 {""} else {"s"},
2559 if args.len() == 1 {" was"} else {"s were"});
2560 err_args(args.len())
2562 (*arg_types).clone()
2566 if args.len() != 0 {
2567 span_err!(tcx.sess, sp, E0058,
2568 "this function takes 0 parameters but {} parameter{} supplied",
2570 if args.len() == 1 {" was"} else {"s were"});
2575 span_err!(tcx.sess, sp, E0059,
2576 "cannot use call notation; the first type parameter \
2577 for the function trait is neither a tuple nor unit");
2578 err_args(supplied_arg_count)
2581 } else if expected_arg_count == supplied_arg_count {
2582 fn_inputs.iter().map(|a| *a).collect()
2583 } else if variadic {
2584 if supplied_arg_count >= expected_arg_count {
2585 fn_inputs.iter().map(|a| *a).collect()
2587 span_err!(tcx.sess, sp, E0060,
2588 "this function takes at least {} parameter{} \
2589 but {} parameter{} supplied",
2591 if expected_arg_count == 1 {""} else {"s"},
2593 if supplied_arg_count == 1 {" was"} else {"s were"});
2594 err_args(supplied_arg_count)
2597 span_err!(tcx.sess, sp, E0061,
2598 "this function takes {} parameter{} but {} parameter{} supplied",
2600 if expected_arg_count == 1 {""} else {"s"},
2602 if supplied_arg_count == 1 {" was"} else {"s were"});
2603 err_args(supplied_arg_count)
2606 debug!("check_argument_types: formal_tys={:?}",
2607 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2609 // Check the arguments.
2610 // We do this in a pretty awful way: first we typecheck any arguments
2611 // that are not anonymous functions, then we typecheck the anonymous
2612 // functions. This is so that we have more information about the types
2613 // of arguments when we typecheck the functions. This isn't really the
2614 // right way to do this.
2615 let xs = [false, true];
2616 for check_blocks in xs.iter() {
2617 let check_blocks = *check_blocks;
2618 debug!("check_blocks={}", check_blocks);
2620 // More awful hacks: before we check the blocks, try to do
2621 // an "opportunistic" vtable resolution of any trait
2622 // bounds on the call.
2624 vtable2::select_fcx_obligations_where_possible(fcx);
2627 // For variadic functions, we don't have a declared type for all of
2628 // the arguments hence we only do our usual type checking with
2629 // the arguments who's types we do know.
2630 let t = if variadic {
2632 } else if tuple_arguments == TupleArguments {
2637 for (i, arg) in args.iter().take(t).enumerate() {
2638 let is_block = match arg.node {
2639 ast::ExprFnBlock(..) |
2641 ast::ExprUnboxedFn(..) => true,
2645 if is_block == check_blocks {
2646 debug!("checking the argument");
2647 let mut formal_ty = *formal_tys.get(i);
2651 match ty::get(formal_ty).sty {
2652 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2655 // So we hit this case when one implements the
2656 // operator traits but leaves an argument as
2657 // just T instead of &T. We'll catch it in the
2658 // mismatch impl/trait method phase no need to
2661 formal_ty = ty::mk_err();
2668 check_expr_coercable_to_type(fcx, &***arg, formal_ty);
2673 // We also need to make sure we at least write the ty of the other
2674 // arguments which we skipped above.
2676 for arg in args.iter().skip(expected_arg_count) {
2677 check_expr(fcx, &***arg);
2679 // There are a few types which get autopromoted when passed via varargs
2680 // in C but we just error out instead and require explicit casts.
2681 let arg_ty = structurally_resolved_type(fcx, arg.span,
2682 fcx.expr_ty(&***arg));
2683 match ty::get(arg_ty).sty {
2684 ty::ty_float(ast::TyF32) => {
2685 fcx.type_error_message(arg.span,
2687 format!("can't pass an {} to variadic \
2688 function, cast to c_double", t)
2691 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2692 fcx.type_error_message(arg.span, |t| {
2693 format!("can't pass {} to variadic \
2694 function, cast to c_int",
2698 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2699 fcx.type_error_message(arg.span, |t| {
2700 format!("can't pass {} to variadic \
2701 function, cast to c_uint",
2711 fn err_args(len: uint) -> Vec<ty::t> {
2712 Vec::from_fn(len, |_| ty::mk_err())
2715 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
2716 fcx.write_ty(call_expr.id, output);
2719 // AST fragment checking
2720 fn check_lit(fcx: &FnCtxt,
2722 expected: Expectation)
2725 let tcx = fcx.ccx.tcx;
2728 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2729 ast::LitBinary(..) => {
2730 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2732 ast::LitByte(_) => ty::mk_u8(),
2733 ast::LitChar(_) => ty::mk_char(),
2734 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2735 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2736 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2737 let opt_ty = expected.map_to_option(fcx, |sty| {
2739 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2740 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2741 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2742 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2743 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2747 opt_ty.unwrap_or_else(
2748 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2750 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2751 ast::LitFloatUnsuffixed(_) => {
2752 let opt_ty = expected.map_to_option(fcx, |sty| {
2754 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2758 opt_ty.unwrap_or_else(
2759 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2761 ast::LitNil => ty::mk_nil(),
2762 ast::LitBool(_) => ty::mk_bool()
2766 pub fn valid_range_bounds(ccx: &CrateCtxt,
2770 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2771 Some(val) => Some(val <= 0),
2776 pub fn check_expr_has_type(fcx: &FnCtxt,
2779 check_expr_with_unifier(
2780 fcx, expr, ExpectHasType(expected), NoPreference,
2781 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2784 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2787 check_expr_with_unifier(
2788 fcx, expr, ExpectHasType(expected), NoPreference,
2789 || demand::coerce(fcx, expr.span, expected, expr));
2792 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2793 check_expr_with_unifier(
2794 fcx, expr, ExpectHasType(expected), NoPreference,
2798 fn check_expr_with_expectation(fcx: &FnCtxt,
2800 expected: Expectation) {
2801 check_expr_with_unifier(
2802 fcx, expr, expected, NoPreference,
2806 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2808 expected: Expectation,
2809 lvalue_pref: LvaluePreference)
2811 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2814 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2815 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2818 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2819 lvalue_pref: LvaluePreference) {
2820 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2823 // determine the `self` type, using fresh variables for all variables
2824 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2825 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2827 pub fn impl_self_ty(fcx: &FnCtxt,
2828 span: Span, // (potential) receiver for this impl
2831 let tcx = fcx.tcx();
2833 let ity = ty::lookup_item_type(tcx, did);
2834 let (n_tps, rps, raw_ty) =
2835 (ity.generics.types.len(subst::TypeSpace),
2836 ity.generics.regions.get_slice(subst::TypeSpace),
2839 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2840 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2841 let substs = subst::Substs::new_type(tps, rps);
2842 let substd_ty = raw_ty.subst(tcx, &substs);
2844 TypeAndSubsts { substs: substs, ty: substd_ty }
2847 // Only for fields! Returns <none> for methods>
2848 // Indifferent to privacy flags
2849 pub fn lookup_field_ty(tcx: &ty::ctxt,
2850 class_id: ast::DefId,
2851 items: &[ty::field_ty],
2852 fieldname: ast::Name,
2853 substs: &subst::Substs) -> Option<ty::t> {
2855 let o_field = items.iter().find(|f| f.name == fieldname);
2856 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2859 pub fn lookup_tup_field_ty(tcx: &ty::ctxt,
2860 class_id: ast::DefId,
2861 items: &[ty::field_ty],
2863 substs: &subst::Substs) -> Option<ty::t> {
2865 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
2866 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2869 // Controls whether the arguments are automatically referenced. This is useful
2870 // for overloaded binary and unary operators.
2871 pub enum DerefArgs {
2876 /// Controls whether the arguments are tupled. This is used for the call
2879 /// Tupling means that all call-side arguments are packed into a tuple and
2880 /// passed as a single parameter. For example, if tupling is enabled, this
2883 /// fn f(x: (int, int))
2885 /// Can be called as:
2892 #[deriving(Clone, Eq, PartialEq)]
2893 enum TupleArgumentsFlag {
2899 /// If an expression has any sub-expressions that result in a type error,
2900 /// inspecting that expression's type with `ty::type_is_error` will return
2901 /// true. Likewise, if an expression is known to diverge, inspecting its
2902 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2903 /// strict, _|_ can appear in the type of an expression that does not,
2904 /// itself, diverge: for example, fn() -> _|_.)
2905 /// Note that inspecting a type's structure *directly* may expose the fact
2906 /// that there are actually multiple representations for both `ty_err` and
2907 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2908 fn check_expr_with_unifier(fcx: &FnCtxt,
2910 expected: Expectation,
2911 lvalue_pref: LvaluePreference,
2914 debug!(">> typechecking: expr={} expected={}",
2915 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2917 // A generic function for doing all of the checking for call expressions
2918 fn check_call<'a>(fcx: &FnCtxt,
2919 call_expr: &ast::Expr,
2921 args: &[&'a P<ast::Expr>]) {
2922 // Store the type of `f` as the type of the callee
2923 let fn_ty = fcx.expr_ty(f);
2925 // Extract the function signature from `in_fty`.
2926 let fn_sty = structure_of(fcx, f.span, fn_ty);
2928 // This is the "default" function signature, used in case of error.
2929 // In that case, we check each argument against "error" in order to
2930 // set up all the node type bindings.
2931 let error_fn_sig = FnSig {
2932 binder_id: ast::CRATE_NODE_ID,
2933 inputs: err_args(args.len()),
2934 output: ty::mk_err(),
2938 let fn_sig = match *fn_sty {
2939 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2940 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2942 fcx.type_error_message(call_expr.span, |actual| {
2943 format!("expected function, found `{}`", actual)
2949 // Replace any bound regions that appear in the function
2950 // signature with region variables
2951 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2952 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2955 // Call the generic checker.
2956 check_argument_types(fcx,
2958 fn_sig.inputs.as_slice(),
2963 DontTupleArguments);
2965 write_call(fcx, call_expr, fn_sig.output);
2968 // Checks a method call.
2969 fn check_method_call(fcx: &FnCtxt,
2971 method_name: ast::SpannedIdent,
2972 args: &[P<ast::Expr>],
2973 tps: &[P<ast::Ty>]) {
2974 let rcvr = &*args[0];
2975 // We can't know if we need &mut self before we look up the method,
2976 // so treat the receiver as mutable just in case - only explicit
2977 // overloaded dereferences care about the distinction.
2978 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2980 // no need to check for bot/err -- callee does that
2981 let expr_t = structurally_resolved_type(fcx,
2983 fcx.expr_ty(&*rcvr));
2985 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2986 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2987 method_name.node.name,
2988 expr_t, tps.as_slice(),
2990 CheckTraitsAndInherentMethods,
2991 AutoderefReceiver, IgnoreStaticMethods) {
2993 let method_ty = method.ty;
2994 let method_call = MethodCall::expr(expr.id);
2995 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2999 debug!("(checking method call) failing expr is {}", expr.id);
3001 fcx.type_error_message(method_name.span,
3003 format!("type `{}` does not implement any \
3004 method in scope named `{}`",
3006 token::get_ident(method_name.node))
3011 // Add error type for the result
3012 fcx.write_error(expr.id);
3014 // Check for potential static matches (missing self parameters)
3018 method_name.node.name,
3022 CheckTraitsAndInherentMethods,
3023 DontAutoderefReceiver,
3024 ReportStaticMethods);
3030 // Call the generic checker.
3031 let args: Vec<_> = args.slice_from(1).iter().map(|x| x).collect();
3032 let ret_ty = check_method_argument_types(fcx,
3038 DontTupleArguments);
3040 write_call(fcx, expr, ret_ty);
3043 // A generic function for checking the then and else in an if
3045 fn check_then_else(fcx: &FnCtxt,
3046 cond_expr: &ast::Expr,
3047 then_blk: &ast::Block,
3048 opt_else_expr: Option<&ast::Expr>,
3051 expected: Expectation) {
3052 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
3054 let branches_ty = match opt_else_expr {
3055 Some(ref else_expr) => {
3056 // Disregard "castable to" expectations because they
3057 // can lead us astray. Consider for example `if cond
3058 // {22} else {c} as u8` -- if we propagate the
3059 // "castable to u8" constraint to 22, it will pick the
3060 // type 22u8, which is overly constrained (c might not
3061 // be a u8). In effect, the problem is that the
3062 // "castable to" expectation is not the tightest thing
3063 // we can say, so we want to drop it in this case.
3064 // The tightest thing we can say is "must unify with
3065 // else branch". Note that in the case of a "has type"
3066 // constraint, this limitation does not hold.
3068 // If the expected type is just a type variable, then don't use
3069 // an expected type. Otherwise, we might write parts of the type
3070 // when checking the 'then' block which are incompatible with the
3072 let expected = match expected.only_has_type() {
3073 ExpectHasType(ety) => {
3074 match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) {
3075 Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
3081 check_block_with_expected(fcx, then_blk, expected);
3082 let then_ty = fcx.node_ty(then_blk.id);
3083 check_expr_with_expectation(fcx, &**else_expr, expected);
3084 let else_ty = fcx.expr_ty(&**else_expr);
3085 infer::common_supertype(fcx.infcx(),
3086 infer::IfExpression(sp),
3092 check_block_no_value(fcx, then_blk);
3097 let cond_ty = fcx.expr_ty(cond_expr);
3098 let if_ty = if ty::type_is_error(cond_ty) {
3100 } else if ty::type_is_bot(cond_ty) {
3106 fcx.write_ty(id, if_ty);
3109 fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
3113 trait_did: Option<ast::DefId>,
3115 rhs: Option<&P<ast::Expr>>,
3116 autoderef_receiver: AutoderefReceiverFlag,
3117 unbound_method: ||) -> ty::t {
3118 let method = match trait_did {
3119 Some(trait_did) => {
3120 method::lookup_in_trait(fcx, op_ex.span, Some(lhs), opname,
3121 trait_did, lhs_ty, &[], autoderef_receiver,
3122 IgnoreStaticMethods)
3126 let args = match rhs {
3127 Some(rhs) => vec![rhs],
3132 let method_ty = method.ty;
3133 // HACK(eddyb) Fully qualified path to work around a resolve bug.
3134 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
3135 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3136 check_method_argument_types(fcx,
3146 // Check the args anyway
3147 // so we get all the error messages
3148 let expected_ty = ty::mk_err();
3149 check_method_argument_types(fcx,
3155 DontTupleArguments);
3161 // could be either an expr_binop or an expr_assign_binop
3162 fn check_binop(fcx: &FnCtxt,
3167 is_binop_assignment: IsBinopAssignment) {
3168 let tcx = fcx.ccx.tcx;
3170 let lvalue_pref = match is_binop_assignment {
3171 BinopAssignment => PreferMutLvalue,
3172 SimpleBinop => NoPreference
3174 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
3176 // Callee does bot / err checking
3177 let lhs_t = structurally_resolved_type(fcx, lhs.span,
3178 fcx.expr_ty(&*lhs));
3180 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
3181 // Shift is a special case: rhs must be uint, no matter what lhs is
3182 check_expr_has_type(fcx, &**rhs, ty::mk_uint());
3183 fcx.write_ty(expr.id, lhs_t);
3187 if ty::is_binopable(tcx, lhs_t, op) {
3188 let tvar = fcx.infcx().next_ty_var();
3189 demand::suptype(fcx, expr.span, tvar, lhs_t);
3190 check_expr_has_type(fcx, &**rhs, tvar);
3192 let result_t = match op {
3193 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
3195 if ty::type_is_simd(tcx, lhs_t) {
3196 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
3197 fcx.type_error_message(expr.span,
3199 format!("binary comparison \
3200 operation `{}` not \
3201 supported for floating \
3202 point SIMD vector `{}`",
3203 ast_util::binop_to_string(op),
3220 fcx.write_ty(expr.id, result_t);
3224 if op == ast::BiOr || op == ast::BiAnd {
3225 // This is an error; one of the operands must have the wrong
3227 fcx.write_error(expr.id);
3228 fcx.write_error(rhs.id);
3229 fcx.type_error_message(expr.span,
3231 format!("binary operation `{}` cannot be applied \
3233 ast_util::binop_to_string(op),
3240 // Check for overloaded operators if not an assignment.
3241 let result_t = if is_binop_assignment == SimpleBinop {
3242 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3244 fcx.type_error_message(expr.span,
3246 format!("binary assignment \
3248 cannot be applied to \
3250 ast_util::binop_to_string(op),
3255 check_expr(fcx, &**rhs);
3259 fcx.write_ty(expr.id, result_t);
3260 if ty::type_is_error(result_t) {
3261 fcx.write_ty(rhs.id, result_t);
3265 fn check_user_binop(fcx: &FnCtxt,
3267 lhs_expr: &ast::Expr,
3268 lhs_resolved_t: ty::t,
3270 rhs: &P<ast::Expr>) -> ty::t {
3271 let tcx = fcx.ccx.tcx;
3272 let lang = &tcx.lang_items;
3273 let (name, trait_did) = match op {
3274 ast::BiAdd => ("add", lang.add_trait()),
3275 ast::BiSub => ("sub", lang.sub_trait()),
3276 ast::BiMul => ("mul", lang.mul_trait()),
3277 ast::BiDiv => ("div", lang.div_trait()),
3278 ast::BiRem => ("rem", lang.rem_trait()),
3279 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3280 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3281 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3282 ast::BiShl => ("shl", lang.shl_trait()),
3283 ast::BiShr => ("shr", lang.shr_trait()),
3284 ast::BiLt => ("lt", lang.ord_trait()),
3285 ast::BiLe => ("le", lang.ord_trait()),
3286 ast::BiGe => ("ge", lang.ord_trait()),
3287 ast::BiGt => ("gt", lang.ord_trait()),
3288 ast::BiEq => ("eq", lang.eq_trait()),
3289 ast::BiNe => ("ne", lang.eq_trait()),
3290 ast::BiAnd | ast::BiOr => {
3291 check_expr(fcx, &**rhs);
3292 return ty::mk_err();
3295 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3296 trait_did, lhs_expr, Some(rhs), DontAutoderefReceiver, || {
3297 fcx.type_error_message(ex.span, |actual| {
3298 format!("binary operation `{}` cannot be applied to type `{}`",
3299 ast_util::binop_to_string(op),
3301 }, lhs_resolved_t, None)
3305 fn check_user_unop(fcx: &FnCtxt,
3308 trait_did: Option<ast::DefId>,
3310 rhs_expr: &ast::Expr,
3311 rhs_t: ty::t) -> ty::t {
3312 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3313 trait_did, rhs_expr, None, DontAutoderefReceiver, || {
3314 fcx.type_error_message(ex.span, |actual| {
3315 format!("cannot apply unary operator `{}` to type `{}`",
3321 fn check_unboxed_closure(fcx: &FnCtxt,
3323 kind: ast::UnboxedClosureKind,
3325 body: &ast::Block) {
3326 let mut fn_ty = astconv::ty_of_closure(
3332 // The `RegionTraitStore` and region_existential_bounds
3333 // are lies, but we ignore them so it doesn't matter.
3335 // FIXME(pcwalton): Refactor this API.
3336 ty::region_existential_bound(ty::ReStatic),
3337 ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
3343 let region = match fcx.infcx().anon_regions(expr.span, 1) {
3345 fcx.ccx.tcx.sess.span_bug(expr.span,
3346 "can't make anon regions here?!")
3348 Ok(regions) => *regions.get(0),
3350 let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
3353 fcx.write_ty(expr.id, closure_type);
3364 // Tuple up the arguments and insert the resulting function type into
3365 // the `unboxed_closures` table.
3366 fn_ty.sig.inputs = if fn_ty.sig.inputs.len() == 0 {
3369 vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)]
3372 let kind = match kind {
3373 ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
3374 ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
3375 ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
3378 let unboxed_closure = ty::UnboxedClosure {
3379 closure_type: fn_ty,
3386 .insert(local_def(expr.id), unboxed_closure);
3389 fn check_expr_fn(fcx: &FnCtxt,
3391 store: ty::TraitStore,
3394 expected: Expectation) {
3395 let tcx = fcx.ccx.tcx;
3397 // Find the expected input/output types (if any). Substitute
3398 // fresh bound regions for any bound regions we find in the
3399 // expected types so as to avoid capture.
3400 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
3403 expected_bounds) = {
3404 match expected_sty {
3405 Some(ty::ty_closure(ref cenv)) => {
3407 replace_late_bound_regions_in_fn_sig(
3409 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
3410 let onceness = match (&store, &cenv.store) {
3411 // As the closure type and onceness go, only three
3412 // combinations are legit:
3416 // If the actual and expected closure type disagree with
3417 // each other, set expected onceness to be always Once or
3418 // Many according to the actual type. Otherwise, it will
3419 // yield either an illegal "many proc" or a less known
3420 // "once closure" in the error message.
3421 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
3422 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
3424 (&ty::UniqTraitStore, _) => ast::Once,
3425 (&ty::RegionTraitStore(..), _) => ast::Many,
3427 (Some(sig), onceness, cenv.bounds)
3430 // Not an error! Means we're inferring the closure type
3431 let (bounds, onceness) = match expr.node {
3432 ast::ExprProc(..) => {
3433 let mut bounds = ty::region_existential_bound(ty::ReStatic);
3434 bounds.builtin_bounds.add(ty::BoundSend); // FIXME
3438 let region = fcx.infcx().next_region_var(
3439 infer::AddrOfRegion(expr.span));
3440 (ty::region_existential_bound(region), ast::Many)
3443 (None, onceness, bounds)
3448 // construct the function type
3449 let fn_ty = astconv::ty_of_closure(fcx,
3458 let fty_sig = fn_ty.sig.clone();
3459 let fty = ty::mk_closure(tcx, fn_ty);
3460 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
3462 fcx.write_ty(expr.id, fty);
3464 // If the closure is a stack closure and hasn't had some non-standard
3465 // style inferred for it, then check it under its parent's style.
3466 // Otherwise, use its own
3467 let (inherited_style, inherited_style_id) = match store {
3468 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
3469 fcx.ps.borrow().def),
3470 ty::UniqTraitStore => (ast::NormalFn, expr.id)
3484 // Check field access expressions
3485 fn check_field(fcx: &FnCtxt,
3487 lvalue_pref: LvaluePreference,
3489 field: &ast::SpannedIdent,
3490 tys: &[P<ast::Ty>]) {
3491 let tcx = fcx.ccx.tcx;
3492 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3493 let expr_t = structurally_resolved_type(fcx, expr.span,
3495 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3496 let (_, autoderefs, field_ty) =
3497 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3498 match ty::get(base_t).sty {
3499 ty::ty_struct(base_id, ref substs) => {
3500 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3501 let fields = ty::lookup_struct_fields(tcx, base_id);
3502 lookup_field_ty(tcx, base_id, fields.as_slice(),
3503 field.node.name, &(*substs))
3510 fcx.write_ty(expr.id, field_ty);
3511 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3517 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
3518 match method::lookup(fcx,
3525 CheckTraitsAndInherentMethods,
3527 IgnoreStaticMethods) {
3529 fcx.type_error_message(
3532 format!("attempted to take value of method `{}` on type \
3533 `{}`", token::get_ident(field.node), actual)
3537 tcx.sess.span_note(field.span,
3538 "maybe a missing `()` to call it? If not, try an anonymous function.");
3542 fcx.type_error_message(
3545 format!("attempted access of field `{}` on \
3546 type `{}`, but no field with that \
3548 token::get_ident(field.node),
3555 fcx.write_error(expr.id);
3558 // Check tuple index expressions
3559 fn check_tup_field(fcx: &FnCtxt,
3561 lvalue_pref: LvaluePreference,
3563 idx: codemap::Spanned<uint>,
3564 _tys: &[P<ast::Ty>]) {
3565 let tcx = fcx.ccx.tcx;
3566 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3567 let expr_t = structurally_resolved_type(fcx, expr.span,
3569 let mut tuple_like = false;
3570 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3571 let (_, autoderefs, field_ty) =
3572 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3573 match ty::get(base_t).sty {
3574 ty::ty_struct(base_id, ref substs) => {
3575 tuple_like = ty::is_tuple_struct(tcx, base_id);
3577 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3578 let fields = ty::lookup_struct_fields(tcx, base_id);
3579 lookup_tup_field_ty(tcx, base_id, fields.as_slice(),
3580 idx.node, &(*substs))
3585 ty::ty_tup(ref v) => {
3587 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3594 fcx.write_ty(expr.id, field_ty);
3595 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3600 fcx.type_error_message(
3604 format!("attempted out-of-bounds tuple index `{}` on \
3609 format!("attempted tuple index `{}` on type `{}`, but the \
3610 type was not a tuple or tuple struct",
3617 fcx.write_error(expr.id);
3620 fn check_struct_or_variant_fields(fcx: &FnCtxt,
3623 class_id: ast::DefId,
3624 node_id: ast::NodeId,
3625 substitutions: subst::Substs,
3626 field_types: &[ty::field_ty],
3627 ast_fields: &[ast::Field],
3628 check_completeness: bool) {
3629 let tcx = fcx.ccx.tcx;
3631 let mut class_field_map = HashMap::new();
3632 let mut fields_found = 0;
3633 for field in field_types.iter() {
3634 class_field_map.insert(field.name, (field.id, false));
3637 let mut error_happened = false;
3639 // Typecheck each field.
3640 for field in ast_fields.iter() {
3641 let mut expected_field_type = ty::mk_err();
3643 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
3646 fcx.type_error_message(
3649 format!("structure `{}` has no field named `{}`",
3650 actual, token::get_ident(field.ident.node))
3654 error_happened = true;
3656 Some((_, true)) => {
3657 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3658 "field `{}` specified more than once",
3659 token::get_ident(field.ident.node));
3660 error_happened = true;
3662 Some((field_id, false)) => {
3663 expected_field_type =
3664 ty::lookup_field_type(
3665 tcx, class_id, field_id, &substitutions);
3666 class_field_map.insert(
3667 field.ident.node.name, (field_id, true));
3671 // Make sure to give a type to the field even if there's
3672 // an error, so we can continue typechecking
3673 check_expr_coercable_to_type(
3676 expected_field_type);
3680 fcx.write_error(node_id);
3683 if check_completeness && !error_happened {
3684 // Make sure the programmer specified all the fields.
3685 assert!(fields_found <= field_types.len());
3686 if fields_found < field_types.len() {
3687 let mut missing_fields = Vec::new();
3688 for class_field in field_types.iter() {
3689 let name = class_field.name;
3690 let (_, seen) = *class_field_map.get(&name);
3692 missing_fields.push(
3693 format!("`{}`", token::get_name(name).get()))
3697 span_err!(tcx.sess, span, E0063,
3698 "missing field{}: {}",
3699 if missing_fields.len() == 1 {""} else {"s"},
3700 missing_fields.connect(", "));
3704 if !error_happened {
3705 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3706 class_id, substitutions));
3710 fn check_struct_constructor(fcx: &FnCtxt,
3712 span: codemap::Span,
3713 class_id: ast::DefId,
3714 fields: &[ast::Field],
3715 base_expr: Option<&ast::Expr>) {
3716 let tcx = fcx.ccx.tcx;
3718 // Generate the struct type.
3720 ty: mut struct_type,
3721 substs: struct_substs
3722 } = fcx.instantiate_item_type(span, class_id);
3724 // Look up and check the fields.
3725 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3726 check_struct_or_variant_fields(fcx,
3732 class_fields.as_slice(),
3734 base_expr.is_none());
3735 if ty::type_is_error(fcx.node_ty(id)) {
3736 struct_type = ty::mk_err();
3739 // Check the base expression if necessary.
3742 Some(base_expr) => {
3743 check_expr_has_type(fcx, &*base_expr, struct_type);
3744 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
3745 struct_type = ty::mk_bot();
3750 // Write in the resulting type.
3751 fcx.write_ty(id, struct_type);
3754 fn check_struct_enum_variant(fcx: &FnCtxt,
3756 span: codemap::Span,
3757 enum_id: ast::DefId,
3758 variant_id: ast::DefId,
3759 fields: &[ast::Field]) {
3760 let tcx = fcx.ccx.tcx;
3762 // Look up the number of type parameters and the raw type, and
3763 // determine whether the enum is region-parameterized.
3766 substs: substitutions
3767 } = fcx.instantiate_item_type(span, enum_id);
3769 // Look up and check the enum variant fields.
3770 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3771 check_struct_or_variant_fields(fcx,
3777 variant_fields.as_slice(),
3780 fcx.write_ty(id, enum_type);
3783 fn check_struct_fields_on_error(fcx: &FnCtxt,
3785 fields: &[ast::Field],
3786 base_expr: &Option<P<ast::Expr>>) {
3787 // Make sure to still write the types
3788 // otherwise we might ICE
3789 fcx.write_error(id);
3790 for field in fields.iter() {
3791 check_expr(fcx, &*field.expr);
3794 Some(ref base) => check_expr(fcx, &**base),
3799 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
3801 let tcx = fcx.ccx.tcx;
3804 ast::ExprBox(ref place, ref subexpr) => {
3805 check_expr(fcx, &**place);
3806 check_expr(fcx, &**subexpr);
3808 let mut checked = false;
3810 ast::ExprPath(ref path) => {
3811 // FIXME(pcwalton): For now we hardcode the two permissible
3812 // places: the exchange heap and the managed heap.
3813 let definition = lookup_def(fcx, path.span, place.id);
3814 let def_id = definition.def_id();
3815 let referent_ty = fcx.expr_ty(&**subexpr);
3816 if tcx.lang_items.exchange_heap() == Some(def_id) {
3817 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3819 } else if tcx.lang_items.managed_heap() == Some(def_id) {
3820 fcx.register_region_obligation(infer::Managed(expr.span),
3823 fcx.write_ty(id, ty::mk_box(tcx, referent_ty));
3831 span_err!(tcx.sess, expr.span, E0066,
3832 "only the managed heap and exchange heap are currently supported");
3833 fcx.write_ty(id, ty::mk_err());
3837 ast::ExprLit(ref lit) => {
3838 let typ = check_lit(fcx, &**lit, expected);
3839 fcx.write_ty(id, typ);
3841 ast::ExprBinary(op, ref lhs, ref rhs) => {
3842 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3844 let lhs_ty = fcx.expr_ty(&**lhs);
3845 let rhs_ty = fcx.expr_ty(&**rhs);
3846 if ty::type_is_error(lhs_ty) ||
3847 ty::type_is_error(rhs_ty) {
3848 fcx.write_error(id);
3850 else if ty::type_is_bot(lhs_ty) ||
3851 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3855 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3856 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3858 let lhs_t = fcx.expr_ty(&**lhs);
3859 let result_t = fcx.expr_ty(expr);
3860 demand::suptype(fcx, expr.span, result_t, lhs_t);
3862 let tcx = fcx.tcx();
3863 if !ty::expr_is_lval(tcx, &**lhs) {
3864 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3867 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3869 // Overwrite result of check_binop...this preserves existing behavior
3870 // but seems quite dubious with regard to user-defined methods
3871 // and so forth. - Niko
3872 if !ty::type_is_error(result_t)
3873 && !ty::type_is_bot(result_t) {
3874 fcx.write_nil(expr.id);
3877 ast::ExprUnary(unop, ref oprnd) => {
3878 let expected_inner = expected.map(fcx, |sty| {
3880 ast::UnBox | ast::UnUniq => match *sty {
3881 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3888 ast::UnNot | ast::UnNeg => {
3896 let lvalue_pref = match unop {
3897 ast::UnDeref => lvalue_pref,
3900 check_expr_with_expectation_and_lvalue_pref(
3901 fcx, &**oprnd, expected_inner, lvalue_pref);
3902 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3904 if !ty::type_is_error(oprnd_t) {
3907 if !ty::type_is_bot(oprnd_t) {
3908 oprnd_t = ty::mk_box(tcx, oprnd_t)
3912 if !ty::type_is_bot(oprnd_t) {
3913 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3917 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3918 oprnd_t = match ty::deref(oprnd_t, true) {
3920 None => match try_overloaded_deref(fcx, expr.span,
3921 Some(MethodCall::expr(expr.id)),
3922 Some(&**oprnd), oprnd_t, lvalue_pref) {
3925 let is_newtype = match ty::get(oprnd_t).sty {
3926 ty::ty_struct(did, ref substs) => {
3927 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3929 && fields.get(0).ident ==
3930 token::special_idents::unnamed_field
3935 // This is an obsolete struct deref
3936 span_err!(tcx.sess, expr.span, E0068,
3937 "single-field tuple-structs can \
3938 no longer be dereferenced");
3940 fcx.type_error_message(expr.span, |actual| {
3941 format!("type `{}` cannot be \
3942 dereferenced", actual)
3951 if !ty::type_is_bot(oprnd_t) {
3952 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3954 if !(ty::type_is_integral(oprnd_t) ||
3955 ty::get(oprnd_t).sty == ty::ty_bool) {
3956 oprnd_t = check_user_unop(fcx, "!", "not",
3957 tcx.lang_items.not_trait(),
3958 expr, &**oprnd, oprnd_t);
3963 if !ty::type_is_bot(oprnd_t) {
3964 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3966 if !(ty::type_is_integral(oprnd_t) ||
3967 ty::type_is_fp(oprnd_t)) {
3968 oprnd_t = check_user_unop(fcx, "-", "neg",
3969 tcx.lang_items.neg_trait(),
3970 expr, &**oprnd, oprnd_t);
3976 fcx.write_ty(id, oprnd_t);
3978 ast::ExprAddrOf(mutbl, ref oprnd) => {
3979 let expected = expected.only_has_type();
3980 let hint = expected.map(fcx, |sty| {
3981 match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3982 _ => NoExpectation }
3984 let lvalue_pref = match mutbl {
3985 ast::MutMutable => PreferMutLvalue,
3986 ast::MutImmutable => NoPreference
3988 check_expr_with_expectation_and_lvalue_pref(fcx,
3993 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3994 let oprnd_t = if ty::type_is_error(tm.ty) {
3996 } else if ty::type_is_bot(tm.ty) {
4000 // Note: at this point, we cannot say what the best lifetime
4001 // is to use for resulting pointer. We want to use the
4002 // shortest lifetime possible so as to avoid spurious borrowck
4003 // errors. Moreover, the longest lifetime will depend on the
4004 // precise details of the value whose address is being taken
4005 // (and how long it is valid), which we don't know yet until type
4006 // inference is complete.
4008 // Therefore, here we simply generate a region variable. The
4009 // region inferencer will then select the ultimate value.
4010 // Finally, borrowck is charged with guaranteeing that the
4011 // value whose address was taken can actually be made to live
4012 // as long as it needs to live.
4014 // String literals are already, implicitly converted to slices.
4015 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
4016 // Empty slices live in static memory.
4017 ast::ExprVec(ref elements) if elements.len() == 0 => {
4018 // Note: we do not assign a lifetime of
4019 // static. This is because the resulting type
4020 // `&'static [T]` would require that T outlives
4022 let region = fcx.infcx().next_region_var(
4023 infer::AddrOfSlice(expr.span));
4024 ty::mk_rptr(tcx, region, tm)
4027 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
4028 ty::mk_rptr(tcx, region, tm)
4032 fcx.write_ty(id, oprnd_t);
4034 ast::ExprPath(ref pth) => {
4035 let defn = lookup_def(fcx, pth.span, id);
4036 let pty = polytype_for_def(fcx, expr.span, defn);
4037 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
4039 // We always require that the type provided as the value for
4040 // a type parameter outlives the moment of instantiation.
4041 constrain_path_type_parameters(fcx, expr);
4043 ast::ExprInlineAsm(ref ia) => {
4044 for &(_, ref input) in ia.inputs.iter() {
4045 check_expr(fcx, &**input);
4047 for &(_, ref out, _) in ia.outputs.iter() {
4048 check_expr(fcx, &**out);
4052 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
4053 ast::ExprBreak(_) => { fcx.write_bot(id); }
4054 ast::ExprAgain(_) => { fcx.write_bot(id); }
4055 ast::ExprRet(ref expr_opt) => {
4056 let ret_ty = fcx.ret_ty;
4058 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
4059 ret_ty, ty::mk_nil()) {
4060 Ok(_) => { /* fall through */ }
4062 span_err!(tcx.sess, expr.span, E0069,
4063 "`return;` in function returning non-nil");
4067 check_expr_coercable_to_type(fcx, &**e, ret_ty);
4072 ast::ExprParen(ref a) => {
4073 check_expr_with_expectation_and_lvalue_pref(fcx,
4077 fcx.write_ty(id, fcx.expr_ty(&**a));
4079 ast::ExprAssign(ref lhs, ref rhs) => {
4080 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4082 let tcx = fcx.tcx();
4083 if !ty::expr_is_lval(tcx, &**lhs) {
4084 span_err!(tcx.sess, expr.span, E0070,
4085 "illegal left-hand side expression");
4088 let lhs_ty = fcx.expr_ty(&**lhs);
4089 check_expr_has_type(fcx, &**rhs, lhs_ty);
4090 let rhs_ty = fcx.expr_ty(&**rhs);
4092 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4094 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4095 fcx.write_error(id);
4096 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
4102 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4103 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4104 id, expr.span, expected);
4106 ast::ExprWhile(ref cond, ref body, _) => {
4107 check_expr_has_type(fcx, &**cond, ty::mk_bool());
4108 check_block_no_value(fcx, &**body);
4109 let cond_ty = fcx.expr_ty(&**cond);
4110 let body_ty = fcx.node_ty(body.id);
4111 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4112 fcx.write_error(id);
4114 else if ty::type_is_bot(cond_ty) {
4121 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4122 check_expr(fcx, &**head);
4123 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4124 vtable2::select_fcx_obligations_where_possible(fcx);
4126 let pcx = pat_ctxt {
4128 map: pat_id_map(&tcx.def_map, &**pat),
4130 _match::check_pat(&pcx, &**pat, typ);
4132 check_block_no_value(fcx, &**block);
4135 ast::ExprLoop(ref body, _) => {
4136 check_block_no_value(fcx, &**body);
4137 if !may_break(tcx, expr.id, &**body) {
4143 ast::ExprMatch(ref discrim, ref arms) => {
4144 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
4146 ast::ExprFnBlock(_, ref decl, ref body) => {
4147 let region = astconv::opt_ast_region_to_region(fcx,
4153 ty::RegionTraitStore(region, ast::MutMutable),
4158 ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
4159 check_unboxed_closure(fcx,
4165 ast::ExprProc(ref decl, ref body) => {
4173 ast::ExprBlock(ref b) => {
4174 check_block_with_expected(fcx, &**b, expected);
4175 fcx.write_ty(id, fcx.node_ty(b.id));
4177 ast::ExprCall(ref f, ref args) => {
4178 // Index expressions need to be handled separately, to inform them
4179 // that they appear in call position.
4180 check_expr(fcx, &**f);
4181 let f_ty = fcx.expr_ty(&**f);
4183 let args: Vec<_> = args.iter().map(|x| x).collect();
4184 if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
4185 check_call(fcx, expr, &**f, args.as_slice());
4186 let (args_bot, args_err) = args.iter().fold((false, false),
4187 |(rest_bot, rest_err), a| {
4188 // is this not working?
4189 let a_ty = fcx.expr_ty(&***a);
4190 (rest_bot || ty::type_is_bot(a_ty),
4191 rest_err || ty::type_is_error(a_ty))});
4192 if ty::type_is_error(f_ty) || args_err {
4193 fcx.write_error(id);
4195 else if ty::type_is_bot(f_ty) || args_bot {
4200 ast::ExprMethodCall(ident, ref tps, ref args) => {
4201 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
4202 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4203 let (args_bot, args_err) = arg_tys.fold((false, false),
4204 |(rest_bot, rest_err), a| {
4205 (rest_bot || ty::type_is_bot(a),
4206 rest_err || ty::type_is_error(a))});
4208 fcx.write_error(id);
4209 } else if args_bot {
4213 ast::ExprCast(ref e, ref t) => {
4215 ast::TyFixedLengthVec(_, ref count_expr) => {
4216 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
4220 check_cast(fcx, expr, &**e, &**t);
4222 ast::ExprVec(ref args) => {
4223 let uty = match expected {
4224 ExpectHasType(uty) => {
4225 match ty::get(uty).sty {
4226 ty::ty_vec(ty, _) => Some(ty),
4233 let typ = match uty {
4235 for e in args.iter() {
4236 check_expr_coercable_to_type(fcx, &**e, uty);
4241 let t: ty::t = fcx.infcx().next_ty_var();
4242 for e in args.iter() {
4243 check_expr_has_type(fcx, &**e, t);
4248 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4249 fcx.write_ty(id, typ);
4251 ast::ExprRepeat(ref element, ref count_expr) => {
4252 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
4253 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4255 let uty = match expected {
4256 ExpectHasType(uty) => {
4257 match ty::get(uty).sty {
4258 ty::ty_vec(ty, _) => Some(ty),
4265 let (element_ty, t) = match uty {
4267 check_expr_coercable_to_type(fcx, &**element, uty);
4271 let t: ty::t = fcx.infcx().next_ty_var();
4272 check_expr_has_type(fcx, &**element, t);
4273 (fcx.expr_ty(&**element), t)
4278 // For [foo, ..n] where n > 1, `foo` must have
4280 fcx.require_type_meets(
4287 if ty::type_is_error(element_ty) {
4288 fcx.write_error(id);
4289 } else if ty::type_is_bot(element_ty) {
4292 let t = ty::mk_vec(tcx, t, Some(count));
4293 fcx.write_ty(id, t);
4296 ast::ExprTup(ref elts) => {
4297 let expected = expected.only_has_type();
4298 let flds = expected.map_to_option(fcx, |sty| {
4300 ty::ty_tup(ref flds) => Some((*flds).clone()),
4304 let mut bot_field = false;
4305 let mut err_field = false;
4307 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4308 let t = match flds {
4309 Some(ref fs) if i < fs.len() => {
4310 let ety = *fs.get(i);
4311 check_expr_coercable_to_type(fcx, &**e, ety);
4315 check_expr_with_expectation(fcx, &**e, NoExpectation);
4319 err_field = err_field || ty::type_is_error(t);
4320 bot_field = bot_field || ty::type_is_bot(t);
4325 } else if err_field {
4326 fcx.write_error(id);
4328 let typ = ty::mk_tup(tcx, elt_ts);
4329 fcx.write_ty(id, typ);
4332 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4333 // Resolve the path.
4334 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
4335 let struct_id = match def {
4336 Some(def::DefVariant(enum_id, variant_id, _)) => {
4337 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4338 variant_id, fields.as_slice());
4341 Some(def::DefTrait(def_id)) => {
4342 span_err!(tcx.sess, path.span, E0159,
4343 "use of trait `{}` as a struct constructor",
4344 pprust::path_to_string(path));
4345 check_struct_fields_on_error(fcx,
4352 // Verify that this was actually a struct.
4353 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4354 match ty::get(typ.ty).sty {
4355 ty::ty_struct(struct_did, _) => {
4356 check_struct_constructor(fcx,
4361 base_expr.as_ref().map(|e| &**e));
4364 span_err!(tcx.sess, path.span, E0071,
4365 "`{}` does not name a structure",
4366 pprust::path_to_string(path));
4367 check_struct_fields_on_error(fcx,
4377 tcx.sess.span_bug(path.span,
4378 "structure constructor wasn't resolved")
4382 // Turn the path into a type and verify that that type unifies with
4383 // the resulting structure type. This is needed to handle type
4384 // parameters correctly.
4385 let actual_structure_type = fcx.expr_ty(&*expr);
4386 if !ty::type_is_error(actual_structure_type) {
4387 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4391 match fcx.mk_subty(false,
4392 infer::Misc(path.span),
4393 actual_structure_type,
4394 type_and_substs.ty) {
4396 Err(type_error) => {
4397 let type_error_description =
4398 ty::type_err_to_str(tcx, &type_error);
4401 .span_err(path.span,
4402 format!("structure constructor specifies a \
4403 structure of type `{}`, but this \
4404 structure has type `{}`: {}",
4406 .ty_to_string(type_and_substs.ty),
4409 actual_structure_type),
4410 type_error_description).as_slice());
4411 ty::note_and_explain_type_err(tcx, &type_error);
4416 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4418 ast::ExprField(ref base, ref field, ref tys) => {
4419 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
4421 ast::ExprTupField(ref base, idx, ref tys) => {
4422 check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
4424 ast::ExprIndex(ref base, ref idx) => {
4425 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4426 check_expr(fcx, &**idx);
4427 let raw_base_t = fcx.expr_ty(&**base);
4428 let idx_t = fcx.expr_ty(&**idx);
4429 if ty::type_is_error(raw_base_t) {
4430 fcx.write_ty(id, raw_base_t);
4431 } else if ty::type_is_error(idx_t) {
4432 fcx.write_ty(id, idx_t);
4434 let (_, autoderefs, field_ty) =
4435 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
4436 lvalue_pref, |base_t, _| ty::index(base_t));
4438 Some(ty) if !ty::type_is_bot(ty) => {
4439 check_expr_has_type(fcx, &**idx, ty::mk_uint());
4440 fcx.write_ty(id, ty);
4441 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
4444 // This is an overloaded method.
4445 let base_t = structurally_resolved_type(fcx,
4448 let method_call = MethodCall::expr(expr.id);
4449 match try_overloaded_index(fcx,
4456 Some(mt) => fcx.write_ty(id, mt.ty),
4458 fcx.type_error_message(expr.span,
4468 fcx.write_ty(id, ty::mk_err())
4475 ast::ExprSlice(ref base, ref start, ref end, ref mutbl) => {
4476 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4477 let raw_base_t = fcx.expr_ty(&**base);
4479 let mut some_err = false;
4480 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
4481 fcx.write_ty(id, raw_base_t);
4486 let check_slice_idx = |e: &ast::Expr| {
4488 let e_t = fcx.expr_ty(e);
4489 if ty::type_is_error(e_t) || ty::type_is_bot(e_t) {
4490 fcx.write_ty(id, e_t);
4494 start.as_ref().map(|e| check_slice_idx(&**e));
4495 end.as_ref().map(|e| check_slice_idx(&**e));
4499 let base_t = structurally_resolved_type(fcx,
4502 let method_call = MethodCall::expr(expr.id);
4503 match try_overloaded_slice(fcx,
4511 Some(mt) => fcx.write_ty(id, mt.ty),
4513 fcx.type_error_message(expr.span,
4515 format!("cannot take a {}slice of a value with type `{}`",
4516 if mutbl == &ast::MutMutable {
4525 fcx.write_ty(id, ty::mk_err())
4532 debug!("type of expr({}) {} is...", expr.id,
4533 syntax::print::pprust::expr_to_string(expr));
4534 debug!("... {}, expected is {}",
4535 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4536 expected.repr(tcx));
4541 fn constrain_path_type_parameters(fcx: &FnCtxt,
4544 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4545 for &ty in item_substs.substs.types.iter() {
4546 let default_bound = ty::ReScope(expr.id);
4547 let origin = infer::RelateDefaultParamBound(expr.span, ty);
4548 fcx.register_region_obligation(origin, ty, default_bound);
4554 fn only_has_type(self) -> Expectation {
4556 NoExpectation | ExpectCastableToType(..) => NoExpectation,
4557 ExpectHasType(t) => ExpectHasType(t)
4561 // Resolves `expected` by a single level if it is a variable. If
4562 // there is no expected type or resolution is not possible (e.g.,
4563 // no constraints yet present), just returns `None`.
4564 fn resolve(self, fcx: &FnCtxt) -> Expectation {
4569 ExpectCastableToType(t) => {
4570 ExpectCastableToType(
4571 fcx.infcx().resolve_type_vars_if_possible(t))
4573 ExpectHasType(t) => {
4575 fcx.infcx().resolve_type_vars_if_possible(t))
4580 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
4581 match self.resolve(fcx) {
4582 NoExpectation => NoExpectation,
4583 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4587 fn map_to_option<O>(self,
4589 unpack: |&ty::sty| -> Option<O>)
4592 match self.resolve(fcx) {
4593 NoExpectation => None,
4594 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4599 impl Repr for Expectation {
4600 fn repr(&self, tcx: &ty::ctxt) -> String {
4602 NoExpectation => format!("NoExpectation"),
4603 ExpectHasType(t) => format!("ExpectHasType({})",
4605 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4611 pub fn check_decl_initializer(fcx: &FnCtxt,
4615 let local_ty = fcx.local_ty(init.span, nid);
4616 check_expr_coercable_to_type(fcx, init, local_ty)
4619 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4620 let tcx = fcx.ccx.tcx;
4622 let t = fcx.local_ty(local.span, local.id);
4623 fcx.write_ty(local.id, t);
4627 check_decl_initializer(fcx, local.id, &**init);
4628 let init_ty = fcx.expr_ty(&**init);
4629 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
4630 fcx.write_ty(local.id, init_ty);
4636 let pcx = pat_ctxt {
4638 map: pat_id_map(&tcx.def_map, &*local.pat),
4640 _match::check_pat(&pcx, &*local.pat, t);
4641 let pat_ty = fcx.node_ty(local.pat.id);
4642 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
4643 fcx.write_ty(local.id, pat_ty);
4647 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4649 let mut saw_bot = false;
4650 let mut saw_err = false;
4652 ast::StmtDecl(ref decl, id) => {
4655 ast::DeclLocal(ref l) => {
4656 check_decl_local(fcx, &**l);
4657 let l_t = fcx.node_ty(l.id);
4658 saw_bot = saw_bot || ty::type_is_bot(l_t);
4659 saw_err = saw_err || ty::type_is_error(l_t);
4661 ast::DeclItem(_) => {/* ignore for now */ }
4664 ast::StmtExpr(ref expr, id) => {
4666 // Check with expected type of ()
4667 check_expr_has_type(fcx, &**expr, ty::mk_nil());
4668 let expr_ty = fcx.expr_ty(&**expr);
4669 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
4670 saw_err = saw_err || ty::type_is_error(expr_ty);
4672 ast::StmtSemi(ref expr, id) => {
4674 check_expr(fcx, &**expr);
4675 let expr_ty = fcx.expr_ty(&**expr);
4676 saw_bot |= ty::type_is_bot(expr_ty);
4677 saw_err |= ty::type_is_error(expr_ty);
4679 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4682 fcx.write_bot(node_id);
4685 fcx.write_error(node_id);
4688 fcx.write_nil(node_id)
4692 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4693 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
4694 let blkty = fcx.node_ty(blk.id);
4695 if ty::type_is_error(blkty) {
4696 fcx.write_error(blk.id);
4698 else if ty::type_is_bot(blkty) {
4699 fcx.write_bot(blk.id);
4702 let nilty = ty::mk_nil();
4703 demand::suptype(fcx, blk.span, nilty, blkty);
4707 fn check_block_with_expected(fcx: &FnCtxt,
4709 expected: Expectation) {
4711 let mut fcx_ps = fcx.ps.borrow_mut();
4712 let fn_style_state = fcx_ps.recurse(blk);
4713 replace(&mut *fcx_ps, fn_style_state)
4716 let mut warned = false;
4717 let mut last_was_bot = false;
4718 let mut any_bot = false;
4719 let mut any_err = false;
4720 for s in blk.stmts.iter() {
4721 check_stmt(fcx, &**s);
4722 let s_id = ast_util::stmt_id(&**s);
4723 let s_ty = fcx.node_ty(s_id);
4724 if last_was_bot && !warned && match s.node {
4725 ast::StmtDecl(ref decl, _) => {
4727 ast::DeclLocal(_) => true,
4731 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4737 .add_lint(lint::builtin::UNREACHABLE_CODE,
4740 "unreachable statement".to_string());
4743 if ty::type_is_bot(s_ty) {
4744 last_was_bot = true;
4746 any_bot = any_bot || ty::type_is_bot(s_ty);
4747 any_err = any_err || ty::type_is_error(s_ty);
4750 None => if any_err {
4751 fcx.write_error(blk.id);
4753 fcx.write_bot(blk.id);
4755 fcx.write_nil(blk.id);
4758 if any_bot && !warned {
4762 .add_lint(lint::builtin::UNREACHABLE_CODE,
4765 "unreachable expression".to_string());
4767 let ety = match expected {
4768 ExpectHasType(ety) => {
4769 check_expr_coercable_to_type(fcx, &**e, ety);
4773 check_expr_with_expectation(fcx, &**e, expected);
4778 fcx.write_ty(blk.id, ety);
4780 fcx.write_error(blk.id);
4782 fcx.write_bot(blk.id);
4787 *fcx.ps.borrow_mut() = prev;
4790 /// Checks a constant appearing in a type. At the moment this is just the
4791 /// length expression in a fixed-length vector, but someday it might be
4792 /// extended to type-level numeric literals.
4793 pub fn check_const_in_type(tcx: &ty::ctxt,
4795 expected_type: ty::t) {
4796 // Synthesize a crate context. The trait map is not needed here (though I
4797 // imagine it will be if we have associated statics --pcwalton), so we
4799 let ccx = CrateCtxt {
4800 trait_map: NodeMap::new(),
4803 let inh = static_inherited_fields(&ccx);
4804 let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
4805 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4808 pub fn check_const(ccx: &CrateCtxt,
4812 let inh = static_inherited_fields(ccx);
4813 let rty = ty::node_id_to_type(ccx.tcx, id);
4814 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4815 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
4816 check_const_with_ty(&fcx, sp, e, declty);
4819 pub fn check_const_with_ty(fcx: &FnCtxt,
4823 // Gather locals in statics (because of block expressions).
4824 // This is technically unnecessary because locals in static items are forbidden,
4825 // but prevents type checking from blowing up before const checking can properly
4827 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4829 check_expr_with_hint(fcx, e, declty);
4830 demand::coerce(fcx, e.span, declty, e);
4831 vtable2::select_all_fcx_obligations_or_error(fcx);
4832 regionck::regionck_expr(fcx, e);
4833 writeback::resolve_type_vars_in_expr(fcx, e);
4836 /// Checks whether a type can be represented in memory. In particular, it
4837 /// identifies types that contain themselves without indirection through a
4838 /// pointer, which would mean their size is unbounded. This is different from
4839 /// the question of whether a type can be instantiated. See the definition of
4840 /// `check_instantiable`.
4841 pub fn check_representable(tcx: &ty::ctxt,
4843 item_id: ast::NodeId,
4844 designation: &str) -> bool {
4845 let rty = ty::node_id_to_type(tcx, item_id);
4847 // Check that it is possible to represent this type. This call identifies
4848 // (1) types that contain themselves and (2) types that contain a different
4849 // recursive type. It is only necessary to throw an error on those that
4850 // contain themselves. For case 2, there must be an inner type that will be
4851 // caught by case 1.
4852 match ty::is_type_representable(tcx, sp, rty) {
4853 ty::SelfRecursive => {
4854 span_err!(tcx.sess, sp, E0072,
4855 "illegal recursive {} type; \
4856 wrap the inner value in a box to make it representable",
4860 ty::Representable | ty::ContainsRecursive => (),
4865 /// Checks whether a type can be created without an instance of itself.
4866 /// This is similar but different from the question of whether a type
4867 /// can be represented. For example, the following type:
4869 /// enum foo { None, Some(foo) }
4871 /// is instantiable but is not representable. Similarly, the type
4873 /// enum foo { Some(@foo) }
4875 /// is representable, but not instantiable.
4876 pub fn check_instantiable(tcx: &ty::ctxt,
4878 item_id: ast::NodeId)
4880 let item_ty = ty::node_id_to_type(tcx, item_id);
4881 if !ty::is_instantiable(tcx, item_ty) {
4882 span_err!(tcx.sess, sp, E0073,
4883 "this type cannot be instantiated without an \
4884 instance of itself; consider using `Option<{}>`",
4885 ppaux::ty_to_string(tcx, item_ty));
4892 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4893 let t = ty::node_id_to_type(tcx, id);
4894 if ty::type_needs_subst(t) {
4895 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4898 match ty::get(t).sty {
4899 ty::ty_struct(did, ref substs) => {
4900 let fields = ty::lookup_struct_fields(tcx, did);
4901 if fields.is_empty() {
4902 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4905 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
4906 if !fields.iter().all(
4907 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4908 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4911 if !ty::type_is_machine(e) {
4912 span_err!(tcx.sess, sp, E0077,
4913 "SIMD vector element type should be machine type");
4921 pub fn check_enum_variants(ccx: &CrateCtxt,
4923 vs: &[P<ast::Variant>],
4926 fn disr_in_range(ccx: &CrateCtxt,
4928 disr: ty::Disr) -> bool {
4929 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4931 ast::TyU8 => disr as u8 as Disr == disr,
4932 ast::TyU16 => disr as u16 as Disr == disr,
4933 ast::TyU32 => disr as u32 as Disr == disr,
4934 ast::TyU64 => disr as u64 as Disr == disr,
4935 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4938 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4940 ast::TyI8 => disr as i8 as Disr == disr,
4941 ast::TyI16 => disr as i16 as Disr == disr,
4942 ast::TyI32 => disr as i32 as Disr == disr,
4943 ast::TyI64 => disr as i64 as Disr == disr,
4944 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4948 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4949 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4953 fn do_check(ccx: &CrateCtxt,
4954 vs: &[P<ast::Variant>],
4956 hint: attr::ReprAttr)
4957 -> Vec<Rc<ty::VariantInfo>> {
4959 let rty = ty::node_id_to_type(ccx.tcx, id);
4960 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4961 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4962 let mut prev_disr_val: Option<ty::Disr> = None;
4964 for v in vs.iter() {
4966 // If the discriminant value is specified explicitly in the enum check whether the
4967 // initialization expression is valid, otherwise use the last value plus one.
4968 let mut current_disr_val = match prev_disr_val {
4969 Some(prev_disr_val) => prev_disr_val + 1,
4970 None => ty::INITIAL_DISCRIMINANT_VALUE
4973 match v.node.disr_expr {
4975 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4977 let inh = static_inherited_fields(ccx);
4978 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4979 let declty = match hint {
4980 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4981 attr::ReprInt(_, attr::SignedInt(ity)) => {
4982 ty::mk_mach_int(ity)
4984 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4985 ty::mk_mach_uint(ity)
4988 check_const_with_ty(&fcx, e.span, &**e, declty);
4989 // check_expr (from check_const pass) doesn't guarantee
4990 // that the expression is in a form that eval_const_expr can
4991 // handle, so we may still get an internal compiler error
4993 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4994 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4995 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4997 span_err!(ccx.tcx.sess, e.span, E0079,
4998 "expected signed integer constant");
5001 span_err!(ccx.tcx.sess, e.span, E0080,
5002 "expected constant: {}", *err);
5009 // Check for duplicate discriminant values
5010 if disr_vals.contains(¤t_disr_val) {
5011 span_err!(ccx.tcx.sess, v.span, E0081,
5012 "discriminant value already exists");
5014 // Check for unrepresentable discriminant values
5016 attr::ReprAny | attr::ReprExtern => (),
5017 attr::ReprInt(sp, ity) => {
5018 if !disr_in_range(ccx, ity, current_disr_val) {
5019 span_err!(ccx.tcx.sess, v.span, E0082,
5020 "discriminant value outside specified type");
5021 span_note!(ccx.tcx.sess, sp,
5022 "discriminant type specified here");
5025 attr::ReprPacked => {
5026 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
5029 disr_vals.push(current_disr_val);
5031 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
5033 prev_disr_val = Some(current_disr_val);
5035 variants.push(variant_info);
5041 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
5042 .as_slice().get(0).unwrap_or(&attr::ReprAny);
5044 if hint != attr::ReprAny && vs.len() <= 1 {
5046 span_err!(ccx.tcx.sess, sp, E0083,
5047 "unsupported representation for univariant enum");
5049 span_err!(ccx.tcx.sess, sp, E0084,
5050 "unsupported representation for zero-variant enum");
5054 let variants = do_check(ccx, vs, id, hint);
5056 // cache so that ty::enum_variants won't repeat this work
5057 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
5059 check_representable(ccx.tcx, sp, id, "enum");
5061 // Check that it is possible to instantiate this enum:
5063 // This *sounds* like the same that as representable, but it's
5064 // not. See def'n of `check_instantiable()` for details.
5065 check_instantiable(ccx.tcx, sp, id);
5068 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
5069 lookup_def_ccx(fcx.ccx, sp, id)
5072 // Returns the type parameter count and the type for the given definition.
5073 pub fn polytype_for_def(fcx: &FnCtxt,
5078 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
5079 let typ = fcx.local_ty(sp, nid);
5080 return no_params(typ);
5082 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
5083 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
5084 def::DefStruct(id) => {
5085 return ty::lookup_item_type(fcx.ccx.tcx, id);
5089 def::DefAssociatedTy(..) |
5091 def::DefTyParam(..)=> {
5092 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
5094 def::DefMod(..) | def::DefForeignMod(..) => {
5095 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
5097 def::DefUse(..) => {
5098 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
5100 def::DefRegion(..) => {
5101 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
5103 def::DefTyParamBinder(..) => {
5104 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
5106 def::DefLabel(..) => {
5107 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
5109 def::DefSelfTy(..) => {
5110 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5112 def::DefMethod(..) => {
5113 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found method");
5118 // Instantiates the given path, which must refer to an item with the given
5119 // number of type parameters and type.
5120 pub fn instantiate_path(fcx: &FnCtxt,
5125 node_id: ast::NodeId) {
5126 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
5127 path.repr(fcx.tcx()),
5128 def.repr(fcx.tcx()),
5130 polytype.repr(fcx.tcx()));
5132 // We need to extract the type parameters supplied by the user in
5133 // the path `path`. Due to the current setup, this is a bit of a
5134 // tricky-process; the problem is that resolve only tells us the
5135 // end-point of the path resolution, and not the intermediate steps.
5136 // Luckily, we can (at least for now) deduce the intermediate steps
5137 // just from the end-point.
5139 // There are basically three cases to consider:
5141 // 1. Reference to a *type*, such as a struct or enum:
5143 // mod a { struct Foo<T> { ... } }
5145 // Because we don't allow types to be declared within one
5146 // another, a path that leads to a type will always look like
5147 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
5148 // that only the final segment can have type parameters, and
5149 // they are located in the TypeSpace.
5151 // *Note:* Generally speaking, references to types don't
5152 // actually pass through this function, but rather the
5153 // `ast_ty_to_ty` function in `astconv`. However, in the case
5154 // of struct patterns (and maybe literals) we do invoke
5155 // `instantiate_path` to get the general type of an instance of
5156 // a struct. (In these cases, there are actually no type
5157 // parameters permitted at present, but perhaps we will allow
5158 // them in the future.)
5160 // 1b. Reference to a enum variant or tuple-like struct:
5162 // struct foo<T>(...)
5163 // enum E<T> { foo(...) }
5165 // In these cases, the parameters are declared in the type
5168 // 2. Reference to a *fn item*:
5172 // In this case, the path will again always have the form
5173 // `a::b::foo::<T>` where only the final segment should have
5174 // type parameters. However, in this case, those parameters are
5175 // declared on a value, and hence are in the `FnSpace`.
5177 // 3. Reference to a *method*:
5179 // impl<A> SomeStruct<A> {
5183 // Here we can have a path like
5184 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5185 // may appear in two places. The penultimate segment,
5186 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5187 // final segment, `foo::<B>` contains parameters in fn space.
5189 // The first step then is to categorize the segments appropriately.
5191 assert!(path.segments.len() >= 1);
5192 let mut segment_spaces;
5194 // Case 1 and 1b. Reference to a *type* or *enum variant*.
5195 def::DefSelfTy(..) |
5196 def::DefStruct(..) |
5197 def::DefVariant(..) |
5198 def::DefTyParamBinder(..) |
5200 def::DefAssociatedTy(..) |
5202 def::DefPrimTy(..) |
5203 def::DefTyParam(..) => {
5204 // Everything but the final segment should have no
5205 // parameters at all.
5206 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5207 segment_spaces.push(Some(subst::TypeSpace));
5210 // Case 2. Reference to a top-level value.
5212 def::DefStatic(..) => {
5213 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5214 segment_spaces.push(Some(subst::FnSpace));
5217 // Case 3. Reference to a method.
5218 def::DefStaticMethod(..) => {
5219 assert!(path.segments.len() >= 2);
5220 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
5221 segment_spaces.push(Some(subst::TypeSpace));
5222 segment_spaces.push(Some(subst::FnSpace));
5225 // Other cases. Various nonsense that really shouldn't show up
5226 // here. If they do, an error will have been reported
5227 // elsewhere. (I hope)
5229 def::DefForeignMod(..) |
5231 def::DefMethod(..) |
5233 def::DefRegion(..) |
5235 def::DefUpvar(..) => {
5236 segment_spaces = Vec::from_elem(path.segments.len(), None);
5239 assert_eq!(segment_spaces.len(), path.segments.len());
5241 debug!("segment_spaces={}", segment_spaces);
5243 // Next, examine the definition, and determine how many type
5244 // parameters we expect from each space.
5245 let type_defs = &polytype.generics.types;
5246 let region_defs = &polytype.generics.regions;
5248 // Now that we have categorized what space the parameters for each
5249 // segment belong to, let's sort out the parameters that the user
5250 // provided (if any) into their appropriate spaces. We'll also report
5251 // errors if type parameters are provided in an inappropriate place.
5252 let mut substs = Substs::empty();
5253 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5256 report_error_if_segment_contains_type_parameters(fcx, segment);
5260 push_explicit_parameters_from_segment_to_substs(fcx,
5270 // Now we have to compare the types that the user *actually*
5271 // provided against the types that were *expected*. If the user
5272 // did not provide any types, then we want to substitute inference
5273 // variables. If the user provided some types, we may still need
5274 // to add defaults. If the user provided *too many* types, that's
5276 for &space in ParamSpace::all().iter() {
5277 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5278 assert_eq!(substs.types.len(space), type_defs.len(space));
5280 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5281 assert_eq!(substs.regions().len(space), region_defs.len(space));
5284 fcx.add_obligations_for_parameters(
5285 traits::ObligationCause::new(span,
5286 traits::ItemObligation(def.def_id())),
5288 &polytype.generics);
5290 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
5294 fn report_error_if_segment_contains_type_parameters(
5296 segment: &ast::PathSegment)
5298 for typ in segment.types.iter() {
5299 span_err!(fcx.tcx().sess, typ.span, E0085,
5300 "type parameters may not appear here");
5304 for lifetime in segment.lifetimes.iter() {
5305 span_err!(fcx.tcx().sess, lifetime.span, E0086,
5306 "lifetime parameters may not appear here");
5311 fn push_explicit_parameters_from_segment_to_substs(
5313 space: subst::ParamSpace,
5314 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
5315 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5316 segment: &ast::PathSegment,
5317 substs: &mut Substs)
5320 * Finds the parameters that the user provided and adds them
5321 * to `substs`. If too many parameters are provided, then
5322 * reports an error and clears the output vector.
5324 * We clear the output vector because that will cause the
5325 * `adjust_XXX_parameters()` later to use inference
5326 * variables. This seems less likely to lead to derived
5329 * Note that we *do not* check for *too few* parameters here.
5330 * Due to the presence of defaults etc that is more
5331 * complicated. I wanted however to do the reporting of *too
5332 * many* parameters here because we can easily use the precise
5333 * span of the N+1'th parameter.
5337 let type_count = type_defs.len(space);
5338 assert_eq!(substs.types.len(space), 0);
5339 for (i, typ) in segment.types.iter().enumerate() {
5340 let t = fcx.to_ty(&**typ);
5342 substs.types.push(space, t);
5343 } else if i == type_count {
5344 span_err!(fcx.tcx().sess, typ.span, E0087,
5345 "too many type parameters provided: \
5346 expected at most {} parameter(s), \
5347 found {} parameter(s)",
5348 type_count, segment.types.len());
5349 substs.types.truncate(space, 0);
5355 let region_count = region_defs.len(space);
5356 assert_eq!(substs.regions().len(space), 0);
5357 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
5358 let r = ast_region_to_region(fcx.tcx(), lifetime);
5359 if i < region_count {
5360 substs.mut_regions().push(space, r);
5361 } else if i == region_count {
5362 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5363 "too many lifetime parameters provided: \
5364 expected {} parameter(s), found {} parameter(s)",
5366 segment.lifetimes.len());
5367 substs.mut_regions().truncate(space, 0);
5373 fn adjust_type_parameters(
5377 defs: &VecPerParamSpace<ty::TypeParameterDef>,
5378 substs: &mut Substs)
5380 let provided_len = substs.types.len(space);
5381 let desired = defs.get_slice(space);
5382 let required_len = desired.iter()
5383 .take_while(|d| d.default.is_none())
5386 debug!("adjust_type_parameters(space={}, \
5395 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5396 assert!(provided_len <= desired.len());
5398 // Nothing specified at all: supply inference variables for
5400 if provided_len == 0 {
5401 substs.types.replace(space,
5402 fcx.infcx().next_ty_vars(desired.len()));
5406 // Too few parameters specified: report an error and use Err
5408 if provided_len < required_len {
5410 if desired.len() != required_len { "at least " } else { "" };
5411 span_err!(fcx.tcx().sess, span, E0089,
5412 "too few type parameters provided: expected {}{} parameter(s) \
5413 , found {} parameter(s)",
5414 qualifier, required_len, provided_len);
5415 substs.types.replace(space,
5416 Vec::from_elem(desired.len(), ty::mk_err()));
5420 // Otherwise, add in any optional parameters that the user
5421 // omitted. The case of *too many* parameters is handled
5423 // push_explicit_parameters_from_segment_to_substs(). Note
5424 // that the *default* type are expressed in terms of all prior
5425 // parameters, so we have to substitute as we go with the
5426 // partial substitution that we have built up.
5427 for i in range(provided_len, desired.len()) {
5428 let default = desired[i].default.unwrap();
5429 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5430 substs.types.push(space, default);
5432 assert_eq!(substs.types.len(space), desired.len());
5434 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5437 fn adjust_region_parameters(
5441 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5442 substs: &mut Substs)
5444 let provided_len = substs.mut_regions().len(space);
5445 let desired = defs.get_slice(space);
5447 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5448 assert!(provided_len <= desired.len());
5450 // If nothing was provided, just use inference variables.
5451 if provided_len == 0 {
5452 substs.mut_regions().replace(
5454 fcx.infcx().region_vars_for_defs(span, desired));
5458 // If just the right number were provided, everybody is happy.
5459 if provided_len == desired.len() {
5463 // Otherwise, too few were provided. Report an error and then
5464 // use inference variables.
5465 span_err!(fcx.tcx().sess, span, E0090,
5466 "too few lifetime parameters provided: expected {} parameter(s), \
5467 found {} parameter(s)",
5468 desired.len(), provided_len);
5470 substs.mut_regions().replace(
5472 fcx.infcx().region_vars_for_defs(span, desired));
5476 // Resolves `typ` by a single level if `typ` is a type variable. If no
5477 // resolution is possible, then an error is reported.
5478 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
5479 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
5480 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
5482 fcx.type_error_message(sp, |_actual| {
5483 "the type of this value must be known in this \
5484 context".to_string()
5486 demand::suptype(fcx, sp, ty::mk_err(), tp);
5492 // Returns the one-level-deep structure of the given type.
5493 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
5495 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
5498 // Returns true if b contains a break that can exit from b
5499 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5500 // First: is there an unlabeled break immediately
5502 (loop_query(&*b, |e| {
5504 ast::ExprBreak(_) => true,
5508 // Second: is there a labeled break with label
5509 // <id> nested anywhere inside the loop?
5510 (block_query(b, |e| {
5512 ast::ExprBreak(Some(_)) => {
5513 match cx.def_map.borrow().find(&e.id) {
5514 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5522 pub fn check_bounds_are_used(ccx: &CrateCtxt,
5524 tps: &OwnedSlice<ast::TyParam>,
5526 debug!("check_bounds_are_used(n_tps={}, ty={})",
5527 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5529 // make a vector of booleans initially false, set to true when used
5530 if tps.len() == 0u { return; }
5531 let mut tps_used = Vec::from_elem(tps.len(), false);
5533 ty::walk_ty(ty, |t| {
5534 match ty::get(t).sty {
5535 ty::ty_param(ParamTy {idx, ..}) => {
5536 debug!("Found use of ty param num {}", idx);
5537 *tps_used.get_mut(idx) = true;
5543 for (i, b) in tps_used.iter().enumerate() {
5545 span_err!(ccx.tcx.sess, span, E0091,
5546 "type parameter `{}` is unused",
5547 token::get_ident(tps.get(i).ident));
5552 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5553 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
5554 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5558 let name = token::get_ident(it.ident);
5559 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5560 let split : Vec<&str> = name.get().split('_').collect();
5561 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5563 //We only care about the operation here
5564 match *split.get(1) {
5565 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5569 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5571 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5574 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5575 "min" | "umax" | "umin" => {
5576 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5580 (0, Vec::new(), ty::mk_nil())
5583 span_err!(tcx.sess, it.span, E0092,
5584 "unrecognized atomic operation function: `{}`", op);
5591 "abort" => (0, Vec::new(), ty::mk_bot()),
5592 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
5594 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5595 "init" => (1u, Vec::new(), param(ccx, 0u)),
5596 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5597 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
5598 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5599 "move_val_init" => {
5602 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
5607 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5608 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5611 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5613 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5615 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5617 mutbl: ast::MutImmutable
5619 (1u, Vec::new(), td_ptr)
5622 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5626 ty::mk_struct(ccx.tcx, did,
5627 subst::Substs::empty())),
5629 tcx.sess.span_fatal(it.span, msg.as_slice());
5634 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5636 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5638 let region0 = ty::ReLateBound(it.id, ty::BrAnon(0));
5639 let region1 = ty::ReLateBound(it.id, ty::BrAnon(1));
5640 let visitor_object_ty =
5641 match ty::visitor_object_ty(tcx, region0, region1) {
5642 Ok((_, vot)) => vot,
5643 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5646 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5648 mutbl: ast::MutImmutable
5650 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
5655 ty::mk_ptr(tcx, ty::mt {
5657 mutbl: ast::MutImmutable
5661 ty::mk_ptr(tcx, ty::mt {
5663 mutbl: ast::MutImmutable
5666 "copy_memory" | "copy_nonoverlapping_memory" |
5667 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5670 ty::mk_ptr(tcx, ty::mt {
5672 mutbl: ast::MutMutable
5674 ty::mk_ptr(tcx, ty::mt {
5676 mutbl: ast::MutImmutable
5682 "set_memory" | "volatile_set_memory" => {
5685 ty::mk_ptr(tcx, ty::mt {
5687 mutbl: ast::MutMutable
5694 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5695 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5698 vec!( ty::mk_f32(), ty::mk_i32() ),
5703 vec!( ty::mk_f64(), ty::mk_i32() ),
5706 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5707 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5708 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5709 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5712 vec!( ty::mk_f32(), ty::mk_f32() ),
5717 vec!( ty::mk_f64(), ty::mk_f64() ),
5720 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5721 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5722 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5723 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5724 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5725 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5726 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5727 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5728 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5729 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5732 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5737 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5740 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5741 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5742 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5743 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5744 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5745 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5746 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5747 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5748 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5749 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5750 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5751 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5752 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5753 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5754 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5755 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5756 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5757 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5758 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5759 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5760 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5761 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5762 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5763 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5764 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5765 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5766 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5767 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5768 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5769 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5770 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5773 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5775 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
5777 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5778 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5779 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5781 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5782 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5783 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5785 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5786 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5787 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5789 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5790 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5791 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5793 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5794 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5795 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5797 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5798 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5799 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5801 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5802 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5803 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5805 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5806 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5807 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5809 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5812 span_err!(tcx.sess, it.span, E0093,
5813 "unrecognized intrinsic function: `{}`", *other);
5818 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5819 fn_style: ast::UnsafeFn,
5820 abi: abi::RustIntrinsic,
5828 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5829 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5830 if i_n_tps != n_tps {
5831 span_err!(tcx.sess, it.span, E0094,
5832 "intrinsic has wrong number of type \
5833 parameters: found {}, expected {}",
5836 require_same_types(tcx,
5843 format!("intrinsic has wrong type: expected `{}`",
5844 ppaux::ty_to_string(ccx.tcx, fty))
5849 impl Repr for RegionObligation {
5850 fn repr(&self, tcx: &ty::ctxt) -> String {
5851 format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5852 self.sub_region.repr(tcx),
5853 self.sup_type.repr(tcx),
5854 self.origin.repr(tcx))