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
79 pub use self::LvaluePreference::*;
80 pub use self::DerefArgs::*;
81 pub use self::Expectation::*;
82 use self::IsBinopAssignment::*;
83 use self::TupleArgumentsFlag::*;
86 use middle::const_eval;
88 use middle::lang_items::IteratorItem;
89 use middle::mem_categorization::McResult;
90 use middle::mem_categorization;
91 use middle::pat_util::pat_id_map;
93 use middle::region::CodeExtent;
95 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
97 use middle::ty::{FnSig, VariantInfo};
98 use middle::ty::{Polytype};
99 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
100 use middle::ty::{mod, Ty};
101 use middle::ty::liberate_late_bound_regions;
102 use middle::ty_fold::TypeFolder;
103 use middle::typeck::astconv::AstConv;
104 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
105 use middle::typeck::astconv;
106 use middle::typeck::check::_match::pat_ctxt;
107 use middle::typeck::CrateCtxt;
108 use middle::typeck::infer;
109 use middle::typeck::rscope::RegionScope;
110 use middle::typeck::{lookup_def_ccx};
111 use middle::typeck::no_params;
112 use middle::typeck::{require_same_types};
113 use middle::typeck::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
114 use middle::typeck::{TypeAndSubsts};
116 use middle::lang_items::TypeIdLangItem;
118 use util::common::{block_query, indenter, loop_query};
120 use util::ppaux::{UserString, Repr};
121 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
123 use std::cell::{Cell, Ref, RefCell};
124 use std::collections::hash_map::{Occupied, Vacant};
125 use std::mem::replace;
128 use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
130 use syntax::ast_util::{local_def, PostExpansionMethod};
131 use syntax::ast_util;
133 use syntax::codemap::Span;
135 use syntax::owned_slice::OwnedSlice;
136 use syntax::parse::token;
137 use syntax::print::pprust;
140 use syntax::visit::Visitor;
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<'tcx>>>,
166 param_env: ty::ParameterEnvironment<'tcx>,
169 node_types: RefCell<NodeMap<Ty<'tcx>>>,
170 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
171 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
172 method_map: MethodMap<'tcx>,
173 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
174 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
175 object_cast_map: ObjectCastMap<'tcx>,
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<'tcx>>>>,
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<'tcx>>>>,
208 // Tracks trait obligations incurred during this function body.
209 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
212 struct RegionObligation<'tcx> {
213 sub_region: ty::Region,
215 origin: infer::SubregionOrigin<'tcx>,
218 /// When type-checking an expression, we propagate downward
219 /// whatever type hint we are able in the form of an `Expectation`.
220 enum Expectation<'tcx> {
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<'tcx>),
227 /// This expression will be cast to the `Ty`
228 ExpectCastableToType(Ty<'tcx>),
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,
287 ret_ty: ty::FnOutput<'tcx>,
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<'tcx>> {
303 fn node_method_ty(&self, method_call: typeck::MethodCall)
304 -> Option<Ty<'tcx>> {
305 self.inh.method_map.borrow().get(&method_call).map(|m| m.ty)
307 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
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<CodeExtent> {
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()[upvar_id].clone()
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)
324 -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
325 &self.inh.unboxed_closures
329 impl<'a, 'tcx> Inherited<'a, 'tcx> {
330 fn new(tcx: &'a ty::ctxt<'tcx>,
331 param_env: ty::ParameterEnvironment<'tcx>)
332 -> Inherited<'a, 'tcx> {
334 infcx: infer::new_infer_ctxt(tcx),
335 locals: RefCell::new(NodeMap::new()),
336 param_env: param_env,
337 node_types: RefCell::new(NodeMap::new()),
338 item_substs: RefCell::new(NodeMap::new()),
339 adjustments: RefCell::new(NodeMap::new()),
340 method_map: RefCell::new(FnvHashMap::new()),
341 object_cast_map: RefCell::new(NodeMap::new()),
342 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
343 unboxed_closures: RefCell::new(DefIdMap::new()),
344 fn_sig_map: RefCell::new(NodeMap::new()),
345 region_obligations: RefCell::new(NodeMap::new()),
346 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
351 // Used by check_const and check_enum_variants
352 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
353 inh: &'a Inherited<'a, 'tcx>,
354 rty: ty::FnOutput<'tcx>,
355 body_id: ast::NodeId)
356 -> FnCtxt<'a, 'tcx> {
359 writeback_errors: Cell::new(false),
360 err_count_on_creation: ccx.tcx.sess.err_count(),
362 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
368 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
369 -> Inherited<'a, 'tcx> {
370 // It's kind of a kludge to manufacture a fake function context
371 // and statement context, but we might as well do write the code only once
372 let param_env = ty::empty_parameter_environment();
373 Inherited::new(ccx.tcx, param_env)
376 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
378 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
379 fn visit_item(&mut self, i: &ast::Item) {
380 check_item(self.ccx, i);
381 visit::walk_item(self, i);
385 pub fn check_item_types(ccx: &CrateCtxt) {
386 let krate = ccx.tcx.map.krate();
387 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
388 visit::walk_crate(&mut visit, krate);
390 // If types are not well-formed, it leads to all manner of errors
391 // downstream, so stop reporting errors at this point.
392 ccx.tcx.sess.abort_if_errors();
394 let mut visit = CheckItemTypesVisitor { ccx: ccx };
395 visit::walk_crate(&mut visit, krate);
397 ccx.tcx.sess.abort_if_errors();
400 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
405 param_env: ty::ParameterEnvironment<'tcx>) {
406 // Compute the fty from point of view of inside fn
407 // (replace any type-scheme with a type)
408 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
411 ty::ty_bare_fn(ref fn_ty) => {
412 let inh = Inherited::new(ccx.tcx, param_env);
413 let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
414 decl, id, body, &inh);
416 vtable::select_all_fcx_obligations_or_error(&fcx);
417 regionck::regionck_fn(&fcx, id, body);
418 fcx.default_diverging_type_variables_to_nil();
419 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
421 _ => ccx.tcx.sess.impossible_case(body.span,
422 "check_bare_fn: function type expected")
426 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
427 fcx: &'a FnCtxt<'a, 'tcx>
430 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
431 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
434 // infer the variable's type
435 let var_ty = self.fcx.infcx().next_ty_var();
436 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
440 // take type that the user specified
441 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
448 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
449 // Add explicitly-declared locals.
450 fn visit_local(&mut self, local: &ast::Local) {
451 let o_ty = match local.ty.node {
452 ast::TyInfer => None,
453 _ => Some(self.fcx.to_ty(&*local.ty))
455 self.assign(local.span, local.id, o_ty);
456 debug!("Local variable {} is assigned type {}",
457 self.fcx.pat_to_string(&*local.pat),
458 self.fcx.infcx().ty_to_string(
459 self.fcx.inh.locals.borrow()[local.id].clone()));
460 visit::walk_local(self, local);
463 // Add pattern bindings.
464 fn visit_pat(&mut self, p: &ast::Pat) {
466 ast::PatIdent(_, ref path1, _)
467 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
468 let var_ty = self.assign(p.span, p.id, None);
470 self.fcx.require_type_is_sized(var_ty, p.span,
471 traits::VariableType(p.id));
473 debug!("Pattern binding {} is assigned to {} with type {}",
474 token::get_ident(path1.node),
475 self.fcx.infcx().ty_to_string(
476 self.fcx.inh.locals.borrow()[p.id].clone()),
477 var_ty.repr(self.fcx.tcx()));
481 visit::walk_pat(self, p);
484 fn visit_block(&mut self, b: &ast::Block) {
485 // non-obvious: the `blk` variable maps to region lb, so
486 // we have to keep this up-to-date. This
487 // is... unfortunate. It'd be nice to not need this.
488 visit::walk_block(self, b);
491 // Since an expr occurs as part of the type fixed size arrays we
492 // need to record the type for that node
493 fn visit_ty(&mut self, t: &ast::Ty) {
495 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
496 self.visit_ty(&**ty);
497 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
499 _ => visit::walk_ty(self, t)
503 // Don't descend into fns and items
504 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
505 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
506 fn visit_item(&mut self, _: &ast::Item) { }
510 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
511 fn_style: ast::FnStyle,
512 fn_style_id: ast::NodeId,
513 fn_sig: &ty::FnSig<'tcx>,
517 inherited: &'a Inherited<'a, 'tcx>)
518 -> FnCtxt<'a, 'tcx> {
520 * Helper used by check_bare_fn and check_expr_fn. Does the
521 * grungy work of checking a function body and returns the
522 * function context used for that purpose, since in the case of a
523 * fn item there is still a bit more to do.
526 * - inherited: other fields inherited from the enclosing fn (if any)
530 let err_count_on_creation = tcx.sess.err_count();
532 // First, we have to replace any bound regions in the fn type with free ones.
533 // The free region references will be bound the node_id of the body block.
534 let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
536 let arg_tys = fn_sig.inputs.as_slice();
537 let ret_ty = fn_sig.output;
539 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
544 // Create the function context. This is either derived from scratch or,
545 // in the case of function expressions, based on the outer context.
548 writeback_errors: Cell::new(false),
549 err_count_on_creation: err_count_on_creation,
551 ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)),
556 // Remember return type so that regionck can access it later.
557 let mut fn_sig_tys: Vec<Ty> =
562 if let ty::FnConverging(ret_ty) = ret_ty {
563 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
564 fn_sig_tys.push(ret_ty);
567 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
569 fn_sig_tys.repr(tcx));
571 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
574 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
576 // Add formal parameters.
577 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
578 // Create type variables for each argument.
579 pat_util::pat_bindings(
582 |_bm, pat_id, sp, _path| {
583 let var_ty = visit.assign(sp, pat_id, None);
584 fcx.require_type_is_sized(var_ty, sp,
585 traits::VariableType(pat_id));
588 // Check the pattern.
591 map: pat_id_map(&tcx.def_map, &*input.pat),
593 _match::check_pat(&pcx, &*input.pat, *arg_ty);
596 visit.visit_block(body);
599 check_block_with_expected(&fcx, body, match ret_ty {
600 ty::FnConverging(result_type) => ExpectHasType(result_type),
601 ty::FnDiverging => NoExpectation
604 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
605 fcx.write_ty(input.id, *arg);
611 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
614 check_representable(tcx, span, id, "struct");
615 check_instantiable(tcx, span, id);
617 if ty::lookup_simd(tcx, local_def(id)) {
618 check_simd(tcx, span, id);
622 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
623 debug!("check_item(it.id={}, it.ident={})",
625 ty::item_path_str(ccx.tcx, local_def(it.id)));
626 let _indenter = indenter();
629 ast::ItemStatic(_, _, ref e) |
630 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
631 ast::ItemEnum(ref enum_definition, _) => {
632 check_enum_variants(ccx,
634 enum_definition.variants.as_slice(),
637 ast::ItemFn(ref decl, _, _, _, ref body) => {
638 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
639 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
640 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
642 ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
643 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
645 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
647 match *opt_trait_ref {
648 Some(ref ast_trait_ref) => {
650 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
651 check_impl_items_against_trait(ccx,
655 impl_items.as_slice());
660 for impl_item in impl_items.iter() {
662 ast::MethodImplItem(ref m) => {
663 check_method_body(ccx, &impl_pty.generics, &**m);
665 ast::TypeImplItem(_) => {
666 // Nothing to do here.
672 ast::ItemTrait(_, _, _, ref trait_methods) => {
673 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
674 for trait_method in trait_methods.iter() {
675 match *trait_method {
676 RequiredMethod(..) => {
677 // Nothing to do, since required methods don't have
680 ProvidedMethod(ref m) => {
681 check_method_body(ccx, &trait_def.generics, &**m);
683 TypeTraitItem(_) => {
689 ast::ItemStruct(..) => {
690 check_struct(ccx, it.id, it.span);
692 ast::ItemTy(ref t, ref generics) => {
693 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
694 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
696 ast::ItemForeignMod(ref m) => {
697 if m.abi == abi::RustIntrinsic {
698 for item in m.items.iter() {
699 check_intrinsic_type(ccx, &**item);
702 for item in m.items.iter() {
703 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
704 if !pty.generics.types.is_empty() {
705 span_err!(ccx.tcx.sess, item.span, E0044,
706 "foreign items may not have type parameters");
710 ast::ForeignItemFn(ref fn_decl, _) => {
711 if fn_decl.variadic && m.abi != abi::C {
712 span_err!(ccx.tcx.sess, item.span, E0045,
713 "variadic function must have C calling convention");
721 _ => {/* nothing to do */ }
725 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
726 item_generics: &ty::Generics<'tcx>,
727 method: &ast::Method) {
729 * Type checks a method body.
732 * - `item_generics`: generics defined on the impl/trait that contains
734 * - `self_bound`: bound for the `Self` type parameter, if any
735 * - `method`: the method definition
738 debug!("check_method_body(item_generics={}, method.id={})",
739 item_generics.repr(ccx.tcx),
741 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
743 let fty = ty::node_id_to_type(ccx.tcx, method.id);
744 debug!("fty (raw): {}", fty.repr(ccx.tcx));
746 let body_id = method.pe_body().id;
747 let fty = liberate_late_bound_regions(
748 ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value;
749 debug!("fty (liberated): {}", fty.repr(ccx.tcx));
752 &*method.pe_fn_decl(),
759 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
761 ast_trait_ref: &ast::TraitRef,
762 impl_trait_ref: &ty::TraitRef<'tcx>,
763 impl_items: &[ast::ImplItem]) {
764 // Locate trait methods
766 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
768 // Check existing impl methods to see if they are both present in trait
769 // and compatible with trait signature
770 for impl_item in impl_items.iter() {
772 ast::MethodImplItem(ref impl_method) => {
773 let impl_method_def_id = local_def(impl_method.id);
774 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
777 // If this is an impl of a trait method, find the
778 // corresponding method definition in the trait.
779 let opt_trait_method_ty =
782 ti.name() == impl_item_ty.name()
784 match opt_trait_method_ty {
785 Some(trait_method_ty) => {
786 match (trait_method_ty, &impl_item_ty) {
787 (&ty::MethodTraitItem(ref trait_method_ty),
788 &ty::MethodTraitItem(ref impl_method_ty)) => {
789 compare_impl_method(ccx.tcx,
792 impl_method.pe_body().id,
797 // This is span_bug as it should have already been
798 // caught in resolve.
800 .span_bug(impl_method.span,
801 format!("item `{}` is of a \
802 different kind from \
805 impl_item_ty.name()),
806 pprust::path_to_string(
807 &ast_trait_ref.path))
813 // This is span_bug as it should have already been
814 // caught in resolve.
818 "method `{}` is not a member of trait `{}`",
819 token::get_name(impl_item_ty.name()),
820 pprust::path_to_string(
821 &ast_trait_ref.path)).as_slice());
825 ast::TypeImplItem(ref typedef) => {
826 let typedef_def_id = local_def(typedef.id);
827 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
830 // If this is an impl of an associated type, find the
831 // corresponding type definition in the trait.
832 let opt_associated_type =
835 ti.name() == typedef_ty.name()
837 match opt_associated_type {
838 Some(associated_type) => {
839 match (associated_type, &typedef_ty) {
840 (&ty::TypeTraitItem(_),
841 &ty::TypeTraitItem(_)) => {}
843 // This is `span_bug` as it should have
844 // already been caught in resolve.
846 .span_bug(typedef.span,
847 format!("item `{}` is of a \
848 different kind from \
852 pprust::path_to_string(
853 &ast_trait_ref.path))
859 // This is `span_bug` as it should have already been
860 // caught in resolve.
864 "associated type `{}` is not a member of \
866 token::get_name(typedef_ty.name()),
867 pprust::path_to_string(
868 &ast_trait_ref.path)).as_slice());
875 // Check for missing items from trait
876 let provided_methods = ty::provided_trait_methods(tcx,
877 impl_trait_ref.def_id);
878 let mut missing_methods = Vec::new();
879 for trait_item in trait_items.iter() {
881 ty::MethodTraitItem(ref trait_method) => {
883 impl_items.iter().any(|ii| {
885 ast::MethodImplItem(ref m) => {
886 m.pe_ident().name == trait_method.name
888 ast::TypeImplItem(_) => false,
892 provided_methods.iter().any(
893 |m| m.name == trait_method.name);
894 if !is_implemented && !is_provided {
895 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
898 ty::TypeTraitItem(ref associated_type) => {
899 let is_implemented = impl_items.iter().any(|ii| {
901 ast::TypeImplItem(ref typedef) => {
902 typedef.ident.name == associated_type.name
904 ast::MethodImplItem(_) => false,
908 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
914 if !missing_methods.is_empty() {
915 span_err!(tcx.sess, impl_span, E0046,
916 "not all trait items implemented, missing: {}",
917 missing_methods.connect(", "));
922 * Checks that a method from an impl conforms to the signature of
923 * the same method as declared in the trait.
927 * - impl_generics: the generics declared on the impl itself (not the method!)
928 * - impl_m: type of the method we are checking
929 * - impl_m_span: span to use for reporting errors
930 * - impl_m_body_id: id of the method body
931 * - trait_m: the method in the trait
932 * - trait_to_impl_substs: the substitutions used on the type of the trait
934 fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
935 impl_m: &ty::Method<'tcx>,
937 impl_m_body_id: ast::NodeId,
938 trait_m: &ty::Method<'tcx>,
939 impl_trait_ref: &ty::TraitRef<'tcx>) {
940 debug!("compare_impl_method(impl_trait_ref={})",
941 impl_trait_ref.repr(tcx));
943 let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
945 // The impl's trait ref may bind late-bound regions from the impl.
946 // Liberate them and assign them the scope of the method body.
948 // An example would be:
950 // impl<'a> Foo<&'a T> for &'a U { ... }
952 // Here, the region parameter `'a` is late-bound, so the
953 // trait reference associated with the impl will be
955 // for<'a> Foo<&'a T>
957 // liberating will convert this into:
961 // where `'A` is the `ReFree` version of `'a`.
962 let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
964 debug!("impl_trait_ref (liberated) = {}",
965 impl_trait_ref.repr(tcx));
967 let infcx = infer::new_infer_ctxt(tcx);
969 let trait_to_impl_substs = &impl_trait_ref.substs;
971 // Try to give more informative error messages about self typing
972 // mismatches. Note that any mismatch will also be detected
973 // below, where we construct a canonical function type that
974 // includes the self parameter as a normal parameter. It's just
975 // that the error messages you get out of this code are a bit more
976 // inscrutable, particularly for cases where one method has no
978 match (&trait_m.explicit_self, &impl_m.explicit_self) {
979 (&ty::StaticExplicitSelfCategory,
980 &ty::StaticExplicitSelfCategory) => {}
981 (&ty::StaticExplicitSelfCategory, _) => {
984 format!("method `{}` has a `{}` declaration in the impl, \
985 but not in the trait",
986 token::get_name(trait_m.name),
987 ppaux::explicit_self_category_to_str(
988 &impl_m.explicit_self)).as_slice());
991 (_, &ty::StaticExplicitSelfCategory) => {
994 format!("method `{}` has a `{}` declaration in the trait, \
995 but not in the impl",
996 token::get_name(trait_m.name),
997 ppaux::explicit_self_category_to_str(
998 &trait_m.explicit_self)).as_slice());
1002 // Let the type checker catch other errors below
1006 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
1007 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
1008 if num_impl_m_type_params != num_trait_m_type_params {
1009 span_err!(tcx.sess, impl_m_span, E0049,
1010 "method `{}` has {} type parameter{} \
1011 but its trait declaration has {} type parameter{}",
1012 token::get_name(trait_m.name),
1013 num_impl_m_type_params,
1014 if num_impl_m_type_params == 1 {""} else {"s"},
1015 num_trait_m_type_params,
1016 if num_trait_m_type_params == 1 {""} else {"s"});
1020 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
1021 span_err!(tcx.sess, impl_m_span, E0050,
1022 "method `{}` has {} parameter{} \
1023 but the declaration in trait `{}` has {}",
1024 token::get_name(trait_m.name),
1025 impl_m.fty.sig.inputs.len(),
1026 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
1027 ty::item_path_str(tcx, trait_m.def_id),
1028 trait_m.fty.sig.inputs.len());
1032 // This code is best explained by example. Consider a trait:
1034 // trait Trait<'t,T> {
1035 // fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
1040 // impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
1041 // fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
1044 // We wish to decide if those two method types are compatible.
1046 // We start out with trait_to_impl_substs, that maps the trait
1047 // type parameters to impl type parameters. This is taken from the
1048 // impl trait reference:
1050 // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
1052 // We create a mapping `dummy_substs` that maps from the impl type
1053 // parameters to fresh types and regions. For type parameters,
1054 // this is the identity transform, but we could as well use any
1055 // skolemized types. For regions, we convert from bound to free
1056 // regions (Note: but only early-bound regions, i.e., those
1057 // declared on the impl or used in type parameter bounds).
1059 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1061 // Now we can apply skol_substs to the type of the impl method
1062 // to yield a new function type in terms of our fresh, skolemized
1065 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1067 // We now want to extract and substitute the type of the *trait*
1068 // method and compare it. To do so, we must create a compound
1069 // substitution by combining trait_to_impl_substs and
1070 // impl_to_skol_substs, and also adding a mapping for the method
1071 // type parameters. We extend the mapping to also include
1072 // the method parameters.
1074 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1076 // Applying this to the trait method type yields:
1078 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1080 // This type is also the same but the name of the bound region ('a
1081 // vs 'b). However, the normal subtyping rules on fn types handle
1082 // this kind of equivalency just fine.
1084 // Create mapping from impl to skolemized.
1086 impl_m.generics.types.map(
1087 |d| ty::mk_param_from_def(tcx, d));
1089 impl_m.generics.regions.map(
1090 |l| ty::free_region_from_def(impl_m_body_id, l));
1091 let impl_to_skol_substs =
1092 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1094 // Create mapping from trait to skolemized.
1095 let trait_to_skol_substs =
1096 trait_to_impl_substs
1097 .subst(tcx, &impl_to_skol_substs)
1098 .with_method(skol_tps.get_slice(subst::FnSpace).to_vec(),
1099 skol_regions.get_slice(subst::FnSpace).to_vec());
1101 // Check region bounds.
1102 if !check_region_bounds_on_impl_method(tcx,
1108 &trait_to_skol_substs,
1109 &impl_to_skol_substs) {
1113 // Check bounds. Note that the bounds from the impl may reference
1114 // late-bound regions declared on the impl, so liberate those.
1115 // This requires two artificial binding scopes -- one for the impl,
1116 // and one for the method.
1118 // An example would be:
1120 // trait Foo<T> { fn method<U:Bound<T>>() { ... } }
1122 // impl<'a> Foo<&'a T> for &'a U {
1123 // fn method<U:Bound<&'a T>>() { ... }
1126 // Here, the region parameter `'a` is late-bound, so in the bound
1127 // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
1128 // depth of 3 (it is nested within 3 binders: the impl, method,
1129 // and trait-ref itself). So when we do the liberation, we have
1130 // two introduce two `ty::bind` scopes, one for the impl and one
1133 // The only late-bounded regions that can possibly appear here are
1134 // from the impl, not the method. This is because region
1135 // parameters declared on the method which appear in a type bound
1136 // would be early bound. On the trait side, there can be no
1137 // late-bound lifetimes because trait definitions do not introduce
1138 // a late region binder.
1140 trait_m.generics.types.get_slice(subst::FnSpace).iter()
1141 .map(|trait_param_def| &trait_param_def.bounds);
1143 impl_m.generics.types.get_slice(subst::FnSpace).iter()
1144 .map(|impl_param_def|
1145 liberate_late_bound_regions(
1148 &ty::bind(ty::bind(impl_param_def.bounds.clone()))).value.value);
1149 for (i, (trait_param_bounds, impl_param_bounds)) in
1150 trait_bounds.zip(impl_bounds).enumerate()
1152 // Check that the impl does not require any builtin-bounds
1153 // that the trait does not guarantee:
1155 impl_param_bounds.builtin_bounds -
1156 trait_param_bounds.builtin_bounds;
1157 if !extra_bounds.is_empty() {
1158 span_err!(tcx.sess, impl_m_span, E0051,
1159 "in method `{}`, type parameter {} requires `{}`, \
1160 which is not required by the corresponding type parameter \
1161 in the trait declaration",
1162 token::get_name(trait_m.name),
1164 extra_bounds.user_string(tcx));
1168 // Check that the trait bounds of the trait imply the bounds of its
1171 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1172 // traits, but I doubt that'll be wanted often, so meh.
1173 for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
1174 debug!("compare_impl_method(): impl-trait-bound subst");
1175 let impl_trait_bound =
1176 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1178 // There may be late-bound regions from the impl in the
1179 // impl's bound, so "liberate" those. Note that the
1180 // trait_to_skol_substs is derived from the impl's
1181 // trait-ref, and the late-bound regions appearing there
1182 // have already been liberated, so the result should match
1185 let found_match_in_trait =
1186 trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
1187 debug!("compare_impl_method(): trait-bound subst");
1189 trait_bound.subst(tcx, &trait_to_skol_substs);
1190 let infcx = infer::new_infer_ctxt(tcx);
1191 infer::mk_sub_trait_refs(&infcx,
1193 infer::Misc(impl_m_span),
1195 impl_trait_bound.clone()).is_ok()
1198 if !found_match_in_trait {
1199 span_err!(tcx.sess, impl_m_span, E0052,
1200 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1201 required by the corresponding type parameter in the trait declaration",
1202 token::get_name(trait_m.name),
1204 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1209 // Compute skolemized form of impl and trait method tys. Note
1210 // that we must liberate the late-bound regions from the impl.
1211 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1212 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1213 let impl_fty = liberate_late_bound_regions(
1214 tcx, impl_m_body_scope, &ty::bind(impl_fty)).value;
1215 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1216 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1218 // Check the impl method type IM is a subtype of the trait method
1219 // type TM. To see why this makes sense, think of a vtable. The
1220 // expected type of the function pointers in the vtable is the
1221 // type TM of the trait method. The actual type will be the type
1222 // IM of the impl method. Because we know that IM <: TM, that
1223 // means that anywhere a TM is expected, a IM will do instead. In
1224 // other words, anyone expecting to call a method with the type
1225 // from the trait, can safely call a method with the type from the
1227 debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
1229 trait_fty.repr(tcx));
1230 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1231 impl_fty, trait_fty) {
1234 span_err!(tcx.sess, impl_m_span, E0053,
1235 "method `{}` has an incompatible type for trait: {}",
1236 token::get_name(trait_m.name),
1237 ty::type_err_to_str(tcx, terr));
1238 ty::note_and_explain_type_err(tcx, terr);
1242 // Finally, resolve all regions. This catches wily misuses of lifetime
1244 infcx.resolve_regions_and_report_errors();
1246 fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
1248 impl_m: &ty::Method<'tcx>,
1249 impl_m_body_scope: CodeExtent,
1250 trait_generics: &ty::Generics<'tcx>,
1251 impl_generics: &ty::Generics<'tcx>,
1252 trait_to_skol_substs: &Substs<'tcx>,
1253 impl_to_skol_substs: &Substs<'tcx>)
1258 Check that region bounds on impl method are the same as those
1259 on the trait. In principle, it could be ok for there to be
1260 fewer region bounds on the impl method, but this leads to an
1261 annoying corner case that is painful to handle (described
1262 below), so for now we can just forbid it.
1265 `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1269 fn method2<'b:'a>();
1272 impl<'a> Foo<'a> for ... {
1273 fn method1<'b:'a>() { .. case 1, definitely bad .. }
1274 fn method2<'b>() { .. case 2, could be ok .. }
1277 The "definitely bad" case is case #1. Here, the impl adds an
1278 extra constraint not present in the trait.
1280 The "maybe bad" case is case #2. Here, the impl adds an extra
1281 constraint not present in the trait. We could in principle
1282 allow this, but it interacts in a complex way with early/late
1283 bound resolution of lifetimes. Basically the presence or
1284 absence of a lifetime bound affects whether the lifetime is
1285 early/late bound, and right now the code breaks if the trait
1286 has an early bound lifetime parameter and the method does not.
1290 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1291 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1293 debug!("check_region_bounds_on_impl_method: \
1296 trait_to_skol_substs={} \
1297 impl_to_skol_substs={}",
1298 trait_generics.repr(tcx),
1299 impl_generics.repr(tcx),
1300 trait_to_skol_substs.repr(tcx),
1301 impl_to_skol_substs.repr(tcx));
1303 // Must have same number of early-bound lifetime parameters.
1304 // Unfortunately, if the user screws up the bounds, then this
1305 // will change classification between early and late. E.g.,
1306 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1307 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1308 // in trait but 0 in the impl. But if we report "expected 2
1309 // but found 0" it's confusing, because it looks like there
1310 // are zero. Since I don't quite know how to phrase things at
1311 // the moment, give a kind of vague error message.
1312 if trait_params.len() != impl_params.len() {
1315 format!("lifetime parameters or bounds on method `{}` do \
1316 not match the trait declaration",
1317 token::get_name(impl_m.name)).as_slice());
1321 // Each parameter `'a:'b+'c+'d` in trait should have the same
1322 // set of bounds in the impl, after subst.
1323 for (trait_param, impl_param) in
1324 trait_params.iter().zip(
1328 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1330 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1332 // The bounds may reference late-bound regions from the
1333 // impl declaration. In that case, we want to replace
1334 // those with the liberated variety so as to match the
1335 // versions appearing in the `trait_to_skol_substs`.
1336 // There are two-levels of binder to be aware of: the
1337 // impl, and the method.
1339 ty::liberate_late_bound_regions(
1340 tcx, impl_m_body_scope, &ty::bind(ty::bind(impl_bounds))).value.value;
1342 debug!("check_region_bounds_on_impl_method: \
1347 trait_param.repr(tcx),
1348 impl_param.repr(tcx),
1349 trait_bounds.repr(tcx),
1350 impl_bounds.repr(tcx));
1352 // Collect the set of bounds present in trait but not in
1354 let missing: Vec<ty::Region> =
1356 .filter(|&b| !impl_bounds.contains(b))
1360 // Collect set present in impl but not in trait.
1361 let extra: Vec<ty::Region> =
1363 .filter(|&b| !trait_bounds.contains(b))
1367 debug!("missing={} extra={}",
1368 missing.repr(tcx), extra.repr(tcx));
1370 let err = if missing.len() != 0 || extra.len() != 0 {
1374 "the lifetime parameter `{}` declared in the impl \
1375 has a distinct set of bounds \
1376 from its counterpart `{}` \
1377 declared in the trait",
1378 impl_param.name.user_string(tcx),
1379 trait_param.name.user_string(tcx)).as_slice());
1385 if missing.len() != 0 {
1388 format!("the impl is missing the following bounds: `{}`",
1389 missing.user_string(tcx)).as_slice());
1392 if extra.len() != 0 {
1395 format!("the impl has the following extra bounds: `{}`",
1396 extra.user_string(tcx)).as_slice());
1408 fn check_cast(fcx: &FnCtxt,
1409 cast_expr: &ast::Expr,
1412 let id = cast_expr.id;
1413 let span = cast_expr.span;
1415 // Find the type of `e`. Supply hints based on the type we are casting to,
1417 let t_1 = fcx.to_ty(t);
1418 let t_1 = structurally_resolved_type(fcx, span, t_1);
1420 if ty::type_is_scalar(t_1) {
1421 // Supply the type as a hint so as to influence integer
1422 // literals and other things that might care.
1423 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1))
1428 let t_e = fcx.expr_ty(e);
1430 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1431 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1433 if ty::type_is_error(t_e) {
1434 fcx.write_error(id);
1438 if !ty::type_is_sized(fcx.tcx(), t_1) {
1439 let tstr = fcx.infcx().ty_to_string(t_1);
1440 fcx.type_error_message(span, |actual| {
1441 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1444 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1445 let mtstr = match mt {
1446 ast::MutMutable => "mut ",
1447 ast::MutImmutable => ""
1449 if ty::type_is_trait(t_1) {
1450 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1452 span_help!(fcx.tcx().sess, span,
1453 "consider using an implicit coercion to `&{}{}` instead",
1457 ty::ty_uniq(..) => {
1458 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1461 span_help!(fcx.tcx().sess, e.span,
1462 "consider using a box or reference as appropriate");
1465 fcx.write_error(id);
1469 if ty::type_is_trait(t_1) {
1470 // This will be looked up later on.
1471 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1472 fcx.write_ty(id, t_1);
1476 let t_1 = structurally_resolved_type(fcx, span, t_1);
1477 let t_e = structurally_resolved_type(fcx, span, t_e);
1479 if ty::type_is_nil(t_e) {
1480 fcx.type_error_message(span, |actual| {
1481 format!("cast from nil: `{}` as `{}`",
1483 fcx.infcx().ty_to_string(t_1))
1485 } else if ty::type_is_nil(t_1) {
1486 fcx.type_error_message(span, |actual| {
1487 format!("cast to nil: `{}` as `{}`",
1489 fcx.infcx().ty_to_string(t_1))
1493 let t_1_is_scalar = ty::type_is_scalar(t_1);
1494 let t_1_is_char = ty::type_is_char(t_1);
1495 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1496 let t_1_is_float = ty::type_is_floating_point(t_1);
1498 // casts to scalars other than `char` and `bare fn` are trivial
1499 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1500 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1501 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1502 fcx.type_error_message(span, |actual| {
1503 format!("illegal cast; cast through an \
1504 integer first: `{}` as `{}`",
1506 fcx.infcx().ty_to_string(t_1))
1509 // casts from C-like enums are allowed
1510 } else if t_1_is_char {
1511 let t_e = fcx.infcx().shallow_resolve(t_e);
1512 if t_e.sty != ty::ty_uint(ast::TyU8) {
1513 fcx.type_error_message(span, |actual| {
1514 format!("only `u8` can be cast as \
1515 `char`, not `{}`", actual)
1518 } else if t_1.sty == ty::ty_bool {
1519 span_err!(fcx.tcx().sess, span, E0054,
1520 "cannot cast as `bool`, compare with zero instead");
1521 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1522 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1523 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1525 ty::ty_vec(_, Some(_)) => {}
1528 if ty::type_needs_infer(t2) {
1529 // This prevents this special case from going off when casting
1530 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1535 let el = ty::sequence_element_type(fcx.tcx(), t1);
1536 infer::mk_eqty(fcx.infcx(),
1543 // Due to the limitations of LLVM global constants,
1544 // region pointers end up pointing at copies of
1545 // vector elements instead of the original values.
1546 // To allow unsafe pointers to work correctly, we
1547 // need to special-case obtaining an unsafe pointer
1548 // from a region pointer to a vector.
1550 /* this cast is only allowed from &[T, ..n] to *T or
1552 match (&t_e.sty, &t_1.sty) {
1553 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1554 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1555 if types_compatible(fcx, e.span, mt1, mt2) => {
1556 /* this case is allowed */
1559 demand::coerce(fcx, e.span, t_1, &*e);
1562 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1564 If more type combinations should be supported than are
1565 supported here, then file an enhancement issue and
1566 record the issue number in this comment.
1568 fcx.type_error_message(span, |actual| {
1569 format!("non-scalar cast: `{}` as `{}`",
1571 fcx.infcx().ty_to_string(t_1))
1573 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1574 fcx.type_error_message(span, |actual| {
1575 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1578 fcx.infcx().ty_to_string(t_1))
1582 fcx.write_ty(id, t_1);
1585 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1586 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1588 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
1589 ty::lookup_item_type(self.tcx(), id)
1592 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1593 ty::lookup_trait_def(self.tcx(), id)
1596 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1597 self.infcx().next_ty_var()
1600 fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId)
1605 fn associated_type_binding(&self,
1607 _: Option<Ty<'tcx>>,
1611 self.tcx().sess.span_err(span, "unsupported associated type binding");
1616 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1617 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1619 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
1623 pub fn sess(&self) -> &Session {
1627 pub fn err_count_since_creation(&self) -> uint {
1628 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1632 impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
1633 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1634 Some(self.next_region_var(infer::MiscVariable(span)))
1637 fn anon_regions(&self, span: Span, count: uint)
1638 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1639 Ok(Vec::from_fn(count, |_| {
1640 self.next_region_var(infer::MiscVariable(span))
1645 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1646 pub fn tag(&self) -> String {
1647 format!("{}", self as *const FnCtxt)
1650 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1651 match self.inh.locals.borrow().get(&nid) {
1654 self.tcx().sess.span_bug(
1656 format!("no type for local variable {}",
1662 pub fn default_diverging_type_variables_to_nil(&self) {
1663 for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1664 if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
1665 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1671 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1672 debug!("write_ty({}, {}) in fcx {}",
1673 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1674 self.inh.node_types.borrow_mut().insert(node_id, ty);
1677 pub fn write_object_cast(&self,
1679 trait_ref: Rc<ty::TraitRef<'tcx>>) {
1680 debug!("write_object_cast key={} trait_ref={}",
1681 key, trait_ref.repr(self.tcx()));
1682 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1685 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1686 if !substs.substs.is_noop() {
1687 debug!("write_substs({}, {}) in fcx {}",
1689 substs.repr(self.tcx()),
1692 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1696 pub fn write_autoderef_adjustment(&self,
1697 node_id: ast::NodeId,
1700 if derefs == 0 { return; }
1701 self.write_adjustment(
1704 ty::AdjustDerefRef(ty::AutoDerefRef {
1710 pub fn write_adjustment(&self,
1711 node_id: ast::NodeId,
1713 adj: ty::AutoAdjustment<'tcx>) {
1714 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1716 if adj.is_identity() {
1720 // Careful: adjustments can imply trait obligations if we are
1721 // casting from a concrete type to an object type. I think
1722 // it'd probably be nicer to move the logic that creates the
1723 // obligation into the code that creates the adjustment, but
1724 // that's a bit awkward, so instead we go digging and pull the
1725 // obligation out here.
1726 self.register_adjustment_obligations(span, &adj);
1727 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1730 fn register_adjustment_obligations(&self,
1732 adj: &ty::AutoAdjustment<'tcx>) {
1734 ty::AdjustAddEnv(..) => { }
1735 ty::AdjustDerefRef(ref d_r) => {
1738 self.register_autoref_obligations(span, a_r);
1746 fn register_autoref_obligations(&self,
1748 autoref: &ty::AutoRef<'tcx>) {
1750 ty::AutoUnsize(ref unsize) => {
1751 self.register_unsize_obligations(span, unsize);
1753 ty::AutoPtr(_, _, None) |
1754 ty::AutoUnsafe(_, None) => {
1756 ty::AutoPtr(_, _, Some(ref a_r)) |
1757 ty::AutoUnsafe(_, Some(ref a_r)) => {
1758 self.register_autoref_obligations(span, &**a_r)
1760 ty::AutoUnsizeUniq(ref unsize) => {
1761 self.register_unsize_obligations(span, unsize);
1766 fn register_unsize_obligations(&self,
1768 unsize: &ty::UnsizeKind<'tcx>) {
1769 debug!("register_unsize_obligations: unsize={}", unsize);
1772 ty::UnsizeLength(..) => {}
1773 ty::UnsizeStruct(ref u, _) => {
1774 self.register_unsize_obligations(span, &**u)
1776 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1777 vtable::check_object_safety(self.tcx(), ty_trait, span);
1779 // If the type is `Foo+'a`, ensures that the type
1780 // being cast to `Foo+'a` implements `Foo`:
1781 vtable::register_object_cast_obligations(self,
1786 // If the type is `Foo+'a`, ensures that the type
1787 // being cast to `Foo+'a` outlives `'a`:
1788 let origin = infer::RelateObjectBound(span);
1789 self.register_region_obligation(origin, self_ty, ty_trait.bounds.region_bound);
1794 pub fn instantiate_type(&self,
1797 -> TypeAndSubsts<'tcx>
1800 * Returns the type of `def_id` with all generics replaced by
1801 * by fresh type/region variables. Also returns the
1802 * substitution from the type parameters on `def_id` to the
1803 * fresh variables. Registers any trait obligations specified
1804 * on `def_id` at the same time.
1806 * Note that function is only intended to be used with types
1807 * (notably, not impls). This is because it doesn't do any
1808 * instantiation of late-bound regions.
1812 ty::lookup_item_type(self.tcx(), def_id);
1814 self.infcx().fresh_substs_for_generics(
1816 &polytype.generics);
1818 polytype.generics.to_bounds(self.tcx(), &substs);
1819 self.add_obligations_for_parameters(
1820 traits::ObligationCause::new(
1822 traits::ItemObligation(def_id)),
1826 polytype.ty.subst(self.tcx(), &substs);
1834 pub fn write_nil(&self, node_id: ast::NodeId) {
1835 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1837 pub fn write_error(&self, node_id: ast::NodeId) {
1838 self.write_ty(node_id, ty::mk_err());
1841 pub fn require_type_meets(&self,
1844 code: traits::ObligationCauseCode<'tcx>,
1845 bound: ty::BuiltinBound)
1847 let obligation = traits::obligation_for_builtin_bound(
1849 traits::ObligationCause::new(span, code),
1853 Ok(ob) => self.register_obligation(ob),
1858 pub fn require_type_is_sized(&self,
1861 code: traits::ObligationCauseCode<'tcx>)
1863 self.require_type_meets(ty, span, code, ty::BoundSized);
1866 pub fn require_expr_have_sized_type(&self,
1868 code: traits::ObligationCauseCode<'tcx>)
1870 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1873 pub fn register_obligation(&self,
1874 obligation: traits::Obligation<'tcx>)
1876 debug!("register_obligation({})",
1877 obligation.repr(self.tcx()));
1879 self.inh.fulfillment_cx
1881 .register_obligation(self.tcx(), obligation);
1884 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1885 let t = ast_ty_to_ty(self, self.infcx(), ast_t);
1887 let mut bounds_checker = wf::BoundsChecker::new(self,
1889 CodeExtent::from_node_id(self.body_id),
1891 bounds_checker.check_ty(t);
1896 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1897 pat.repr(self.tcx())
1900 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1901 match self.inh.node_types.borrow().get(&ex.id) {
1904 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1905 self.tag()).as_slice());
1910 pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
1912 * Fetch type of `expr` after applying adjustments that
1913 * have been recorded in the fcx.
1916 let adjustments = self.inh.adjustments.borrow();
1917 let adjustment = adjustments.get(&expr.id);
1918 self.adjust_expr_ty(expr, adjustment)
1921 pub fn adjust_expr_ty(&self,
1923 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1927 * Apply `adjustment` to the type of `expr`
1930 let raw_ty = self.expr_ty(expr);
1931 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1932 ty::adjust_ty(self.tcx(),
1937 |method_call| self.inh.method_map.borrow()
1939 .map(|method| method.ty))
1942 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1943 match self.inh.node_types.borrow().get(&id) {
1946 self.tcx().sess.bug(
1947 format!("no type for node {}: {} in fcx {}",
1948 id, self.tcx().map.node_to_string(id),
1949 self.tag()).as_slice());
1954 pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts<'tcx>>> {
1955 self.inh.item_substs.borrow()
1958 pub fn opt_node_ty_substs(&self,
1960 f: |&ty::ItemSubsts<'tcx>|) {
1961 match self.inh.item_substs.borrow().get(&id) {
1967 pub fn mk_subty(&self,
1968 a_is_expected: bool,
1969 origin: infer::TypeOrigin,
1972 -> Result<(), ty::type_err<'tcx>> {
1973 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1976 pub fn can_mk_subty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
1977 -> Result<(), ty::type_err<'tcx>> {
1978 infer::can_mk_subty(self.infcx(), sub, sup)
1981 pub fn can_mk_eqty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
1982 -> Result<(), ty::type_err<'tcx>> {
1983 infer::can_mk_eqty(self.infcx(), sub, sup)
1986 pub fn mk_assignty(&self,
1990 -> Result<(), ty::type_err<'tcx>> {
1991 match infer::mk_coercety(self.infcx(),
1993 infer::ExprAssignable(expr.span),
1997 Err(ref e) => Err((*e)),
1998 Ok(Some(adjustment)) => {
1999 self.write_adjustment(expr.id, expr.span, adjustment);
2005 pub fn mk_eqty(&self,
2006 a_is_expected: bool,
2007 origin: infer::TypeOrigin,
2010 -> Result<(), ty::type_err<'tcx>> {
2011 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
2014 pub fn mk_subr(&self,
2015 origin: infer::SubregionOrigin<'tcx>,
2018 infer::mk_subr(self.infcx(), origin, sub, sup)
2021 pub fn type_error_message(&self,
2023 mk_msg: |String| -> String,
2024 actual_ty: Ty<'tcx>,
2025 err: Option<&ty::type_err<'tcx>>) {
2026 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
2029 pub fn report_mismatched_types(&self,
2033 err: &ty::type_err<'tcx>) {
2034 self.infcx().report_mismatched_types(sp, e, a, err)
2037 pub fn register_region_obligation(&self,
2038 origin: infer::SubregionOrigin<'tcx>,
2043 * Registers an obligation for checking later, during
2044 * regionck, that the type `ty` must outlive the region `r`.
2047 let mut region_obligations = self.inh.region_obligations.borrow_mut();
2048 let region_obligation = RegionObligation { sub_region: r,
2052 match region_obligations.entry(self.body_id) {
2053 Vacant(entry) => { entry.set(vec![region_obligation]); },
2054 Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
2058 pub fn add_default_region_param_bounds(&self,
2059 substs: &Substs<'tcx>,
2062 for &ty in substs.types.iter() {
2063 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
2064 let origin = infer::RelateDefaultParamBound(expr.span, ty);
2065 self.register_region_obligation(origin, ty, default_bound);
2069 pub fn add_obligations_for_parameters(&self,
2070 cause: traits::ObligationCause<'tcx>,
2071 substs: &Substs<'tcx>,
2072 generic_bounds: &ty::GenericBounds<'tcx>)
2075 * Given a fully substituted set of bounds (`generic_bounds`),
2076 * and the values with which each type/region parameter was
2077 * instantiated (`substs`), creates and registers suitable
2078 * trait/region obligations.
2080 * For example, if there is a function:
2082 * fn foo<'a,T:'a>(...)
2088 * Then we will create a fresh region variable `'$0` and a
2089 * fresh type variable `$1` for `'a` and `T`. This routine
2090 * will add a region obligation `$1:'$0` and register it
2094 assert!(!generic_bounds.has_escaping_regions());
2096 debug!("add_obligations_for_parameters(substs={}, generic_bounds={})",
2097 substs.repr(self.tcx()),
2098 generic_bounds.repr(self.tcx()));
2100 self.add_trait_obligations_for_generics(cause, substs, generic_bounds);
2101 self.add_region_obligations_for_generics(cause, substs, generic_bounds);
2104 fn add_trait_obligations_for_generics(&self,
2105 cause: traits::ObligationCause<'tcx>,
2106 substs: &Substs<'tcx>,
2107 generic_bounds: &ty::GenericBounds<'tcx>) {
2108 assert!(!generic_bounds.has_escaping_regions());
2109 assert!(!substs.has_regions_escaping_depth(0));
2112 traits::obligations_for_generics(self.tcx(),
2116 obligations.map_move(|o| self.register_obligation(o));
2119 fn add_region_obligations_for_generics(&self,
2120 cause: traits::ObligationCause<'tcx>,
2121 substs: &Substs<'tcx>,
2122 generic_bounds: &ty::GenericBounds<'tcx>)
2124 assert!(!generic_bounds.has_escaping_regions());
2125 assert_eq!(generic_bounds.types.iter().len(), substs.types.iter().len());
2127 for (type_bounds, &type_param) in
2128 generic_bounds.types.iter().zip(
2129 substs.types.iter())
2131 self.add_region_obligations_for_type_parameter(
2132 cause.span, type_bounds, type_param);
2135 assert_eq!(generic_bounds.regions.iter().len(),
2136 substs.regions().iter().len());
2137 for (region_bounds, ®ion_param) in
2138 generic_bounds.regions.iter().zip(
2139 substs.regions().iter())
2141 self.add_region_obligations_for_region_parameter(
2142 cause.span, region_bounds.as_slice(), region_param);
2146 fn add_region_obligations_for_type_parameter(&self,
2148 param_bound: &ty::ParamBounds<'tcx>,
2151 // For each declared region bound `T:r`, `T` must outlive `r`.
2153 ty::required_region_bounds(
2155 param_bound.region_bounds.as_slice(),
2156 param_bound.builtin_bounds,
2157 param_bound.trait_bounds.as_slice());
2158 for &r in region_bounds.iter() {
2159 let origin = infer::RelateParamBound(span, ty);
2160 self.register_region_obligation(origin, ty, r);
2164 fn add_region_obligations_for_region_parameter(&self,
2166 region_bounds: &[ty::Region],
2167 region_param: ty::Region)
2169 for &b in region_bounds.iter() {
2170 // For each bound `region:b`, `b <= region` must hold
2171 // (i.e., `region` must outlive `b`).
2172 let origin = infer::RelateRegionParamBound(span);
2173 self.mk_subr(origin, b, region_param);
2179 pub enum LvaluePreference {
2184 pub fn autoderef<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
2186 expr_id: Option<ast::NodeId>,
2187 mut lvalue_pref: LvaluePreference,
2188 should_stop: |Ty<'tcx>, uint| -> Option<T>)
2189 -> (Ty<'tcx>, uint, Option<T>) {
2191 * Executes an autoderef loop for the type `t`. At each step, invokes
2192 * `should_stop` to decide whether to terminate the loop. Returns
2193 * the final type and number of derefs that it performed.
2195 * Note: this method does not modify the adjustments table. The caller is
2196 * responsible for inserting an AutoAdjustment record into the `fcx`
2197 * using one of the suitable methods.
2200 let mut t = base_ty;
2201 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
2202 let resolved_t = structurally_resolved_type(fcx, sp, t);
2204 if ty::type_is_error(resolved_t) {
2205 return (resolved_t, autoderefs, None);
2208 match should_stop(resolved_t, autoderefs) {
2209 Some(x) => return (resolved_t, autoderefs, Some(x)),
2213 // Otherwise, deref if type is derefable:
2214 let mt = match ty::deref(resolved_t, false) {
2215 Some(mt) => Some(mt),
2217 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
2218 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2224 if mt.mutbl == ast::MutImmutable {
2225 lvalue_pref = NoPreference;
2228 None => return (resolved_t, autoderefs, None)
2232 // We've reached the recursion limit, error gracefully.
2233 span_err!(fcx.tcx().sess, sp, E0055,
2234 "reached the recursion limit while auto-dereferencing {}",
2235 base_ty.repr(fcx.tcx()));
2236 (ty::mk_err(), 0, None)
2239 /// Attempts to resolve a call expression as an overloaded call.
2240 fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2241 call_expression: &ast::Expr,
2243 callee_type: Ty<'tcx>,
2244 args: &[&P<ast::Expr>])
2246 // Bail out if the callee is a bare function or a closure. We check those
2248 match *structure_of(fcx, callee.span, callee_type) {
2249 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
2253 // Try the options that are least restrictive on the caller first.
2254 for &(maybe_function_trait, method_name) in [
2255 (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
2256 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2257 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2259 let function_trait = match maybe_function_trait {
2261 Some(function_trait) => function_trait,
2264 match method::lookup_in_trait(fcx,
2265 call_expression.span,
2272 Some(method_callee) => method_callee,
2274 let method_call = MethodCall::expr(call_expression.id);
2275 let output_type = check_method_argument_types(fcx,
2276 call_expression.span,
2282 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2283 write_call(fcx, call_expression, output_type);
2285 if !fcx.tcx().sess.features.borrow().unboxed_closures {
2286 span_err!(fcx.tcx().sess, call_expression.span, E0056,
2287 "overloaded calls are experimental");
2288 span_help!(fcx.tcx().sess, call_expression.span,
2289 "add `#![feature(unboxed_closures)]` to \
2290 the crate attributes to enable");
2299 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2301 method_call: Option<MethodCall>,
2302 base_expr: Option<&ast::Expr>,
2304 lvalue_pref: LvaluePreference)
2305 -> Option<ty::mt<'tcx>>
2307 // Try DerefMut first, if preferred.
2308 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2309 (PreferMutLvalue, Some(trait_did)) => {
2310 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2311 token::intern("deref_mut"), trait_did,
2317 // Otherwise, fall back to Deref.
2318 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2319 (None, Some(trait_did)) => {
2320 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2321 token::intern("deref"), trait_did,
2324 (method, _) => method
2327 make_overloaded_lvalue_return_type(fcx, method_call, method)
2330 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2331 method_call: Option<MethodCall>,
2332 method: Option<MethodCallee<'tcx>>)
2333 -> Option<ty::mt<'tcx>>
2336 * For the overloaded lvalue expressions (`*x`, `x[3]`), the trait
2337 * returns a type of `&T`, but the actual type we assign to the
2338 * *expression* is `T`. So this function just peels off the return
2339 * type by one layer to yield `T`. It also inserts the
2340 * `method-callee` into the method map.
2345 let ref_ty = ty::ty_fn_ret(method.ty);
2347 Some(method_call) => {
2348 fcx.inh.method_map.borrow_mut().insert(method_call,
2354 ty::FnConverging(ref_ty) => {
2355 ty::deref(ref_ty, true)
2357 ty::FnDiverging => {
2358 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2366 fn autoderef_for_index<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>,
2367 base_expr: &ast::Expr,
2369 lvalue_pref: LvaluePreference,
2370 step: |Ty<'tcx>, ty::AutoDerefRef<'tcx>| -> Option<T>)
2373 // FIXME(#18741) -- this is almost but not quite the same as the
2374 // autoderef that normal method probing does. They could likely be
2377 let (ty, autoderefs, final_mt) =
2378 autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
2379 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2380 step(adj_ty, autoderefref)
2383 if final_mt.is_some() {
2387 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2388 // do a final unsized coercion to yield [T].
2390 ty::ty_vec(element_ty, Some(n)) => {
2391 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2392 let autoderefref = ty::AutoDerefRef {
2393 autoderefs: autoderefs,
2394 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2396 step(adjusted_ty, autoderefref)
2404 fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2405 method_call: MethodCall,
2407 base_expr: &ast::Expr,
2409 start_expr: &Option<P<ast::Expr>>,
2410 end_expr: &Option<P<ast::Expr>>,
2411 mutbl: ast::Mutability)
2412 -> Option<Ty<'tcx>> // return type is result of slice
2415 * Autoderefs `base_expr`, looking for a `Slice` impl. If it
2416 * finds one, installs the relevant method info and returns the
2417 * result type (else None).
2420 let lvalue_pref = match mutbl {
2421 ast::MutMutable => PreferMutLvalue,
2422 ast::MutImmutable => NoPreference
2426 autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| {
2427 try_overloaded_slice_step(fcx, method_call, expr, base_expr,
2428 adjusted_ty, autoderefref, mutbl,
2429 start_expr, end_expr)
2432 // Regardless of whether the lookup succeeds, check the method arguments
2433 // so that we have *some* type for each argument.
2434 let method_ty_or_err = opt_method_ty.unwrap_or(ty::mk_err());
2436 let mut args = vec![];
2437 start_expr.as_ref().map(|x| args.push(x));
2438 end_expr.as_ref().map(|x| args.push(x));
2440 check_method_argument_types(fcx,
2446 DontTupleArguments);
2448 opt_method_ty.map(|method_ty| {
2449 let result_ty = ty::ty_fn_ret(method_ty);
2451 ty::FnConverging(result_ty) => result_ty,
2452 ty::FnDiverging => {
2453 fcx.tcx().sess.span_bug(expr.span,
2454 "slice trait does not define a `!` return")
2460 fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2461 method_call: MethodCall,
2463 base_expr: &ast::Expr,
2464 base_ty: Ty<'tcx>, // autoderef'd type
2465 autoderefref: ty::AutoDerefRef<'tcx>,
2466 mutbl: ast::Mutability,
2467 start_expr: &Option<P<ast::Expr>>,
2468 end_expr: &Option<P<ast::Expr>>)
2469 // result type is type of method being called
2473 * Checks for a `Slice` (or `SliceMut`) impl at the relevant level
2474 * of autoderef. If it finds one, installs method info and returns
2475 * type of method (else None).
2478 let method = if mutbl == ast::MutMutable {
2479 // Try `SliceMut` first, if preferred.
2480 match fcx.tcx().lang_items.slice_mut_trait() {
2481 Some(trait_did) => {
2482 let method_name = match (start_expr, end_expr) {
2483 (&Some(_), &Some(_)) => "slice_or_fail_mut",
2484 (&Some(_), &None) => "slice_from_or_fail_mut",
2485 (&None, &Some(_)) => "slice_to_or_fail_mut",
2486 (&None, &None) => "as_mut_slice_",
2489 method::lookup_in_trait_adjusted(fcx,
2492 token::intern(method_name),
2501 // Otherwise, fall back to `Slice`.
2502 // FIXME(#17293) this will not coerce base_expr, so we miss the Slice
2503 // trait for `&mut [T]`.
2504 match fcx.tcx().lang_items.slice_trait() {
2505 Some(trait_did) => {
2506 let method_name = match (start_expr, end_expr) {
2507 (&Some(_), &Some(_)) => "slice_or_fail",
2508 (&Some(_), &None) => "slice_from_or_fail",
2509 (&None, &Some(_)) => "slice_to_or_fail",
2510 (&None, &None) => "as_slice_",
2513 method::lookup_in_trait_adjusted(fcx,
2516 token::intern(method_name),
2526 // If some lookup succeeded, install method in table
2527 method.map(|method| {
2529 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2534 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2535 method_call: MethodCall,
2537 base_expr: &ast::Expr,
2538 adjusted_ty: Ty<'tcx>,
2539 adjustment: ty::AutoDerefRef<'tcx>,
2540 lvalue_pref: LvaluePreference)
2541 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2544 * To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2545 * `base_expr`, looking for a type which either supports builtin indexing or overloaded
2546 * indexing. This loop implements one step in that search; the autoderef loop is implemented
2547 * by `autoderef_for_index`.
2550 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={})",
2551 expr.repr(fcx.tcx()),
2552 base_expr.repr(fcx.tcx()),
2553 adjusted_ty.repr(fcx.tcx()),
2556 // Try built-in indexing first.
2557 match ty::index(adjusted_ty) {
2559 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2560 return Some((ty::mk_uint(), ty));
2566 let input_ty = fcx.infcx().next_ty_var();
2567 let return_ty = fcx.infcx().next_ty_var();
2569 // Try `IndexMut` first, if preferred.
2570 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2571 (PreferMutLvalue, Some(trait_did)) => {
2572 method::lookup_in_trait_adjusted(fcx,
2575 token::intern("index_mut"),
2579 Some(vec![input_ty, return_ty]))
2584 // Otherwise, fall back to `Index`.
2585 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2586 (None, Some(trait_did)) => {
2587 method::lookup_in_trait_adjusted(fcx,
2590 token::intern("index"),
2594 Some(vec![input_ty, return_ty]))
2596 (method, _) => method,
2599 // If some lookup succeeds, write callee into table and extract index/element
2600 // type from the method signature.
2601 // If some lookup succeeded, install method in table
2602 method.map(|method| {
2603 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method));
2604 (input_ty, return_ty)
2608 /// Given the head of a `for` expression, looks up the `next` method in the
2609 /// `Iterator` trait. Panics if the expression does not implement `next`.
2611 /// The return type of this function represents the concrete element type
2612 /// `A` in the type `Iterator<A>` that the method returns.
2613 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2614 iterator_expr: &ast::Expr,
2615 loop_id: ast::NodeId)
2617 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2618 Ok(trait_did) => trait_did,
2619 Err(ref err_string) => {
2620 fcx.tcx().sess.span_err(iterator_expr.span,
2621 err_string.as_slice());
2626 let expr_type = fcx.expr_ty(&*iterator_expr);
2627 let method = method::lookup_in_trait(fcx,
2629 Some(&*iterator_expr),
2630 token::intern("next"),
2635 // Regardless of whether the lookup succeeds, check the method arguments
2636 // so that we have *some* type for each argument.
2637 let method_type = match method {
2638 Some(ref method) => method.ty,
2640 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
2642 if !ty::type_is_error(true_expr_type) {
2643 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2644 fcx.tcx().sess.span_err(iterator_expr.span,
2645 format!("`for` loop expression has type `{}` which does \
2646 not implement the `Iterator` trait; \
2648 ty_string).as_slice());
2653 let return_type = check_method_argument_types(fcx,
2659 DontTupleArguments);
2663 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2666 // We expect the return type to be `Option` or something like it.
2667 // Grab the first parameter of its type substitution.
2668 let return_type = match return_type {
2669 ty::FnConverging(return_type) =>
2670 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2671 ty::FnDiverging => ty::mk_err()
2673 match return_type.sty {
2674 ty::ty_enum(_, ref substs)
2675 if !substs.types.is_empty_in(subst::TypeSpace) => {
2676 *substs.types.get(subst::TypeSpace, 0)
2682 fcx.tcx().sess.span_err(iterator_expr.span,
2683 format!("`next` method of the `Iterator` \
2684 trait has an unexpected type `{}`",
2685 fcx.infcx().ty_to_string(return_type))
2691 None => ty::mk_err()
2695 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2697 method_fn_ty: Ty<'tcx>,
2698 callee_expr: &ast::Expr,
2699 args_no_rcvr: &[&P<ast::Expr>],
2700 deref_args: DerefArgs,
2701 tuple_arguments: TupleArgumentsFlag)
2702 -> ty::FnOutput<'tcx> {
2703 if ty::type_is_error(method_fn_ty) {
2704 let err_inputs = err_args(args_no_rcvr.len());
2705 check_argument_types(fcx,
2707 err_inputs.as_slice(),
2713 ty::FnConverging(ty::mk_err())
2715 match method_fn_ty.sty {
2716 ty::ty_bare_fn(ref fty) => {
2717 // HACK(eddyb) ignore self in the definition (see above).
2718 check_argument_types(fcx,
2720 fty.sig.inputs.slice_from(1),
2729 fcx.tcx().sess.span_bug(callee_expr.span,
2730 "method without bare fn type");
2736 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2738 fn_inputs: &[Ty<'tcx>],
2739 _callee_expr: &ast::Expr,
2740 args: &[&P<ast::Expr>],
2741 deref_args: DerefArgs,
2743 tuple_arguments: TupleArgumentsFlag) {
2746 * Generic function that factors out common logic from
2747 * function calls, method calls and overloaded operators.
2750 let tcx = fcx.ccx.tcx;
2752 // Grab the argument types, supplying fresh type variables
2753 // if the wrong number of arguments were supplied
2754 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2760 let expected_arg_count = fn_inputs.len();
2761 let formal_tys = if tuple_arguments == TupleArguments {
2762 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2763 match tuple_type.sty {
2764 ty::ty_tup(ref arg_types) => {
2765 if arg_types.len() != args.len() {
2766 span_err!(tcx.sess, sp, E0057,
2767 "this function takes {} parameter{} but {} parameter{} supplied",
2769 if arg_types.len() == 1 {""} else {"s"},
2771 if args.len() == 1 {" was"} else {"s were"});
2772 err_args(args.len())
2774 (*arg_types).clone()
2778 span_err!(tcx.sess, sp, E0059,
2779 "cannot use call notation; the first type parameter \
2780 for the function trait is neither a tuple nor unit");
2781 err_args(args.len())
2784 } else if expected_arg_count == supplied_arg_count {
2785 fn_inputs.iter().map(|a| *a).collect()
2786 } else if variadic {
2787 if supplied_arg_count >= expected_arg_count {
2788 fn_inputs.iter().map(|a| *a).collect()
2790 span_err!(tcx.sess, sp, E0060,
2791 "this function takes at least {} parameter{} \
2792 but {} parameter{} supplied",
2794 if expected_arg_count == 1 {""} else {"s"},
2796 if supplied_arg_count == 1 {" was"} else {"s were"});
2797 err_args(supplied_arg_count)
2800 span_err!(tcx.sess, sp, E0061,
2801 "this function takes {} parameter{} but {} parameter{} supplied",
2803 if expected_arg_count == 1 {""} else {"s"},
2805 if supplied_arg_count == 1 {" was"} else {"s were"});
2806 err_args(supplied_arg_count)
2809 debug!("check_argument_types: formal_tys={}",
2810 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2812 // Check the arguments.
2813 // We do this in a pretty awful way: first we typecheck any arguments
2814 // that are not anonymous functions, then we typecheck the anonymous
2815 // functions. This is so that we have more information about the types
2816 // of arguments when we typecheck the functions. This isn't really the
2817 // right way to do this.
2818 let xs = [false, true];
2819 for check_blocks in xs.iter() {
2820 let check_blocks = *check_blocks;
2821 debug!("check_blocks={}", check_blocks);
2823 // More awful hacks: before we check the blocks, try to do
2824 // an "opportunistic" vtable resolution of any trait
2825 // bounds on the call.
2827 vtable::select_new_fcx_obligations(fcx);
2830 // For variadic functions, we don't have a declared type for all of
2831 // the arguments hence we only do our usual type checking with
2832 // the arguments who's types we do know.
2833 let t = if variadic {
2835 } else if tuple_arguments == TupleArguments {
2840 for (i, arg) in args.iter().take(t).enumerate() {
2841 let is_block = match arg.node {
2842 ast::ExprClosure(..) | ast::ExprProc(..) => true,
2846 if is_block == check_blocks {
2847 debug!("checking the argument");
2848 let mut formal_ty = formal_tys[i];
2852 match formal_ty.sty {
2853 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2856 // So we hit this case when one implements the
2857 // operator traits but leaves an argument as
2858 // just T instead of &T. We'll catch it in the
2859 // mismatch impl/trait method phase no need to
2862 formal_ty = ty::mk_err();
2869 check_expr_coercable_to_type(fcx, &***arg, formal_ty);
2874 // We also need to make sure we at least write the ty of the other
2875 // arguments which we skipped above.
2877 for arg in args.iter().skip(expected_arg_count) {
2878 check_expr(fcx, &***arg);
2880 // There are a few types which get autopromoted when passed via varargs
2881 // in C but we just error out instead and require explicit casts.
2882 let arg_ty = structurally_resolved_type(fcx, arg.span,
2883 fcx.expr_ty(&***arg));
2885 ty::ty_float(ast::TyF32) => {
2886 fcx.type_error_message(arg.span,
2888 format!("can't pass an {} to variadic \
2889 function, cast to c_double", t)
2892 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2893 fcx.type_error_message(arg.span, |t| {
2894 format!("can't pass {} to variadic \
2895 function, cast to c_int",
2899 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2900 fcx.type_error_message(arg.span, |t| {
2901 format!("can't pass {} to variadic \
2902 function, cast to c_uint",
2912 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2913 fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
2914 Vec::from_fn(len, |_| ty::mk_err())
2917 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2918 call_expr: &ast::Expr,
2919 output: ty::FnOutput<'tcx>) {
2920 fcx.write_ty(call_expr.id, match output {
2921 ty::FnConverging(output_ty) => output_ty,
2922 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2926 // AST fragment checking
2927 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2929 expected: Expectation<'tcx>)
2932 let tcx = fcx.ccx.tcx;
2935 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2936 ast::LitBinary(..) => {
2937 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2939 ast::LitByte(_) => ty::mk_u8(),
2940 ast::LitChar(_) => ty::mk_char(),
2941 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2942 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2943 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2944 let opt_ty = expected.map_to_option(fcx, |sty| {
2946 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2947 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2948 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2949 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2950 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2954 opt_ty.unwrap_or_else(
2955 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2957 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2958 ast::LitFloatUnsuffixed(_) => {
2959 let opt_ty = expected.map_to_option(fcx, |sty| {
2961 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2965 opt_ty.unwrap_or_else(
2966 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2968 ast::LitBool(_) => ty::mk_bool()
2972 pub fn valid_range_bounds(ccx: &CrateCtxt,
2976 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2977 Some(val) => Some(val <= 0),
2982 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2984 expected: Ty<'tcx>) {
2985 check_expr_with_unifier(
2986 fcx, expr, ExpectHasType(expected), NoPreference,
2987 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2990 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2992 expected: Ty<'tcx>) {
2993 check_expr_with_unifier(
2994 fcx, expr, ExpectHasType(expected), NoPreference,
2995 || demand::coerce(fcx, expr.span, expected, expr));
2998 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2999 expected: Ty<'tcx>) {
3000 check_expr_with_unifier(
3001 fcx, expr, ExpectHasType(expected), NoPreference,
3005 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3007 expected: Expectation<'tcx>) {
3008 check_expr_with_unifier(
3009 fcx, expr, expected, NoPreference,
3013 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3015 expected: Expectation<'tcx>,
3016 lvalue_pref: LvaluePreference)
3018 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
3021 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
3022 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
3025 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
3026 lvalue_pref: LvaluePreference) {
3027 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
3030 // determine the `self` type, using fresh variables for all variables
3031 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
3032 // would return ($0, $1) where $0 and $1 are freshly instantiated type
3034 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3035 span: Span, // (potential) receiver for this impl
3037 -> TypeAndSubsts<'tcx> {
3038 let tcx = fcx.tcx();
3040 let ity = ty::lookup_item_type(tcx, did);
3041 let (n_tps, rps, raw_ty) =
3042 (ity.generics.types.len(subst::TypeSpace),
3043 ity.generics.regions.get_slice(subst::TypeSpace),
3046 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
3047 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
3048 let substs = subst::Substs::new_type(tps, rps);
3049 let substd_ty = raw_ty.subst(tcx, &substs);
3051 TypeAndSubsts { substs: substs, ty: substd_ty }
3054 // Only for fields! Returns <none> for methods>
3055 // Indifferent to privacy flags
3056 pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
3057 class_id: ast::DefId,
3058 items: &[ty::field_ty],
3059 fieldname: ast::Name,
3060 substs: &subst::Substs<'tcx>)
3061 -> Option<Ty<'tcx>> {
3063 let o_field = items.iter().find(|f| f.name == fieldname);
3064 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
3067 pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
3068 class_id: ast::DefId,
3069 items: &[ty::field_ty],
3071 substs: &subst::Substs<'tcx>)
3072 -> Option<Ty<'tcx>> {
3074 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
3075 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
3078 // Controls whether the arguments are automatically referenced. This is useful
3079 // for overloaded binary and unary operators.
3080 pub enum DerefArgs {
3085 /// Controls whether the arguments are tupled. This is used for the call
3088 /// Tupling means that all call-side arguments are packed into a tuple and
3089 /// passed as a single parameter. For example, if tupling is enabled, this
3092 /// fn f(x: (int, int))
3094 /// Can be called as:
3101 #[deriving(Clone, Eq, PartialEq)]
3102 enum TupleArgumentsFlag {
3108 /// If an expression has any sub-expressions that result in a type error,
3109 /// inspecting that expression's type with `ty::type_is_error` will return
3110 /// true. Likewise, if an expression is known to diverge, inspecting its
3111 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
3112 /// strict, _|_ can appear in the type of an expression that does not,
3113 /// itself, diverge: for example, fn() -> _|_.)
3114 /// Note that inspecting a type's structure *directly* may expose the fact
3115 /// that there are actually multiple representations for `ty_err`, so avoid
3116 /// that when err needs to be handled differently.
3117 fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3119 expected: Expectation<'tcx>,
3120 lvalue_pref: LvaluePreference,
3123 debug!(">> typechecking: expr={} expected={}",
3124 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
3126 // A generic function for doing all of the checking for call expressions
3127 fn check_call(fcx: &FnCtxt,
3128 call_expr: &ast::Expr,
3130 args: &[&P<ast::Expr>]) {
3131 // Store the type of `f` as the type of the callee
3132 let fn_ty = fcx.expr_ty(f);
3134 // Extract the function signature from `in_fty`.
3135 let fn_sty = structure_of(fcx, f.span, fn_ty);
3137 // This is the "default" function signature, used in case of error.
3138 // In that case, we check each argument against "error" in order to
3139 // set up all the node type bindings.
3140 let error_fn_sig = FnSig {
3141 inputs: err_args(args.len()),
3142 output: ty::FnConverging(ty::mk_err()),
3146 let fn_sig = match *fn_sty {
3147 ty::ty_bare_fn(ty::BareFnTy {ref sig, ..}) |
3148 ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
3150 fcx.type_error_message(call_expr.span, |actual| {
3151 format!("expected function, found `{}`", actual)
3157 // Replace any bound regions that appear in the function
3158 // signature with region variables
3160 fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
3164 // Call the generic checker.
3165 check_argument_types(fcx,
3167 fn_sig.inputs.as_slice(),
3172 DontTupleArguments);
3174 write_call(fcx, call_expr, fn_sig.output);
3177 // Checks a method call.
3178 fn check_method_call(fcx: &FnCtxt,
3180 method_name: ast::SpannedIdent,
3181 args: &[P<ast::Expr>],
3183 lvalue_pref: LvaluePreference) {
3184 let rcvr = &*args[0];
3185 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
3187 // no need to check for bot/err -- callee does that
3188 let expr_t = structurally_resolved_type(fcx,
3190 fcx.expr_ty(&*rcvr));
3192 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
3193 let fn_ty = match method::lookup(fcx,
3195 method_name.node.name,
3201 let method_ty = method.ty;
3202 let method_call = MethodCall::expr(expr.id);
3203 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3207 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
3208 fcx.write_error(expr.id);
3213 // Call the generic checker.
3214 let args: Vec<_> = args[1..].iter().map(|x| x).collect();
3215 let ret_ty = check_method_argument_types(fcx,
3221 DontTupleArguments);
3223 write_call(fcx, expr, ret_ty);
3226 // A generic function for checking the then and else in an if
3228 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3229 cond_expr: &ast::Expr,
3230 then_blk: &ast::Block,
3231 opt_else_expr: Option<&ast::Expr>,
3234 expected: Expectation<'tcx>) {
3235 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
3237 // Disregard "castable to" expectations because they
3238 // can lead us astray. Consider for example `if cond
3239 // {22} else {c} as u8` -- if we propagate the
3240 // "castable to u8" constraint to 22, it will pick the
3241 // type 22u8, which is overly constrained (c might not
3242 // be a u8). In effect, the problem is that the
3243 // "castable to" expectation is not the tightest thing
3244 // we can say, so we want to drop it in this case.
3245 // The tightest thing we can say is "must unify with
3246 // else branch". Note that in the case of a "has type"
3247 // constraint, this limitation does not hold.
3249 // If the expected type is just a type variable, then don't use
3250 // an expected type. Otherwise, we might write parts of the type
3251 // when checking the 'then' block which are incompatible with the
3253 let expected = match expected.only_has_type() {
3254 ExpectHasType(ety) => {
3255 let ety = fcx.infcx().shallow_resolve(ety);
3256 if !ty::type_is_ty_var(ety) {
3264 check_block_with_expected(fcx, then_blk, expected);
3265 let then_ty = fcx.node_ty(then_blk.id);
3267 let branches_ty = match opt_else_expr {
3268 Some(ref else_expr) => {
3269 check_expr_with_expectation(fcx, &**else_expr, expected);
3270 let else_ty = fcx.expr_ty(&**else_expr);
3271 infer::common_supertype(fcx.infcx(),
3272 infer::IfExpression(sp),
3278 infer::common_supertype(fcx.infcx(),
3279 infer::IfExpressionWithNoElse(sp),
3282 ty::mk_nil(fcx.tcx()))
3286 let cond_ty = fcx.expr_ty(cond_expr);
3287 let if_ty = if ty::type_is_error(cond_ty) {
3293 fcx.write_ty(id, if_ty);
3296 fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
3300 trait_did: Option<ast::DefId>,
3302 rhs: Option<&P<ast::Expr>>,
3303 unbound_method: ||) -> Ty<'tcx> {
3304 let method = match trait_did {
3305 Some(trait_did) => {
3306 // We do eager coercions to make using operators
3309 // - If the input is of type &'a T (resp. &'a mut T),
3310 // then reborrow it to &'b T (resp. &'b mut T) where
3311 // 'b <= 'a. This makes things like `x == y`, where
3312 // `x` and `y` are both region pointers, work. We
3313 // could also solve this with variance or different
3314 // traits that don't force left and right to have same
3316 let (adj_ty, adjustment) = match lhs_ty.sty {
3317 ty::ty_rptr(r_in, mt) => {
3318 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
3319 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, r_in);
3320 let adjusted_ty = ty::mk_rptr(fcx.tcx(), r_adj, mt);
3321 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
3322 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
3323 (adjusted_ty, adjustment)
3326 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
3330 debug!("adjusted_ty={} adjustment={}",
3331 adj_ty.repr(fcx.tcx()),
3334 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
3335 trait_did, adjustment, adj_ty, None)
3339 let args = match rhs {
3340 Some(rhs) => vec![rhs],
3345 let method_ty = method.ty;
3346 // HACK(eddyb) Fully qualified path to work around a resolve bug.
3347 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
3348 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3349 match check_method_argument_types(fcx,
3355 DontTupleArguments) {
3356 ty::FnConverging(result_type) => result_type,
3357 ty::FnDiverging => ty::mk_err()
3362 // Check the args anyway
3363 // so we get all the error messages
3364 let expected_ty = ty::mk_err();
3365 check_method_argument_types(fcx,
3371 DontTupleArguments);
3377 // could be either an expr_binop or an expr_assign_binop
3378 fn check_binop(fcx: &FnCtxt,
3383 is_binop_assignment: IsBinopAssignment) {
3384 let tcx = fcx.ccx.tcx;
3386 let lvalue_pref = match is_binop_assignment {
3387 BinopAssignment => PreferMutLvalue,
3388 SimpleBinop => NoPreference
3390 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
3392 // Callee does bot / err checking
3393 let lhs_t = structurally_resolved_type(fcx, lhs.span,
3394 fcx.expr_ty(&*lhs));
3396 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
3397 // Shift is a special case: rhs must be uint, no matter what lhs is
3398 check_expr_has_type(fcx, &**rhs, ty::mk_uint());
3399 fcx.write_ty(expr.id, lhs_t);
3403 if ty::is_binopable(tcx, lhs_t, op) {
3404 let tvar = fcx.infcx().next_ty_var();
3405 demand::suptype(fcx, expr.span, tvar, lhs_t);
3406 check_expr_has_type(fcx, &**rhs, tvar);
3408 let result_t = match op {
3409 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
3411 if ty::type_is_simd(tcx, lhs_t) {
3412 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
3413 fcx.type_error_message(expr.span,
3415 format!("binary comparison \
3416 operation `{}` not \
3417 supported for floating \
3418 point SIMD vector `{}`",
3419 ast_util::binop_to_string(op),
3436 fcx.write_ty(expr.id, result_t);
3440 if op == ast::BiOr || op == ast::BiAnd {
3441 // This is an error; one of the operands must have the wrong
3443 fcx.write_error(expr.id);
3444 fcx.write_error(rhs.id);
3445 fcx.type_error_message(expr.span,
3447 format!("binary operation `{}` cannot be applied \
3449 ast_util::binop_to_string(op),
3456 // Check for overloaded operators if not an assignment.
3457 let result_t = if is_binop_assignment == SimpleBinop {
3458 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3460 fcx.type_error_message(expr.span,
3462 format!("binary assignment \
3464 cannot be applied to \
3466 ast_util::binop_to_string(op),
3471 check_expr(fcx, &**rhs);
3475 fcx.write_ty(expr.id, result_t);
3476 if ty::type_is_error(result_t) {
3477 fcx.write_ty(rhs.id, result_t);
3481 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3483 lhs_expr: &ast::Expr,
3484 lhs_resolved_t: Ty<'tcx>,
3486 rhs: &P<ast::Expr>) -> Ty<'tcx> {
3487 let tcx = fcx.ccx.tcx;
3488 let lang = &tcx.lang_items;
3489 let (name, trait_did) = match op {
3490 ast::BiAdd => ("add", lang.add_trait()),
3491 ast::BiSub => ("sub", lang.sub_trait()),
3492 ast::BiMul => ("mul", lang.mul_trait()),
3493 ast::BiDiv => ("div", lang.div_trait()),
3494 ast::BiRem => ("rem", lang.rem_trait()),
3495 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3496 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3497 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3498 ast::BiShl => ("shl", lang.shl_trait()),
3499 ast::BiShr => ("shr", lang.shr_trait()),
3500 ast::BiLt => ("lt", lang.ord_trait()),
3501 ast::BiLe => ("le", lang.ord_trait()),
3502 ast::BiGe => ("ge", lang.ord_trait()),
3503 ast::BiGt => ("gt", lang.ord_trait()),
3504 ast::BiEq => ("eq", lang.eq_trait()),
3505 ast::BiNe => ("ne", lang.eq_trait()),
3506 ast::BiAnd | ast::BiOr => {
3507 check_expr(fcx, &**rhs);
3508 return ty::mk_err();
3511 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3512 trait_did, lhs_expr, Some(rhs), || {
3513 fcx.type_error_message(ex.span, |actual| {
3514 format!("binary operation `{}` cannot be applied to type `{}`",
3515 ast_util::binop_to_string(op),
3517 }, lhs_resolved_t, None)
3521 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3524 trait_did: Option<ast::DefId>,
3526 rhs_expr: &ast::Expr,
3527 rhs_t: Ty<'tcx>) -> Ty<'tcx> {
3528 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3529 trait_did, rhs_expr, None, || {
3530 fcx.type_error_message(ex.span, |actual| {
3531 format!("cannot apply unary operator `{}` to type `{}`",
3537 // Check field access expressions
3538 fn check_field(fcx: &FnCtxt,
3540 lvalue_pref: LvaluePreference,
3542 field: &ast::SpannedIdent) {
3543 let tcx = fcx.ccx.tcx;
3544 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3545 let expr_t = structurally_resolved_type(fcx, expr.span,
3547 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3548 let (_, autoderefs, field_ty) =
3549 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3551 ty::ty_struct(base_id, ref substs) => {
3552 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3553 let fields = ty::lookup_struct_fields(tcx, base_id);
3554 lookup_field_ty(tcx, base_id, fields.as_slice(),
3555 field.node.name, &(*substs))
3562 fcx.write_ty(expr.id, field_ty);
3563 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3569 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3570 fcx.type_error_message(
3573 format!("attempted to take value of method `{}` on type \
3574 `{}`", token::get_ident(field.node), actual)
3578 tcx.sess.span_help(field.span,
3579 "maybe a `()` to call it is missing? \
3580 If not, try an anonymous function");
3582 fcx.type_error_message(
3585 format!("attempted access of field `{}` on \
3586 type `{}`, but no field with that \
3588 token::get_ident(field.node),
3594 fcx.write_error(expr.id);
3597 // Check tuple index expressions
3598 fn check_tup_field(fcx: &FnCtxt,
3600 lvalue_pref: LvaluePreference,
3602 idx: codemap::Spanned<uint>) {
3603 let tcx = fcx.ccx.tcx;
3604 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3605 let expr_t = structurally_resolved_type(fcx, expr.span,
3607 let mut tuple_like = false;
3608 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3609 let (_, autoderefs, field_ty) =
3610 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3612 ty::ty_struct(base_id, ref substs) => {
3613 tuple_like = ty::is_tuple_struct(tcx, base_id);
3615 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3616 let fields = ty::lookup_struct_fields(tcx, base_id);
3617 lookup_tup_field_ty(tcx, base_id, fields.as_slice(),
3618 idx.node, &(*substs))
3623 ty::ty_tup(ref v) => {
3625 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3632 fcx.write_ty(expr.id, field_ty);
3633 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3638 fcx.type_error_message(
3642 format!("attempted out-of-bounds tuple index `{}` on \
3647 format!("attempted tuple index `{}` on type `{}`, but the \
3648 type was not a tuple or tuple struct",
3655 fcx.write_error(expr.id);
3658 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3659 struct_ty: Ty<'tcx>,
3661 class_id: ast::DefId,
3662 node_id: ast::NodeId,
3663 substitutions: subst::Substs<'tcx>,
3664 field_types: &[ty::field_ty],
3665 ast_fields: &[ast::Field],
3666 check_completeness: bool) {
3667 let tcx = fcx.ccx.tcx;
3669 let mut class_field_map = FnvHashMap::new();
3670 let mut fields_found = 0;
3671 for field in field_types.iter() {
3672 class_field_map.insert(field.name, (field.id, false));
3675 let mut error_happened = false;
3677 // Typecheck each field.
3678 for field in ast_fields.iter() {
3679 let mut expected_field_type = ty::mk_err();
3681 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3684 fcx.type_error_message(
3687 format!("structure `{}` has no field named `{}`",
3688 actual, token::get_ident(field.ident.node))
3692 error_happened = true;
3694 Some((_, true)) => {
3695 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3696 "field `{}` specified more than once",
3697 token::get_ident(field.ident.node));
3698 error_happened = true;
3700 Some((field_id, false)) => {
3701 expected_field_type =
3702 ty::lookup_field_type(
3703 tcx, class_id, field_id, &substitutions);
3704 class_field_map.insert(
3705 field.ident.node.name, (field_id, true));
3709 // Make sure to give a type to the field even if there's
3710 // an error, so we can continue typechecking
3711 check_expr_coercable_to_type(
3714 expected_field_type);
3718 fcx.write_error(node_id);
3721 if check_completeness && !error_happened {
3722 // Make sure the programmer specified all the fields.
3723 assert!(fields_found <= field_types.len());
3724 if fields_found < field_types.len() {
3725 let mut missing_fields = Vec::new();
3726 for class_field in field_types.iter() {
3727 let name = class_field.name;
3728 let (_, seen) = class_field_map[name];
3730 missing_fields.push(
3731 format!("`{}`", token::get_name(name).get()))
3735 span_err!(tcx.sess, span, E0063,
3736 "missing field{}: {}",
3737 if missing_fields.len() == 1 {""} else {"s"},
3738 missing_fields.connect(", "));
3742 if !error_happened {
3743 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3744 class_id, substitutions));
3748 fn check_struct_constructor(fcx: &FnCtxt,
3750 span: codemap::Span,
3751 class_id: ast::DefId,
3752 fields: &[ast::Field],
3753 base_expr: Option<&ast::Expr>) {
3754 let tcx = fcx.ccx.tcx;
3756 // Generate the struct type.
3758 ty: mut struct_type,
3759 substs: struct_substs
3760 } = fcx.instantiate_type(span, class_id);
3762 // Look up and check the fields.
3763 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3764 check_struct_or_variant_fields(fcx,
3770 class_fields.as_slice(),
3772 base_expr.is_none());
3773 if ty::type_is_error(fcx.node_ty(id)) {
3774 struct_type = ty::mk_err();
3777 // Check the base expression if necessary.
3780 Some(base_expr) => {
3781 check_expr_has_type(fcx, &*base_expr, struct_type);
3785 // Write in the resulting type.
3786 fcx.write_ty(id, struct_type);
3789 fn check_struct_enum_variant(fcx: &FnCtxt,
3791 span: codemap::Span,
3792 enum_id: ast::DefId,
3793 variant_id: ast::DefId,
3794 fields: &[ast::Field]) {
3795 let tcx = fcx.ccx.tcx;
3797 // Look up the number of type parameters and the raw type, and
3798 // determine whether the enum is region-parameterized.
3801 substs: substitutions
3802 } = fcx.instantiate_type(span, enum_id);
3804 // Look up and check the enum variant fields.
3805 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3806 check_struct_or_variant_fields(fcx,
3812 variant_fields.as_slice(),
3815 fcx.write_ty(id, enum_type);
3818 fn check_struct_fields_on_error(fcx: &FnCtxt,
3820 fields: &[ast::Field],
3821 base_expr: &Option<P<ast::Expr>>) {
3822 // Make sure to still write the types
3823 // otherwise we might ICE
3824 fcx.write_error(id);
3825 for field in fields.iter() {
3826 check_expr(fcx, &*field.expr);
3829 Some(ref base) => check_expr(fcx, &**base),
3834 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3836 let tcx = fcx.ccx.tcx;
3839 ast::ExprBox(ref place, ref subexpr) => {
3840 check_expr(fcx, &**place);
3841 check_expr(fcx, &**subexpr);
3843 let mut checked = false;
3845 ast::ExprPath(ref path) => {
3846 // FIXME(pcwalton): For now we hardcode the two permissible
3847 // places: the exchange heap and the managed heap.
3848 let definition = lookup_def(fcx, path.span, place.id);
3849 let def_id = definition.def_id();
3850 let referent_ty = fcx.expr_ty(&**subexpr);
3851 if tcx.lang_items.exchange_heap() == Some(def_id) {
3852 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3860 span_err!(tcx.sess, expr.span, E0066,
3861 "only the managed heap and exchange heap are currently supported");
3862 fcx.write_ty(id, ty::mk_err());
3866 ast::ExprLit(ref lit) => {
3867 let typ = check_lit(fcx, &**lit, expected);
3868 fcx.write_ty(id, typ);
3870 ast::ExprBinary(op, ref lhs, ref rhs) => {
3871 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3873 let lhs_ty = fcx.expr_ty(&**lhs);
3874 let rhs_ty = fcx.expr_ty(&**rhs);
3875 if ty::type_is_error(lhs_ty) ||
3876 ty::type_is_error(rhs_ty) {
3877 fcx.write_error(id);
3880 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3881 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3883 let lhs_t = fcx.expr_ty(&**lhs);
3884 let result_t = fcx.expr_ty(expr);
3885 demand::suptype(fcx, expr.span, result_t, lhs_t);
3887 let tcx = fcx.tcx();
3888 if !ty::expr_is_lval(tcx, &**lhs) {
3889 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3892 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3894 // Overwrite result of check_binop...this preserves existing behavior
3895 // but seems quite dubious with regard to user-defined methods
3896 // and so forth. - Niko
3897 if !ty::type_is_error(result_t) {
3898 fcx.write_nil(expr.id);
3901 ast::ExprUnary(unop, ref oprnd) => {
3902 let expected_inner = expected.map(fcx, |sty| {
3904 ast::UnUniq => match *sty {
3905 ty::ty_uniq(ty) => {
3912 ast::UnNot | ast::UnNeg => {
3920 let lvalue_pref = match unop {
3921 ast::UnDeref => lvalue_pref,
3924 check_expr_with_expectation_and_lvalue_pref(
3925 fcx, &**oprnd, expected_inner, lvalue_pref);
3926 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3928 if !ty::type_is_error(oprnd_t) {
3931 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3934 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3935 oprnd_t = match ty::deref(oprnd_t, true) {
3937 None => match try_overloaded_deref(fcx, expr.span,
3938 Some(MethodCall::expr(expr.id)),
3939 Some(&**oprnd), oprnd_t, lvalue_pref) {
3942 let is_newtype = match oprnd_t.sty {
3943 ty::ty_struct(did, ref substs) => {
3944 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3946 && fields[0].name ==
3947 token::special_idents::unnamed_field.name
3952 // This is an obsolete struct deref
3953 span_err!(tcx.sess, expr.span, E0068,
3954 "single-field tuple-structs can \
3955 no longer be dereferenced");
3957 fcx.type_error_message(expr.span, |actual| {
3958 format!("type `{}` cannot be \
3959 dereferenced", actual)
3968 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3970 if !(ty::type_is_integral(oprnd_t) ||
3971 oprnd_t.sty == ty::ty_bool) {
3972 oprnd_t = check_user_unop(fcx, "!", "not",
3973 tcx.lang_items.not_trait(),
3974 expr, &**oprnd, oprnd_t);
3978 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3980 if !(ty::type_is_integral(oprnd_t) ||
3981 ty::type_is_fp(oprnd_t)) {
3982 oprnd_t = check_user_unop(fcx, "-", "neg",
3983 tcx.lang_items.neg_trait(),
3984 expr, &**oprnd, oprnd_t);
3989 fcx.write_ty(id, oprnd_t);
3991 ast::ExprAddrOf(mutbl, ref oprnd) => {
3992 let expected = expected.only_has_type();
3993 let hint = expected.map(fcx, |sty| {
3994 match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3995 _ => NoExpectation }
3997 let lvalue_pref = match mutbl {
3998 ast::MutMutable => PreferMutLvalue,
3999 ast::MutImmutable => NoPreference
4001 check_expr_with_expectation_and_lvalue_pref(fcx,
4006 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
4007 let oprnd_t = if ty::type_is_error(tm.ty) {
4010 // Note: at this point, we cannot say what the best lifetime
4011 // is to use for resulting pointer. We want to use the
4012 // shortest lifetime possible so as to avoid spurious borrowck
4013 // errors. Moreover, the longest lifetime will depend on the
4014 // precise details of the value whose address is being taken
4015 // (and how long it is valid), which we don't know yet until type
4016 // inference is complete.
4018 // Therefore, here we simply generate a region variable. The
4019 // region inferencer will then select the ultimate value.
4020 // Finally, borrowck is charged with guaranteeing that the
4021 // value whose address was taken can actually be made to live
4022 // as long as it needs to live.
4024 // String literals are already, implicitly converted to slices.
4025 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
4026 // Empty slices live in static memory.
4027 ast::ExprVec(ref elements) if elements.len() == 0 => {
4028 // Note: we do not assign a lifetime of
4029 // static. This is because the resulting type
4030 // `&'static [T]` would require that T outlives
4032 let region = fcx.infcx().next_region_var(
4033 infer::AddrOfSlice(expr.span));
4034 ty::mk_rptr(tcx, region, tm)
4037 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
4038 ty::mk_rptr(tcx, region, tm)
4042 fcx.write_ty(id, oprnd_t);
4044 ast::ExprPath(ref pth) => {
4045 let defn = lookup_def(fcx, pth.span, id);
4046 let pty = polytype_for_def(fcx, expr.span, defn);
4047 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
4049 // We always require that the type provided as the value for
4050 // a type parameter outlives the moment of instantiation.
4051 constrain_path_type_parameters(fcx, expr);
4053 ast::ExprInlineAsm(ref ia) => {
4054 for &(_, ref input) in ia.inputs.iter() {
4055 check_expr(fcx, &**input);
4057 for &(_, ref out, _) in ia.outputs.iter() {
4058 check_expr(fcx, &**out);
4062 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
4063 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
4064 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
4065 ast::ExprRet(ref expr_opt) => {
4067 ty::FnConverging(result_type) => {
4070 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
4071 result_type, ty::mk_nil(fcx.tcx())) {
4072 span_err!(tcx.sess, expr.span, E0069,
4073 "`return;` in function returning non-nil");
4076 check_expr_coercable_to_type(fcx, &**e, result_type);
4080 ty::FnDiverging => {
4081 if let Some(ref e) = *expr_opt {
4082 check_expr(fcx, &**e);
4084 span_err!(tcx.sess, expr.span, E0166,
4085 "`return` in a function declared as diverging");
4088 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4090 ast::ExprParen(ref a) => {
4091 check_expr_with_expectation_and_lvalue_pref(fcx,
4095 fcx.write_ty(id, fcx.expr_ty(&**a));
4097 ast::ExprAssign(ref lhs, ref rhs) => {
4098 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4100 let tcx = fcx.tcx();
4101 if !ty::expr_is_lval(tcx, &**lhs) {
4102 span_err!(tcx.sess, expr.span, E0070,
4103 "illegal left-hand side expression");
4106 let lhs_ty = fcx.expr_ty(&**lhs);
4107 check_expr_has_type(fcx, &**rhs, lhs_ty);
4108 let rhs_ty = fcx.expr_ty(&**rhs);
4110 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4112 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4113 fcx.write_error(id);
4118 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4119 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4120 id, expr.span, expected);
4122 ast::ExprIfLet(..) => {
4123 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
4125 ast::ExprWhile(ref cond, ref body, _) => {
4126 check_expr_has_type(fcx, &**cond, ty::mk_bool());
4127 check_block_no_value(fcx, &**body);
4128 let cond_ty = fcx.expr_ty(&**cond);
4129 let body_ty = fcx.node_ty(body.id);
4130 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4131 fcx.write_error(id);
4137 ast::ExprWhileLet(..) => {
4138 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
4140 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4141 check_expr(fcx, &**head);
4142 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4143 vtable::select_new_fcx_obligations(fcx);
4145 let pcx = pat_ctxt {
4147 map: pat_id_map(&tcx.def_map, &**pat),
4149 _match::check_pat(&pcx, &**pat, typ);
4151 check_block_no_value(fcx, &**block);
4154 ast::ExprLoop(ref body, _) => {
4155 check_block_no_value(fcx, &**body);
4156 if !may_break(tcx, expr.id, &**body) {
4157 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4162 ast::ExprMatch(ref discrim, ref arms, _) => {
4163 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
4165 ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
4166 closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
4168 ast::ExprProc(ref decl, ref body) => {
4169 closure::check_boxed_closure(fcx,
4176 ast::ExprBlock(ref b) => {
4177 check_block_with_expected(fcx, &**b, expected);
4178 fcx.write_ty(id, fcx.node_ty(b.id));
4180 ast::ExprCall(ref f, ref args) => {
4181 // Index expressions need to be handled separately, to inform them
4182 // that they appear in call position.
4183 check_expr(fcx, &**f);
4184 let f_ty = fcx.expr_ty(&**f);
4186 let args: Vec<_> = args.iter().map(|x| x).collect();
4187 if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
4188 check_call(fcx, expr, &**f, args.as_slice());
4189 let args_err = args.iter().fold(false,
4191 // is this not working?
4192 let a_ty = fcx.expr_ty(&***a);
4193 rest_err || ty::type_is_error(a_ty)});
4194 if ty::type_is_error(f_ty) || args_err {
4195 fcx.write_error(id);
4199 ast::ExprMethodCall(ident, ref tps, ref args) => {
4200 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref);
4201 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4202 let args_err = arg_tys.fold(false,
4204 rest_err || ty::type_is_error(a)});
4206 fcx.write_error(id);
4209 ast::ExprCast(ref e, ref t) => {
4211 ast::TyFixedLengthVec(_, ref count_expr) => {
4212 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
4216 check_cast(fcx, expr, &**e, &**t);
4218 ast::ExprVec(ref args) => {
4219 let uty = match expected {
4220 ExpectHasType(uty) => {
4222 ty::ty_vec(ty, _) => Some(ty),
4229 let typ = match uty {
4231 for e in args.iter() {
4232 check_expr_coercable_to_type(fcx, &**e, uty);
4237 let t: Ty = fcx.infcx().next_ty_var();
4238 for e in args.iter() {
4239 check_expr_has_type(fcx, &**e, t);
4244 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4245 fcx.write_ty(id, typ);
4247 ast::ExprRepeat(ref element, ref count_expr) => {
4248 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
4249 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4251 let uty = match expected {
4252 ExpectHasType(uty) => {
4254 ty::ty_vec(ty, _) => Some(ty),
4261 let (element_ty, t) = match uty {
4263 check_expr_coercable_to_type(fcx, &**element, uty);
4267 let t: Ty = fcx.infcx().next_ty_var();
4268 check_expr_has_type(fcx, &**element, t);
4269 (fcx.expr_ty(&**element), t)
4274 // For [foo, ..n] where n > 1, `foo` must have
4276 fcx.require_type_meets(
4283 if ty::type_is_error(element_ty) {
4284 fcx.write_error(id);
4286 let t = ty::mk_vec(tcx, t, Some(count));
4287 fcx.write_ty(id, t);
4290 ast::ExprTup(ref elts) => {
4291 let expected = expected.only_has_type();
4292 let flds = expected.map_to_option(fcx, |sty| {
4294 ty::ty_tup(ref flds) => Some((*flds).clone()),
4298 let mut err_field = false;
4300 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4301 let t = match flds {
4302 Some(ref fs) if i < fs.len() => {
4304 check_expr_coercable_to_type(fcx, &**e, ety);
4308 check_expr_with_expectation(fcx, &**e, NoExpectation);
4312 err_field = err_field || ty::type_is_error(t);
4316 fcx.write_error(id);
4318 let typ = ty::mk_tup(tcx, elt_ts);
4319 fcx.write_ty(id, typ);
4322 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4323 // Resolve the path.
4324 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
4325 let struct_id = match def {
4326 Some(def::DefVariant(enum_id, variant_id, true)) => {
4327 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4328 variant_id, fields.as_slice());
4331 Some(def::DefTrait(def_id)) => {
4332 span_err!(tcx.sess, path.span, E0159,
4333 "use of trait `{}` as a struct constructor",
4334 pprust::path_to_string(path));
4335 check_struct_fields_on_error(fcx,
4342 // Verify that this was actually a struct.
4343 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4345 ty::ty_struct(struct_did, _) => {
4346 check_struct_constructor(fcx,
4351 base_expr.as_ref().map(|e| &**e));
4354 span_err!(tcx.sess, path.span, E0071,
4355 "`{}` does not name a structure",
4356 pprust::path_to_string(path));
4357 check_struct_fields_on_error(fcx,
4367 tcx.sess.span_bug(path.span,
4368 "structure constructor wasn't resolved")
4372 // Turn the path into a type and verify that that type unifies with
4373 // the resulting structure type. This is needed to handle type
4374 // parameters correctly.
4375 let actual_structure_type = fcx.expr_ty(&*expr);
4376 if !ty::type_is_error(actual_structure_type) {
4377 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4381 match fcx.mk_subty(false,
4382 infer::Misc(path.span),
4383 actual_structure_type,
4384 type_and_substs.ty) {
4386 Err(type_error) => {
4387 let type_error_description =
4388 ty::type_err_to_str(tcx, &type_error);
4391 .span_err(path.span,
4392 format!("structure constructor specifies a \
4393 structure of type `{}`, but this \
4394 structure has type `{}`: {}",
4396 .ty_to_string(type_and_substs.ty),
4399 actual_structure_type),
4400 type_error_description).as_slice());
4401 ty::note_and_explain_type_err(tcx, &type_error);
4406 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4408 ast::ExprField(ref base, ref field, _) => {
4409 check_field(fcx, expr, lvalue_pref, &**base, field);
4411 ast::ExprTupField(ref base, idx, _) => {
4412 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
4414 ast::ExprIndex(ref base, ref idx) => {
4415 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4416 check_expr(fcx, &**idx);
4417 let base_t = fcx.expr_ty(&**base);
4418 let idx_t = fcx.expr_ty(&**idx);
4419 if ty::type_is_error(base_t) {
4420 fcx.write_ty(id, base_t);
4421 } else if ty::type_is_error(idx_t) {
4422 fcx.write_ty(id, idx_t);
4424 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
4427 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
4429 MethodCall::expr(expr.id),
4438 Some((index_ty, element_ty)) => {
4439 check_expr_has_type(fcx, &**idx, index_ty);
4440 fcx.write_ty(id, element_ty);
4443 check_expr_has_type(fcx, &**idx, ty::mk_err());
4444 fcx.type_error_message(
4447 format!("cannot index a value of type `{}`",
4452 fcx.write_ty(id, ty::mk_err())
4457 ast::ExprSlice(ref base, ref start, ref end, mutbl) => {
4458 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4459 let raw_base_t = fcx.expr_ty(&**base);
4461 let mut some_err = false;
4462 if ty::type_is_error(raw_base_t) {
4463 fcx.write_ty(id, raw_base_t);
4468 let check_slice_idx = |e: &ast::Expr| {
4470 let e_t = fcx.expr_ty(e);
4471 if ty::type_is_error(e_t) {
4472 fcx.write_ty(id, e_t);
4476 start.as_ref().map(|e| check_slice_idx(&**e));
4477 end.as_ref().map(|e| check_slice_idx(&**e));
4481 let base_t = structurally_resolved_type(fcx,
4484 let method_call = MethodCall::expr(expr.id);
4485 match try_overloaded_slice(fcx,
4493 Some(ty) => fcx.write_ty(id, ty),
4495 fcx.type_error_message(expr.span,
4497 format!("cannot take a {}slice of a value with type `{}`",
4498 if mutbl == ast::MutMutable {
4507 fcx.write_ty(id, ty::mk_err())
4514 debug!("type of expr({}) {} is...", expr.id,
4515 syntax::print::pprust::expr_to_string(expr));
4516 debug!("... {}, expected is {}",
4517 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4518 expected.repr(tcx));
4523 fn constrain_path_type_parameters(fcx: &FnCtxt,
4526 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4527 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4531 impl<'tcx> Expectation<'tcx> {
4532 fn only_has_type(self) -> Expectation<'tcx> {
4534 NoExpectation | ExpectCastableToType(..) => NoExpectation,
4535 ExpectHasType(t) => ExpectHasType(t)
4539 // Resolves `expected` by a single level if it is a variable. If
4540 // there is no expected type or resolution is not possible (e.g.,
4541 // no constraints yet present), just returns `None`.
4542 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4547 ExpectCastableToType(t) => {
4548 ExpectCastableToType(
4549 fcx.infcx().resolve_type_vars_if_possible(t))
4551 ExpectHasType(t) => {
4553 fcx.infcx().resolve_type_vars_if_possible(t))
4558 fn map<'a>(self, fcx: &FnCtxt<'a, 'tcx>,
4559 unpack: |&ty::sty<'tcx>| -> Expectation<'tcx>)
4560 -> Expectation<'tcx> {
4561 match self.resolve(fcx) {
4562 NoExpectation => NoExpectation,
4563 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
4567 fn map_to_option<'a, O>(self,
4568 fcx: &FnCtxt<'a, 'tcx>,
4569 unpack: |&ty::sty<'tcx>| -> Option<O>)
4572 match self.resolve(fcx) {
4573 NoExpectation => None,
4574 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
4579 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4580 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4582 NoExpectation => format!("NoExpectation"),
4583 ExpectHasType(t) => format!("ExpectHasType({})",
4585 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4591 pub fn check_decl_initializer(fcx: &FnCtxt,
4595 let local_ty = fcx.local_ty(init.span, nid);
4596 check_expr_coercable_to_type(fcx, init, local_ty)
4599 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4600 let tcx = fcx.ccx.tcx;
4602 let t = fcx.local_ty(local.span, local.id);
4603 fcx.write_ty(local.id, t);
4607 check_decl_initializer(fcx, local.id, &**init);
4608 let init_ty = fcx.expr_ty(&**init);
4609 if ty::type_is_error(init_ty) {
4610 fcx.write_ty(local.id, init_ty);
4616 let pcx = pat_ctxt {
4618 map: pat_id_map(&tcx.def_map, &*local.pat),
4620 _match::check_pat(&pcx, &*local.pat, t);
4621 let pat_ty = fcx.node_ty(local.pat.id);
4622 if ty::type_is_error(pat_ty) {
4623 fcx.write_ty(local.id, pat_ty);
4627 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4629 let mut saw_bot = false;
4630 let mut saw_err = false;
4632 ast::StmtDecl(ref decl, id) => {
4635 ast::DeclLocal(ref l) => {
4636 check_decl_local(fcx, &**l);
4637 let l_t = fcx.node_ty(l.id);
4638 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4639 saw_err = saw_err || ty::type_is_error(l_t);
4641 ast::DeclItem(_) => {/* ignore for now */ }
4644 ast::StmtExpr(ref expr, id) => {
4646 // Check with expected type of ()
4647 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4648 let expr_ty = fcx.expr_ty(&**expr);
4649 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4650 saw_err = saw_err || ty::type_is_error(expr_ty);
4652 ast::StmtSemi(ref expr, id) => {
4654 check_expr(fcx, &**expr);
4655 let expr_ty = fcx.expr_ty(&**expr);
4656 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4657 saw_err |= ty::type_is_error(expr_ty);
4659 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4662 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4665 fcx.write_error(node_id);
4668 fcx.write_nil(node_id)
4672 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4673 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4674 let blkty = fcx.node_ty(blk.id);
4675 if ty::type_is_error(blkty) {
4676 fcx.write_error(blk.id);
4678 let nilty = ty::mk_nil(fcx.tcx());
4679 demand::suptype(fcx, blk.span, nilty, blkty);
4683 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4685 expected: Expectation<'tcx>) {
4687 let mut fcx_ps = fcx.ps.borrow_mut();
4688 let fn_style_state = fcx_ps.recurse(blk);
4689 replace(&mut *fcx_ps, fn_style_state)
4692 let mut warned = false;
4693 let mut any_diverges = false;
4694 let mut any_err = false;
4695 for s in blk.stmts.iter() {
4696 check_stmt(fcx, &**s);
4697 let s_id = ast_util::stmt_id(&**s);
4698 let s_ty = fcx.node_ty(s_id);
4699 if any_diverges && !warned && match s.node {
4700 ast::StmtDecl(ref decl, _) => {
4702 ast::DeclLocal(_) => true,
4706 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4712 .add_lint(lint::builtin::UNREACHABLE_CODE,
4715 "unreachable statement".to_string());
4718 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4719 any_err = any_err || ty::type_is_error(s_ty);
4722 None => if any_err {
4723 fcx.write_error(blk.id);
4724 } else if any_diverges {
4725 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4727 fcx.write_nil(blk.id);
4730 if any_diverges && !warned {
4734 .add_lint(lint::builtin::UNREACHABLE_CODE,
4737 "unreachable expression".to_string());
4739 let ety = match expected {
4740 ExpectHasType(ety) => {
4741 check_expr_coercable_to_type(fcx, &**e, ety);
4745 check_expr_with_expectation(fcx, &**e, expected);
4751 fcx.write_error(blk.id);
4752 } else if any_diverges {
4753 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4755 fcx.write_ty(blk.id, ety);
4760 *fcx.ps.borrow_mut() = prev;
4763 /// Checks a constant appearing in a type. At the moment this is just the
4764 /// length expression in a fixed-length vector, but someday it might be
4765 /// extended to type-level numeric literals.
4766 pub fn check_const_in_type<'tcx>(tcx: &ty::ctxt<'tcx>,
4768 expected_type: Ty<'tcx>) {
4769 // Synthesize a crate context. The trait map is not needed here (though I
4770 // imagine it will be if we have associated statics --pcwalton), so we
4772 let ccx = CrateCtxt {
4773 trait_map: NodeMap::new(),
4776 let inh = static_inherited_fields(&ccx);
4777 let fcx = blank_fn_ctxt(&ccx, &inh, ty::FnConverging(expected_type), expr.id);
4778 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4781 pub fn check_const(ccx: &CrateCtxt,
4785 let inh = static_inherited_fields(ccx);
4786 let rty = ty::node_id_to_type(ccx.tcx, id);
4787 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4788 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4789 check_const_with_ty(&fcx, sp, e, declty);
4792 pub fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4796 // Gather locals in statics (because of block expressions).
4797 // This is technically unnecessary because locals in static items are forbidden,
4798 // but prevents type checking from blowing up before const checking can properly
4800 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4802 check_expr_with_hint(fcx, e, declty);
4803 demand::coerce(fcx, e.span, declty, e);
4804 vtable::select_all_fcx_obligations_or_error(fcx);
4805 regionck::regionck_expr(fcx, e);
4806 writeback::resolve_type_vars_in_expr(fcx, e);
4809 /// Checks whether a type can be represented in memory. In particular, it
4810 /// identifies types that contain themselves without indirection through a
4811 /// pointer, which would mean their size is unbounded. This is different from
4812 /// the question of whether a type can be instantiated. See the definition of
4813 /// `check_instantiable`.
4814 pub fn check_representable(tcx: &ty::ctxt,
4816 item_id: ast::NodeId,
4817 designation: &str) -> bool {
4818 let rty = ty::node_id_to_type(tcx, item_id);
4820 // Check that it is possible to represent this type. This call identifies
4821 // (1) types that contain themselves and (2) types that contain a different
4822 // recursive type. It is only necessary to throw an error on those that
4823 // contain themselves. For case 2, there must be an inner type that will be
4824 // caught by case 1.
4825 match ty::is_type_representable(tcx, sp, rty) {
4826 ty::SelfRecursive => {
4827 span_err!(tcx.sess, sp, E0072,
4828 "illegal recursive {} type; \
4829 wrap the inner value in a box to make it representable",
4833 ty::Representable | ty::ContainsRecursive => (),
4838 /// Checks whether a type can be created without an instance of itself.
4839 /// This is similar but different from the question of whether a type
4840 /// can be represented. For example, the following type:
4842 /// enum foo { None, Some(foo) }
4844 /// is instantiable but is not representable. Similarly, the type
4846 /// enum foo { Some(@foo) }
4848 /// is representable, but not instantiable.
4849 pub fn check_instantiable(tcx: &ty::ctxt,
4851 item_id: ast::NodeId)
4853 let item_ty = ty::node_id_to_type(tcx, item_id);
4854 if !ty::is_instantiable(tcx, item_ty) {
4855 span_err!(tcx.sess, sp, E0073,
4856 "this type cannot be instantiated without an \
4857 instance of itself");
4858 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4859 ppaux::ty_to_string(tcx, item_ty));
4866 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4867 let t = ty::node_id_to_type(tcx, id);
4868 if ty::type_needs_subst(t) {
4869 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4873 ty::ty_struct(did, ref substs) => {
4874 let fields = ty::lookup_struct_fields(tcx, did);
4875 if fields.is_empty() {
4876 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4879 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4880 if !fields.iter().all(
4881 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4882 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4885 if !ty::type_is_machine(e) {
4886 span_err!(tcx.sess, sp, E0077,
4887 "SIMD vector element type should be machine type");
4895 pub fn check_enum_variants(ccx: &CrateCtxt,
4897 vs: &[P<ast::Variant>],
4900 fn disr_in_range(ccx: &CrateCtxt,
4902 disr: ty::Disr) -> bool {
4903 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4905 ast::TyU8 => disr as u8 as Disr == disr,
4906 ast::TyU16 => disr as u16 as Disr == disr,
4907 ast::TyU32 => disr as u32 as Disr == disr,
4908 ast::TyU64 => disr as u64 as Disr == disr,
4909 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4912 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4914 ast::TyI8 => disr as i8 as Disr == disr,
4915 ast::TyI16 => disr as i16 as Disr == disr,
4916 ast::TyI32 => disr as i32 as Disr == disr,
4917 ast::TyI64 => disr as i64 as Disr == disr,
4918 ast::TyI => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4922 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4923 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4927 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4928 vs: &[P<ast::Variant>],
4930 hint: attr::ReprAttr)
4931 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4933 let rty = ty::node_id_to_type(ccx.tcx, id);
4934 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4935 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4936 let mut prev_disr_val: Option<ty::Disr> = None;
4938 for v in vs.iter() {
4940 // If the discriminant value is specified explicitly in the enum check whether the
4941 // initialization expression is valid, otherwise use the last value plus one.
4942 let mut current_disr_val = match prev_disr_val {
4943 Some(prev_disr_val) => prev_disr_val + 1,
4944 None => ty::INITIAL_DISCRIMINANT_VALUE
4947 match v.node.disr_expr {
4949 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4951 let inh = static_inherited_fields(ccx);
4952 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4953 let declty = match hint {
4954 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4955 attr::ReprInt(_, attr::SignedInt(ity)) => {
4956 ty::mk_mach_int(ity)
4958 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4959 ty::mk_mach_uint(ity)
4962 check_const_with_ty(&fcx, e.span, &**e, declty);
4963 // check_expr (from check_const pass) doesn't guarantee
4964 // that the expression is in a form that eval_const_expr can
4965 // handle, so we may still get an internal compiler error
4967 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4968 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4969 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4971 span_err!(ccx.tcx.sess, e.span, E0079,
4972 "expected signed integer constant");
4975 span_err!(ccx.tcx.sess, e.span, E0080,
4976 "expected constant: {}", *err);
4983 // Check for duplicate discriminant values
4984 match disr_vals.iter().position(|&x| x == current_disr_val) {
4986 span_err!(ccx.tcx.sess, v.span, E0081,
4987 "discriminant value `{}` already exists", disr_vals[i]);
4988 span_note!(ccx.tcx.sess, ccx.tcx().map.span(variants[i].id.node),
4989 "conflicting discriminant here")
4993 // Check for unrepresentable discriminant values
4995 attr::ReprAny | attr::ReprExtern => (),
4996 attr::ReprInt(sp, ity) => {
4997 if !disr_in_range(ccx, ity, current_disr_val) {
4998 span_err!(ccx.tcx.sess, v.span, E0082,
4999 "discriminant value outside specified type");
5000 span_note!(ccx.tcx.sess, sp,
5001 "discriminant type specified here");
5004 attr::ReprPacked => {
5005 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
5008 disr_vals.push(current_disr_val);
5010 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
5012 prev_disr_val = Some(current_disr_val);
5014 variants.push(variant_info);
5020 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
5021 .as_slice().get(0).unwrap_or(&attr::ReprAny);
5023 if hint != attr::ReprAny && vs.len() <= 1 {
5025 span_err!(ccx.tcx.sess, sp, E0083,
5026 "unsupported representation for univariant enum");
5028 span_err!(ccx.tcx.sess, sp, E0084,
5029 "unsupported representation for zero-variant enum");
5033 let variants = do_check(ccx, vs, id, hint);
5035 // cache so that ty::enum_variants won't repeat this work
5036 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
5038 check_representable(ccx.tcx, sp, id, "enum");
5040 // Check that it is possible to instantiate this enum:
5042 // This *sounds* like the same that as representable, but it's
5043 // not. See def'n of `check_instantiable()` for details.
5044 check_instantiable(ccx.tcx, sp, id);
5047 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
5048 lookup_def_ccx(fcx.ccx, sp, id)
5051 // Returns the type parameter count and the type for the given definition.
5052 pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5057 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
5058 let typ = fcx.local_ty(sp, nid);
5059 return no_params(typ);
5061 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
5062 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
5063 def::DefStruct(id) | def::DefConst(id) => {
5064 return ty::lookup_item_type(fcx.ccx.tcx, id);
5068 def::DefAssociatedTy(..) |
5070 def::DefTyParam(..)=> {
5071 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
5073 def::DefMod(..) | def::DefForeignMod(..) => {
5074 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
5076 def::DefUse(..) => {
5077 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
5079 def::DefRegion(..) => {
5080 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
5082 def::DefTyParamBinder(..) => {
5083 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
5085 def::DefLabel(..) => {
5086 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
5088 def::DefSelfTy(..) => {
5089 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5094 // Instantiates the given path, which must refer to an item with the given
5095 // number of type parameters and type.
5096 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5098 polytype: Polytype<'tcx>,
5101 node_id: ast::NodeId) {
5102 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
5103 path.repr(fcx.tcx()),
5104 def.repr(fcx.tcx()),
5106 polytype.repr(fcx.tcx()));
5108 // We need to extract the type parameters supplied by the user in
5109 // the path `path`. Due to the current setup, this is a bit of a
5110 // tricky-process; the problem is that resolve only tells us the
5111 // end-point of the path resolution, and not the intermediate steps.
5112 // Luckily, we can (at least for now) deduce the intermediate steps
5113 // just from the end-point.
5115 // There are basically three cases to consider:
5117 // 1. Reference to a *type*, such as a struct or enum:
5119 // mod a { struct Foo<T> { ... } }
5121 // Because we don't allow types to be declared within one
5122 // another, a path that leads to a type will always look like
5123 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
5124 // that only the final segment can have type parameters, and
5125 // they are located in the TypeSpace.
5127 // *Note:* Generally speaking, references to types don't
5128 // actually pass through this function, but rather the
5129 // `ast_ty_to_ty` function in `astconv`. However, in the case
5130 // of struct patterns (and maybe literals) we do invoke
5131 // `instantiate_path` to get the general type of an instance of
5132 // a struct. (In these cases, there are actually no type
5133 // parameters permitted at present, but perhaps we will allow
5134 // them in the future.)
5136 // 1b. Reference to a enum variant or tuple-like struct:
5138 // struct foo<T>(...)
5139 // enum E<T> { foo(...) }
5141 // In these cases, the parameters are declared in the type
5144 // 2. Reference to a *fn item*:
5148 // In this case, the path will again always have the form
5149 // `a::b::foo::<T>` where only the final segment should have
5150 // type parameters. However, in this case, those parameters are
5151 // declared on a value, and hence are in the `FnSpace`.
5153 // 3. Reference to a *method*:
5155 // impl<A> SomeStruct<A> {
5159 // Here we can have a path like
5160 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5161 // may appear in two places. The penultimate segment,
5162 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5163 // final segment, `foo::<B>` contains parameters in fn space.
5165 // The first step then is to categorize the segments appropriately.
5167 assert!(path.segments.len() >= 1);
5168 let mut segment_spaces;
5170 // Case 1 and 1b. Reference to a *type* or *enum variant*.
5171 def::DefSelfTy(..) |
5172 def::DefStruct(..) |
5173 def::DefVariant(..) |
5174 def::DefTyParamBinder(..) |
5176 def::DefAssociatedTy(..) |
5178 def::DefPrimTy(..) |
5179 def::DefTyParam(..) => {
5180 // Everything but the final segment should have no
5181 // parameters at all.
5182 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5183 segment_spaces.push(Some(subst::TypeSpace));
5186 // Case 2. Reference to a top-level value.
5189 def::DefStatic(..) => {
5190 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5191 segment_spaces.push(Some(subst::FnSpace));
5194 // Case 3. Reference to a method.
5195 def::DefStaticMethod(..) => {
5196 assert!(path.segments.len() >= 2);
5197 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
5198 segment_spaces.push(Some(subst::TypeSpace));
5199 segment_spaces.push(Some(subst::FnSpace));
5202 // Other cases. Various nonsense that really shouldn't show up
5203 // here. If they do, an error will have been reported
5204 // elsewhere. (I hope)
5206 def::DefForeignMod(..) |
5208 def::DefMethod(..) |
5210 def::DefRegion(..) |
5212 def::DefUpvar(..) => {
5213 segment_spaces = Vec::from_elem(path.segments.len(), None);
5216 assert_eq!(segment_spaces.len(), path.segments.len());
5218 debug!("segment_spaces={}", segment_spaces);
5220 // Next, examine the definition, and determine how many type
5221 // parameters we expect from each space.
5222 let type_defs = &polytype.generics.types;
5223 let region_defs = &polytype.generics.regions;
5225 // Now that we have categorized what space the parameters for each
5226 // segment belong to, let's sort out the parameters that the user
5227 // provided (if any) into their appropriate spaces. We'll also report
5228 // errors if type parameters are provided in an inappropriate place.
5229 let mut substs = Substs::empty();
5230 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5233 report_error_if_segment_contains_type_parameters(fcx, segment);
5237 push_explicit_parameters_from_segment_to_substs(fcx,
5248 // Now we have to compare the types that the user *actually*
5249 // provided against the types that were *expected*. If the user
5250 // did not provide any types, then we want to substitute inference
5251 // variables. If the user provided some types, we may still need
5252 // to add defaults. If the user provided *too many* types, that's
5254 for &space in ParamSpace::all().iter() {
5255 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5256 assert_eq!(substs.types.len(space), type_defs.len(space));
5258 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5259 assert_eq!(substs.regions().len(space), region_defs.len(space));
5262 // The things we are substituting into the type should not contain
5263 // escaping late-bound regions.
5264 assert!(!substs.has_regions_escaping_depth(0));
5266 // In the case of static items taken from impls, there may be
5267 // late-bound regions associated with the impl (not declared on
5268 // the fn itself). Those should be replaced with fresh variables
5269 // now. These can appear either on the type being referenced, or
5270 // on the associated bounds.
5271 let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs);
5272 let (ty_late_bound, bounds) =
5273 fcx.infcx().replace_late_bound_regions_with_fresh_var(
5276 &ty::bind((polytype.ty, bounds))).0.value;
5278 debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx()));
5279 debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx()));
5281 fcx.add_obligations_for_parameters(
5282 traits::ObligationCause::new(span, traits::ItemObligation(def.def_id())),
5286 // Substitute the values for the type parameters into the type of
5287 // the referenced item.
5288 let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs);
5290 debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx()));
5292 fcx.write_ty(node_id, ty_substituted);
5293 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
5296 fn report_error_if_segment_contains_type_parameters(
5298 segment: &ast::PathSegment)
5300 for typ in segment.parameters.types().iter() {
5301 span_err!(fcx.tcx().sess, typ.span, E0085,
5302 "type parameters may not appear here");
5306 for lifetime in segment.parameters.lifetimes().iter() {
5307 span_err!(fcx.tcx().sess, lifetime.span, E0086,
5308 "lifetime parameters may not appear here");
5313 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
5314 fcx: &FnCtxt<'a, 'tcx>,
5315 space: subst::ParamSpace,
5317 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5318 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5319 segment: &ast::PathSegment,
5320 substs: &mut Substs<'tcx>)
5323 * Finds the parameters that the user provided and adds them
5324 * to `substs`. If too many parameters are provided, then
5325 * reports an error and clears the output vector.
5327 * We clear the output vector because that will cause the
5328 * `adjust_XXX_parameters()` later to use inference
5329 * variables. This seems less likely to lead to derived
5332 * Note that we *do not* check for *too few* parameters here.
5333 * Due to the presence of defaults etc that is more
5334 * complicated. I wanted however to do the reporting of *too
5335 * many* parameters here because we can easily use the precise
5336 * span of the N+1'th parameter.
5339 match segment.parameters {
5340 ast::AngleBracketedParameters(ref data) => {
5341 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
5342 fcx, space, type_defs, region_defs, data, substs);
5345 ast::ParenthesizedParameters(ref data) => {
5346 push_explicit_parenthesized_parameters_from_segment_to_substs(
5347 fcx, space, span, type_defs, data, substs);
5352 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
5353 fcx: &FnCtxt<'a, 'tcx>,
5354 space: subst::ParamSpace,
5355 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5356 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5357 data: &ast::AngleBracketedParameterData,
5358 substs: &mut Substs<'tcx>)
5361 let type_count = type_defs.len(space);
5362 assert_eq!(substs.types.len(space), 0);
5363 for (i, typ) in data.types.iter().enumerate() {
5364 let t = fcx.to_ty(&**typ);
5366 substs.types.push(space, t);
5367 } else if i == type_count {
5368 span_err!(fcx.tcx().sess, typ.span, E0087,
5369 "too many type parameters provided: \
5370 expected at most {} parameter(s), \
5371 found {} parameter(s)",
5372 type_count, data.types.len());
5373 substs.types.truncate(space, 0);
5379 let region_count = region_defs.len(space);
5380 assert_eq!(substs.regions().len(space), 0);
5381 for (i, lifetime) in data.lifetimes.iter().enumerate() {
5382 let r = ast_region_to_region(fcx.tcx(), lifetime);
5383 if i < region_count {
5384 substs.mut_regions().push(space, r);
5385 } else if i == region_count {
5386 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5387 "too many lifetime parameters provided: \
5388 expected {} parameter(s), found {} parameter(s)",
5390 data.lifetimes.len());
5391 substs.mut_regions().truncate(space, 0);
5397 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
5398 fcx: &FnCtxt<'a, 'tcx>,
5399 space: subst::ParamSpace,
5401 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5402 data: &ast::ParenthesizedParameterData,
5403 substs: &mut Substs<'tcx>)
5407 * `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
5408 * but intended for `Foo(A,B) -> C` form. This expands to
5409 * roughly the same thing as `Foo<(A,B),C>`. One important
5410 * difference has to do with the treatment of anonymous
5411 * regions, which are translated into bound regions (NYI).
5414 let type_count = type_defs.len(space);
5416 span_err!(fcx.tcx().sess, span, E0167,
5417 "parenthesized form always supplies 2 type parameters, \
5418 but only {} parameter(s) were expected",
5422 let input_tys: Vec<Ty> =
5423 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
5426 ty::mk_tup(fcx.tcx(), input_tys);
5428 if type_count >= 1 {
5429 substs.types.push(space, tuple_ty);
5432 let output_ty: Option<Ty> =
5433 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
5436 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
5438 if type_count >= 2 {
5439 substs.types.push(space, output_ty);
5443 fn adjust_type_parameters<'a, 'tcx>(
5444 fcx: &FnCtxt<'a, 'tcx>,
5447 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5448 substs: &mut Substs<'tcx>)
5450 let provided_len = substs.types.len(space);
5451 let desired = defs.get_slice(space);
5452 let required_len = desired.iter()
5453 .take_while(|d| d.default.is_none())
5456 debug!("adjust_type_parameters(space={}, \
5465 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5466 assert!(provided_len <= desired.len());
5468 // Nothing specified at all: supply inference variables for
5470 if provided_len == 0 {
5471 substs.types.replace(space,
5472 fcx.infcx().next_ty_vars(desired.len()));
5476 // Too few parameters specified: report an error and use Err
5478 if provided_len < required_len {
5480 if desired.len() != required_len { "at least " } else { "" };
5481 span_err!(fcx.tcx().sess, span, E0089,
5482 "too few type parameters provided: expected {}{} parameter(s) \
5483 , found {} parameter(s)",
5484 qualifier, required_len, provided_len);
5485 substs.types.replace(space,
5486 Vec::from_elem(desired.len(), ty::mk_err()));
5490 // Otherwise, add in any optional parameters that the user
5491 // omitted. The case of *too many* parameters is handled
5493 // push_explicit_parameters_from_segment_to_substs(). Note
5494 // that the *default* type are expressed in terms of all prior
5495 // parameters, so we have to substitute as we go with the
5496 // partial substitution that we have built up.
5497 for i in range(provided_len, desired.len()) {
5498 let default = desired[i].default.unwrap();
5499 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5500 substs.types.push(space, default);
5502 assert_eq!(substs.types.len(space), desired.len());
5504 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5507 fn adjust_region_parameters(
5511 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5512 substs: &mut Substs)
5514 let provided_len = substs.mut_regions().len(space);
5515 let desired = defs.get_slice(space);
5517 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5518 assert!(provided_len <= desired.len());
5520 // If nothing was provided, just use inference variables.
5521 if provided_len == 0 {
5522 substs.mut_regions().replace(
5524 fcx.infcx().region_vars_for_defs(span, desired));
5528 // If just the right number were provided, everybody is happy.
5529 if provided_len == desired.len() {
5533 // Otherwise, too few were provided. Report an error and then
5534 // use inference variables.
5535 span_err!(fcx.tcx().sess, span, E0090,
5536 "too few lifetime parameters provided: expected {} parameter(s), \
5537 found {} parameter(s)",
5538 desired.len(), provided_len);
5540 substs.mut_regions().replace(
5542 fcx.infcx().region_vars_for_defs(span, desired));
5546 // Resolves `typ` by a single level if `typ` is a type variable. If no
5547 // resolution is possible, then an error is reported.
5548 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5549 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5550 // If `ty` is a type variable, see whether we already know what it is.
5551 ty = fcx.infcx().shallow_resolve(ty);
5553 // If not, try resolve pending fcx obligations. Those can shed light.
5555 // FIXME(#18391) -- This current strategy can lead to bad performance in
5556 // extreme cases. We probably ought to smarter in general about
5557 // only resolving when we need help and only resolving obligations
5558 // will actually help.
5559 if ty::type_is_ty_var(ty) {
5560 vtable::select_fcx_obligations_where_possible(fcx);
5561 ty = fcx.infcx().shallow_resolve(ty);
5565 if ty::type_is_ty_var(ty) {
5566 fcx.type_error_message(sp, |_actual| {
5567 "the type of this value must be known in this \
5568 context".to_string()
5570 demand::suptype(fcx, sp, ty::mk_err(), ty);
5577 // Returns the one-level-deep structure of the given type.
5578 pub fn structure_of<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, typ: Ty<'tcx>)
5579 -> &'tcx ty::sty<'tcx> {
5580 &structurally_resolved_type(fcx, sp, typ).sty
5583 // Returns true if b contains a break that can exit from b
5584 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5585 // First: is there an unlabeled break immediately
5587 (loop_query(&*b, |e| {
5589 ast::ExprBreak(_) => true,
5593 // Second: is there a labeled break with label
5594 // <id> nested anywhere inside the loop?
5595 (block_query(b, |e| {
5597 ast::ExprBreak(Some(_)) => {
5598 match cx.def_map.borrow().get(&e.id) {
5599 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5607 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5609 tps: &OwnedSlice<ast::TyParam>,
5611 debug!("check_bounds_are_used(n_tps={}, ty={})",
5612 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5614 // make a vector of booleans initially false, set to true when used
5615 if tps.len() == 0u { return; }
5616 let mut tps_used = Vec::from_elem(tps.len(), false);
5618 ty::walk_ty(ty, |t| {
5620 ty::ty_param(ParamTy {idx, ..}) => {
5621 debug!("Found use of ty param num {}", idx);
5622 tps_used[idx] = true;
5628 for (i, b) in tps_used.iter().enumerate() {
5630 span_err!(ccx.tcx.sess, span, E0091,
5631 "type parameter `{}` is unused",
5632 token::get_ident(tps.get(i).ident));
5637 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5638 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: uint) -> Ty<'tcx> {
5639 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5643 let name = token::get_ident(it.ident);
5644 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5645 let split : Vec<&str> = name.get().split('_').collect();
5646 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5648 //We only care about the operation here
5649 let (n_tps, inputs, output) = match split[1] {
5650 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5654 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5656 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5659 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5660 "min" | "umax" | "umin" => {
5661 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5665 (0, Vec::new(), ty::mk_nil(tcx))
5668 span_err!(tcx.sess, it.span, E0092,
5669 "unrecognized atomic operation function: `{}`", op);
5673 (n_tps, inputs, ty::FnConverging(output))
5674 } else if name.get() == "abort" || name.get() == "unreachable" {
5675 (0, Vec::new(), ty::FnDiverging)
5677 let (n_tps, inputs, output) = match name.get() {
5678 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5680 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5681 "init" => (1u, Vec::new(), param(ccx, 0u)),
5682 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5683 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5684 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5685 "move_val_init" => {
5688 ty::mk_mut_rptr(tcx, ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0)),
5694 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5695 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5698 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5700 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5702 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5704 mutbl: ast::MutImmutable
5706 (1u, Vec::new(), td_ptr)
5709 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5713 ty::mk_struct(ccx.tcx, did,
5714 subst::Substs::empty())),
5716 tcx.sess.span_fatal(it.span, msg.as_slice());
5723 ty::mk_ptr(tcx, ty::mt {
5725 mutbl: ast::MutImmutable
5729 ty::mk_ptr(tcx, ty::mt {
5731 mutbl: ast::MutImmutable
5734 "copy_memory" | "copy_nonoverlapping_memory" |
5735 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5738 ty::mk_ptr(tcx, ty::mt {
5740 mutbl: ast::MutMutable
5742 ty::mk_ptr(tcx, ty::mt {
5744 mutbl: ast::MutImmutable
5750 "set_memory" | "volatile_set_memory" => {
5753 ty::mk_ptr(tcx, ty::mt {
5755 mutbl: ast::MutMutable
5762 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5763 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5766 vec!( ty::mk_f32(), ty::mk_i32() ),
5771 vec!( ty::mk_f64(), ty::mk_i32() ),
5774 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5775 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5776 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5777 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5780 vec!( ty::mk_f32(), ty::mk_f32() ),
5785 vec!( ty::mk_f64(), ty::mk_f64() ),
5788 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5789 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5790 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5791 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5792 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5793 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5794 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5795 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5796 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5797 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5800 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5805 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5808 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5809 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5810 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5811 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5812 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5813 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5814 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5815 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5816 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5817 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5818 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5819 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5820 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5821 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5822 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5823 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5824 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5825 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5826 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5827 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5828 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5829 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5830 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5831 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5832 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5833 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5834 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5835 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5836 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5837 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5838 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5841 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5843 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5845 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5846 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5847 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5849 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5850 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5851 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5853 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5854 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5855 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5857 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5858 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5859 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5861 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5862 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5863 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5865 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5866 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5867 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5869 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5870 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5871 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5873 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5874 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5875 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5877 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5879 "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
5882 span_err!(tcx.sess, it.span, E0093,
5883 "unrecognized intrinsic function: `{}`", *other);
5887 (n_tps, inputs, ty::FnConverging(output))
5889 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5890 fn_style: ast::UnsafeFn,
5891 abi: abi::RustIntrinsic,
5898 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5899 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5900 if i_n_tps != n_tps {
5901 span_err!(tcx.sess, it.span, E0094,
5902 "intrinsic has wrong number of type \
5903 parameters: found {}, expected {}",
5906 require_same_types(tcx,
5913 format!("intrinsic has wrong type: expected `{}`",
5914 ppaux::ty_to_string(ccx.tcx, fty))
5919 impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
5920 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
5921 format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5922 self.sub_region.repr(tcx),
5923 self.sup_type.repr(tcx),
5924 self.origin.repr(tcx))