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 `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::*;
85 use astconv::{mod, ast_region_to_region, ast_ty_to_ty, AstConv};
86 use check::_match::pat_ctxt;
87 use middle::{const_eval, def, traits};
89 use middle::lang_items::IteratorItem;
90 use middle::mem_categorization::{mod, McResult};
91 use middle::pat_util::{mod, pat_id_map};
92 use middle::region::CodeExtent;
93 use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace};
94 use middle::ty::{FnSig, VariantInfo, Polytype};
95 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
96 use middle::ty::{mod, Ty};
97 use middle::ty::liberate_late_bound_regions;
98 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
99 use middle::ty_fold::TypeFolder;
100 use rscope::RegionScope;
101 use session::Session;
102 use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
104 use middle::lang_items::TypeIdLangItem;
106 use util::common::{block_query, indenter, loop_query};
107 use util::ppaux::{mod, UserString, Repr};
108 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
110 use std::cell::{Cell, Ref, RefCell};
111 use std::collections::hash_map::{Occupied, Vacant};
112 use std::mem::replace;
114 use syntax::{mod, abi, attr};
115 use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem};
116 use syntax::ast_util::{mod, local_def, PostExpansionMethod};
117 use syntax::codemap::{mod, Span};
118 use syntax::owned_slice::OwnedSlice;
119 use syntax::parse::token;
120 use syntax::print::pprust;
122 use syntax::visit::{mod, Visitor};
135 /// Fields that are part of a `FnCtxt` which are inherited by
136 /// closures defined within the function. For example:
139 /// bar(proc() { ... })
142 /// Here, the function `foo()` and the closure passed to
143 /// `bar()` will each have their own `FnCtxt`, but they will
144 /// share the inherited fields.
145 pub struct Inherited<'a, 'tcx: 'a> {
146 infcx: infer::InferCtxt<'a, 'tcx>,
147 locals: RefCell<NodeMap<Ty<'tcx>>>,
148 param_env: ty::ParameterEnvironment<'tcx>,
151 node_types: RefCell<NodeMap<Ty<'tcx>>>,
152 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
153 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
154 method_map: MethodMap<'tcx>,
155 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
156 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
157 object_cast_map: ObjectCastMap<'tcx>,
159 // A mapping from each fn's id to its signature, with all bound
160 // regions replaced with free ones. Unlike the other tables, this
161 // one is never copied into the tcx: it is only used by regionck.
162 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
164 // A set of constraints that regionck must validate. Each
165 // constraint has the form `T:'a`, meaning "some type `T` must
166 // outlive the lifetime 'a". These constraints derive from
167 // instantiated type parameters. So if you had a struct defined
170 // struct Foo<T:'static> { ... }
172 // then in some expression `let x = Foo { ... }` it will
173 // instantiate the type parameter `T` with a fresh type `$0`. At
174 // the same time, it will record a region obligation of
175 // `$0:'static`. This will get checked later by regionck. (We
176 // can't generally check these things right away because we have
177 // to wait until types are resolved.)
179 // These are stored in a map keyed to the id of the innermost
180 // enclosing fn body / static initializer expression. This is
181 // because the location where the obligation was incurred can be
182 // relevant with respect to which sublifetime assumptions are in
183 // place. The reason that we store under the fn-id, and not
184 // something more fine-grained, is so that it is easier for
185 // regionck to be sure that it has found *all* the region
186 // obligations (otherwise, it's easy to fail to walk to a
187 // particular node-id).
188 region_obligations: RefCell<NodeMap<Vec<RegionObligation<'tcx>>>>,
190 // Tracks trait obligations incurred during this function body.
191 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
194 struct RegionObligation<'tcx> {
195 sub_region: ty::Region,
197 origin: infer::SubregionOrigin<'tcx>,
200 /// When type-checking an expression, we propagate downward
201 /// whatever type hint we are able in the form of an `Expectation`.
202 enum Expectation<'tcx> {
203 /// We know nothing about what type this expression should have.
206 /// This expression should have the type given (or some subtype)
207 ExpectHasType(Ty<'tcx>),
209 /// This expression will be cast to the `Ty`
210 ExpectCastableToType(Ty<'tcx>),
213 impl<'tcx> Copy for Expectation<'tcx> {}
216 pub struct FnStyleState {
217 pub def: ast::NodeId,
218 pub fn_style: ast::FnStyle,
222 impl Copy for FnStyleState {}
225 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
226 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
229 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
230 match self.fn_style {
231 // If this unsafe, then if the outer function was already marked as
232 // unsafe we shouldn't attribute the unsafe'ness to the block. This
233 // way the block can be warned about instead of ignoring this
234 // extraneous block (functions are never warned about).
235 ast::UnsafeFn if self.from_fn => *self,
238 let (fn_style, def) = match blk.rules {
239 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
240 ast::DefaultBlock => (fn_style, self.def),
242 FnStyleState{ def: def,
250 /// Whether `check_binop` is part of an assignment or not.
251 /// Used to know whether we allow user overloads and to print
252 /// better messages on error.
253 #[deriving(PartialEq)]
254 enum IsBinopAssignment{
260 pub struct FnCtxt<'a, 'tcx: 'a> {
261 body_id: ast::NodeId,
263 // This flag is set to true if, during the writeback phase, we encounter
264 // a type error in this function.
265 writeback_errors: Cell<bool>,
267 // Number of errors that had been reported when we started
268 // checking this function. On exit, if we find that *more* errors
269 // have been reported, we will skip regionck and other work that
270 // expects the types within the function to be consistent.
271 err_count_on_creation: uint,
273 ret_ty: ty::FnOutput<'tcx>,
275 ps: RefCell<FnStyleState>,
277 inh: &'a Inherited<'a, 'tcx>,
279 ccx: &'a CrateCtxt<'a, 'tcx>,
282 impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
283 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
286 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
289 fn node_method_ty(&self, method_call: ty::MethodCall)
290 -> Option<Ty<'tcx>> {
291 self.inh.method_map.borrow().get(&method_call).map(|m| m.ty)
293 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
294 &self.inh.adjustments
296 fn is_method_call(&self, id: ast::NodeId) -> bool {
297 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
299 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
300 self.tcx().temporary_scope(rvalue_id)
302 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
303 self.inh.upvar_borrow_map.borrow()[upvar_id].clone()
305 fn capture_mode(&self, closure_expr_id: ast::NodeId)
306 -> ast::CaptureClause {
307 self.ccx.tcx.capture_mode(closure_expr_id)
309 fn unboxed_closures<'a>(&'a self)
310 -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
311 &self.inh.unboxed_closures
315 impl<'a, 'tcx> Inherited<'a, 'tcx> {
316 fn new(tcx: &'a ty::ctxt<'tcx>,
317 param_env: ty::ParameterEnvironment<'tcx>)
318 -> Inherited<'a, 'tcx> {
320 infcx: infer::new_infer_ctxt(tcx),
321 locals: RefCell::new(NodeMap::new()),
322 param_env: param_env,
323 node_types: RefCell::new(NodeMap::new()),
324 item_substs: RefCell::new(NodeMap::new()),
325 adjustments: RefCell::new(NodeMap::new()),
326 method_map: RefCell::new(FnvHashMap::new()),
327 object_cast_map: RefCell::new(NodeMap::new()),
328 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
329 unboxed_closures: RefCell::new(DefIdMap::new()),
330 fn_sig_map: RefCell::new(NodeMap::new()),
331 region_obligations: RefCell::new(NodeMap::new()),
332 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
337 // Used by check_const and check_enum_variants
338 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
339 inh: &'a Inherited<'a, 'tcx>,
340 rty: ty::FnOutput<'tcx>,
341 body_id: ast::NodeId)
342 -> FnCtxt<'a, 'tcx> {
345 writeback_errors: Cell::new(false),
346 err_count_on_creation: ccx.tcx.sess.err_count(),
348 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
354 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
355 -> Inherited<'a, 'tcx> {
356 // It's kind of a kludge to manufacture a fake function context
357 // and statement context, but we might as well do write the code only once
358 let param_env = ty::empty_parameter_environment();
359 Inherited::new(ccx.tcx, param_env)
362 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
364 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
365 fn visit_item(&mut self, i: &ast::Item) {
366 check_item(self.ccx, i);
367 visit::walk_item(self, i);
370 fn visit_ty(&mut self, t: &ast::Ty) {
372 ast::TyFixedLengthVec(_, ref expr) => {
373 check_const_in_type(self.ccx, &**expr, ty::mk_uint());
378 visit::walk_ty(self, t);
382 pub fn check_item_types(ccx: &CrateCtxt) {
383 let krate = ccx.tcx.map.krate();
384 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
385 visit::walk_crate(&mut visit, krate);
387 // If types are not well-formed, it leads to all manner of errors
388 // downstream, so stop reporting errors at this point.
389 ccx.tcx.sess.abort_if_errors();
391 let mut visit = CheckItemTypesVisitor { ccx: ccx };
392 visit::walk_crate(&mut visit, krate);
394 ccx.tcx.sess.abort_if_errors();
397 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
402 param_env: ty::ParameterEnvironment<'tcx>) {
403 // Compute the fty from point of view of inside fn
404 // (replace any type-scheme with a type)
405 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
408 ty::ty_bare_fn(ref fn_ty) => {
409 let inh = Inherited::new(ccx.tcx, param_env);
410 let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
411 decl, id, body, &inh);
413 vtable::select_all_fcx_obligations_or_error(&fcx);
414 regionck::regionck_fn(&fcx, id, decl, body);
415 fcx.default_diverging_type_variables_to_nil();
416 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
418 _ => ccx.tcx.sess.impossible_case(body.span,
419 "check_bare_fn: function type expected")
423 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
424 fcx: &'a FnCtxt<'a, 'tcx>
427 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
428 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
431 // infer the variable's type
432 let var_ty = self.fcx.infcx().next_ty_var();
433 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
437 // take type that the user specified
438 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
445 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
446 // Add explicitly-declared locals.
447 fn visit_local(&mut self, local: &ast::Local) {
448 let o_ty = match local.ty.node {
449 ast::TyInfer => None,
450 _ => Some(self.fcx.to_ty(&*local.ty))
452 self.assign(local.span, local.id, o_ty);
453 debug!("Local variable {} is assigned type {}",
454 self.fcx.pat_to_string(&*local.pat),
455 self.fcx.infcx().ty_to_string(
456 self.fcx.inh.locals.borrow()[local.id].clone()));
457 visit::walk_local(self, local);
460 // Add pattern bindings.
461 fn visit_pat(&mut self, p: &ast::Pat) {
462 if let ast::PatIdent(_, ref path1, _) = p.node {
463 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
464 let var_ty = self.assign(p.span, p.id, None);
466 self.fcx.require_type_is_sized(var_ty, p.span,
467 traits::VariableType(p.id));
469 debug!("Pattern binding {} is assigned to {} with type {}",
470 token::get_ident(path1.node),
471 self.fcx.infcx().ty_to_string(
472 self.fcx.inh.locals.borrow()[p.id].clone()),
473 var_ty.repr(self.fcx.tcx()));
476 visit::walk_pat(self, p);
479 fn visit_block(&mut self, b: &ast::Block) {
480 // non-obvious: the `blk` variable maps to region lb, so
481 // we have to keep this up-to-date. This
482 // is... unfortunate. It'd be nice to not need this.
483 visit::walk_block(self, b);
486 // Since an expr occurs as part of the type fixed size arrays we
487 // need to record the type for that node
488 fn visit_ty(&mut self, t: &ast::Ty) {
490 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
491 self.visit_ty(&**ty);
492 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
494 _ => visit::walk_ty(self, t)
498 // Don't descend into fns and items
499 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
500 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
501 fn visit_item(&mut self, _: &ast::Item) { }
505 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
506 /// body and returns the function context used for that purpose, since in the case of a fn item
507 /// there is still a bit more to do.
510 /// * inherited: other fields inherited from the enclosing fn (if any)
511 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
512 fn_style: ast::FnStyle,
513 fn_style_id: ast::NodeId,
514 fn_sig: &ty::FnSig<'tcx>,
518 inherited: &'a Inherited<'a, 'tcx>)
519 -> FnCtxt<'a, 'tcx> {
521 let err_count_on_creation = tcx.sess.err_count();
523 // First, we have to replace any bound regions in the fn type with free ones.
524 // The free region references will be bound the node_id of the body block.
525 let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
527 let arg_tys = fn_sig.inputs.as_slice();
528 let ret_ty = fn_sig.output;
530 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
535 // Create the function context. This is either derived from scratch or,
536 // in the case of function expressions, based on the outer context.
539 writeback_errors: Cell::new(false),
540 err_count_on_creation: err_count_on_creation,
542 ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)),
547 // Remember return type so that regionck can access it later.
548 let mut fn_sig_tys: Vec<Ty> =
553 if let ty::FnConverging(ret_ty) = ret_ty {
554 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
555 fn_sig_tys.push(ret_ty);
558 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
560 fn_sig_tys.repr(tcx));
562 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
565 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
567 // Add formal parameters.
568 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
569 // Create type variables for each argument.
570 pat_util::pat_bindings(
573 |_bm, pat_id, sp, _path| {
574 let var_ty = visit.assign(sp, pat_id, None);
575 fcx.require_type_is_sized(var_ty, sp,
576 traits::VariableType(pat_id));
579 // Check the pattern.
582 map: pat_id_map(&tcx.def_map, &*input.pat),
584 _match::check_pat(&pcx, &*input.pat, *arg_ty);
587 visit.visit_block(body);
590 check_block_with_expected(&fcx, body, match ret_ty {
591 ty::FnConverging(result_type) => ExpectHasType(result_type),
592 ty::FnDiverging => NoExpectation
595 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
596 fcx.write_ty(input.id, *arg);
602 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
605 check_representable(tcx, span, id, "struct");
606 check_instantiable(tcx, span, id);
608 if ty::lookup_simd(tcx, local_def(id)) {
609 check_simd(tcx, span, id);
613 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
614 debug!("check_item(it.id={}, it.ident={})",
616 ty::item_path_str(ccx.tcx, local_def(it.id)));
617 let _indenter = indenter();
620 ast::ItemStatic(_, _, ref e) |
621 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
622 ast::ItemEnum(ref enum_definition, _) => {
623 check_enum_variants(ccx,
625 enum_definition.variants.as_slice(),
628 ast::ItemFn(ref decl, _, _, _, ref body) => {
629 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
630 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
631 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
633 ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
634 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
636 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
638 match *opt_trait_ref {
639 Some(ref ast_trait_ref) => {
641 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
642 check_impl_items_against_trait(ccx,
646 impl_items.as_slice());
651 for impl_item in impl_items.iter() {
653 ast::MethodImplItem(ref m) => {
654 check_method_body(ccx, &impl_pty.generics, &**m);
656 ast::TypeImplItem(_) => {
657 // Nothing to do here.
663 ast::ItemTrait(_, _, _, ref trait_methods) => {
664 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
665 for trait_method in trait_methods.iter() {
666 match *trait_method {
667 RequiredMethod(..) => {
668 // Nothing to do, since required methods don't have
671 ProvidedMethod(ref m) => {
672 check_method_body(ccx, &trait_def.generics, &**m);
674 TypeTraitItem(_) => {
680 ast::ItemStruct(..) => {
681 check_struct(ccx, it.id, it.span);
683 ast::ItemTy(ref t, ref generics) => {
684 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
685 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
687 ast::ItemForeignMod(ref m) => {
688 if m.abi == abi::RustIntrinsic {
689 for item in m.items.iter() {
690 check_intrinsic_type(ccx, &**item);
693 for item in m.items.iter() {
694 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
695 if !pty.generics.types.is_empty() {
696 span_err!(ccx.tcx.sess, item.span, E0044,
697 "foreign items may not have type parameters");
700 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
701 if fn_decl.variadic && m.abi != abi::C {
702 span_err!(ccx.tcx.sess, item.span, E0045,
703 "variadic function must have C calling convention");
709 _ => {/* nothing to do */ }
713 /// Type checks a method body.
717 /// * `item_generics`: generics defined on the impl/trait that contains
719 /// * `self_bound`: bound for the `Self` type parameter, if any
720 /// * `method`: the method definition
721 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
722 item_generics: &ty::Generics<'tcx>,
723 method: &ast::Method) {
724 debug!("check_method_body(item_generics={}, method.id={})",
725 item_generics.repr(ccx.tcx),
727 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
729 let fty = ty::node_id_to_type(ccx.tcx, method.id);
730 debug!("fty (raw): {}", fty.repr(ccx.tcx));
732 let body_id = method.pe_body().id;
733 let fty = liberate_late_bound_regions(
734 ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value;
735 debug!("fty (liberated): {}", fty.repr(ccx.tcx));
738 &*method.pe_fn_decl(),
745 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
747 ast_trait_ref: &ast::TraitRef,
748 impl_trait_ref: &ty::TraitRef<'tcx>,
749 impl_items: &[ast::ImplItem]) {
750 // Locate trait methods
752 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
754 // Check existing impl methods to see if they are both present in trait
755 // and compatible with trait signature
756 for impl_item in impl_items.iter() {
758 ast::MethodImplItem(ref impl_method) => {
759 let impl_method_def_id = local_def(impl_method.id);
760 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
763 // If this is an impl of a trait method, find the
764 // corresponding method definition in the trait.
765 let opt_trait_method_ty =
768 ti.name() == impl_item_ty.name()
770 match opt_trait_method_ty {
771 Some(trait_method_ty) => {
772 match (trait_method_ty, &impl_item_ty) {
773 (&ty::MethodTraitItem(ref trait_method_ty),
774 &ty::MethodTraitItem(ref impl_method_ty)) => {
775 compare_impl_method(ccx.tcx,
778 impl_method.pe_body().id,
783 // This is span_bug as it should have already been
784 // caught in resolve.
786 .span_bug(impl_method.span,
787 format!("item `{}` is of a \
788 different kind from \
791 impl_item_ty.name()),
792 pprust::path_to_string(
793 &ast_trait_ref.path))
799 // This is span_bug as it should have already been
800 // caught in resolve.
804 "method `{}` is not a member of trait `{}`",
805 token::get_name(impl_item_ty.name()),
806 pprust::path_to_string(
807 &ast_trait_ref.path)).as_slice());
811 ast::TypeImplItem(ref typedef) => {
812 let typedef_def_id = local_def(typedef.id);
813 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
816 // If this is an impl of an associated type, find the
817 // corresponding type definition in the trait.
818 let opt_associated_type =
821 ti.name() == typedef_ty.name()
823 match opt_associated_type {
824 Some(associated_type) => {
825 match (associated_type, &typedef_ty) {
826 (&ty::TypeTraitItem(_),
827 &ty::TypeTraitItem(_)) => {}
829 // This is `span_bug` as it should have
830 // already been caught in resolve.
832 .span_bug(typedef.span,
833 format!("item `{}` is of a \
834 different kind from \
838 pprust::path_to_string(
839 &ast_trait_ref.path))
845 // This is `span_bug` as it should have already been
846 // caught in resolve.
850 "associated type `{}` is not a member of \
852 token::get_name(typedef_ty.name()),
853 pprust::path_to_string(
854 &ast_trait_ref.path)).as_slice());
861 // Check for missing items from trait
862 let provided_methods = ty::provided_trait_methods(tcx,
863 impl_trait_ref.def_id);
864 let mut missing_methods = Vec::new();
865 for trait_item in trait_items.iter() {
867 ty::MethodTraitItem(ref trait_method) => {
869 impl_items.iter().any(|ii| {
871 ast::MethodImplItem(ref m) => {
872 m.pe_ident().name == trait_method.name
874 ast::TypeImplItem(_) => false,
878 provided_methods.iter().any(
879 |m| m.name == trait_method.name);
880 if !is_implemented && !is_provided {
881 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
884 ty::TypeTraitItem(ref associated_type) => {
885 let is_implemented = impl_items.iter().any(|ii| {
887 ast::TypeImplItem(ref typedef) => {
888 typedef.ident.name == associated_type.name
890 ast::MethodImplItem(_) => false,
894 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
900 if !missing_methods.is_empty() {
901 span_err!(tcx.sess, impl_span, E0046,
902 "not all trait items implemented, missing: {}",
903 missing_methods.connect(", "));
907 /// Checks that a method from an impl conforms to the signature of
908 /// the same method as declared in the trait.
912 /// - impl_generics: the generics declared on the impl itself (not the method!)
913 /// - impl_m: type of the method we are checking
914 /// - impl_m_span: span to use for reporting errors
915 /// - impl_m_body_id: id of the method body
916 /// - trait_m: the method in the trait
917 /// - trait_to_impl_substs: the substitutions used on the type of the trait
918 fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
919 impl_m: &ty::Method<'tcx>,
921 impl_m_body_id: ast::NodeId,
922 trait_m: &ty::Method<'tcx>,
923 impl_trait_ref: &ty::TraitRef<'tcx>) {
924 debug!("compare_impl_method(impl_trait_ref={})",
925 impl_trait_ref.repr(tcx));
927 let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
929 // The impl's trait ref may bind late-bound regions from the impl.
930 // Liberate them and assign them the scope of the method body.
932 // An example would be:
934 // impl<'a> Foo<&'a T> for &'a U { ... }
936 // Here, the region parameter `'a` is late-bound, so the
937 // trait reference associated with the impl will be
939 // for<'a> Foo<&'a T>
941 // liberating will convert this into:
945 // where `'A` is the `ReFree` version of `'a`.
946 let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
948 debug!("impl_trait_ref (liberated) = {}",
949 impl_trait_ref.repr(tcx));
951 let infcx = infer::new_infer_ctxt(tcx);
953 let trait_to_impl_substs = &impl_trait_ref.substs;
955 // Try to give more informative error messages about self typing
956 // mismatches. Note that any mismatch will also be detected
957 // below, where we construct a canonical function type that
958 // includes the self parameter as a normal parameter. It's just
959 // that the error messages you get out of this code are a bit more
960 // inscrutable, particularly for cases where one method has no
962 match (&trait_m.explicit_self, &impl_m.explicit_self) {
963 (&ty::StaticExplicitSelfCategory,
964 &ty::StaticExplicitSelfCategory) => {}
965 (&ty::StaticExplicitSelfCategory, _) => {
968 format!("method `{}` has a `{}` declaration in the impl, \
969 but not in the trait",
970 token::get_name(trait_m.name),
971 ppaux::explicit_self_category_to_str(
972 &impl_m.explicit_self)).as_slice());
975 (_, &ty::StaticExplicitSelfCategory) => {
978 format!("method `{}` has a `{}` declaration in the trait, \
979 but not in the impl",
980 token::get_name(trait_m.name),
981 ppaux::explicit_self_category_to_str(
982 &trait_m.explicit_self)).as_slice());
986 // Let the type checker catch other errors below
990 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
991 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
992 if num_impl_m_type_params != num_trait_m_type_params {
993 span_err!(tcx.sess, impl_m_span, E0049,
994 "method `{}` has {} type parameter{} \
995 but its trait declaration has {} type parameter{}",
996 token::get_name(trait_m.name),
997 num_impl_m_type_params,
998 if num_impl_m_type_params == 1 {""} else {"s"},
999 num_trait_m_type_params,
1000 if num_trait_m_type_params == 1 {""} else {"s"});
1004 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
1005 span_err!(tcx.sess, impl_m_span, E0050,
1006 "method `{}` has {} parameter{} \
1007 but the declaration in trait `{}` has {}",
1008 token::get_name(trait_m.name),
1009 impl_m.fty.sig.inputs.len(),
1010 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
1011 ty::item_path_str(tcx, trait_m.def_id),
1012 trait_m.fty.sig.inputs.len());
1016 // This code is best explained by example. Consider a trait:
1018 // trait Trait<'t,T> {
1019 // fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
1024 // impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
1025 // fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
1028 // We wish to decide if those two method types are compatible.
1030 // We start out with trait_to_impl_substs, that maps the trait
1031 // type parameters to impl type parameters. This is taken from the
1032 // impl trait reference:
1034 // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
1036 // We create a mapping `dummy_substs` that maps from the impl type
1037 // parameters to fresh types and regions. For type parameters,
1038 // this is the identity transform, but we could as well use any
1039 // skolemized types. For regions, we convert from bound to free
1040 // regions (Note: but only early-bound regions, i.e., those
1041 // declared on the impl or used in type parameter bounds).
1043 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1045 // Now we can apply skol_substs to the type of the impl method
1046 // to yield a new function type in terms of our fresh, skolemized
1049 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1051 // We now want to extract and substitute the type of the *trait*
1052 // method and compare it. To do so, we must create a compound
1053 // substitution by combining trait_to_impl_substs and
1054 // impl_to_skol_substs, and also adding a mapping for the method
1055 // type parameters. We extend the mapping to also include
1056 // the method parameters.
1058 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1060 // Applying this to the trait method type yields:
1062 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1064 // This type is also the same but the name of the bound region ('a
1065 // vs 'b). However, the normal subtyping rules on fn types handle
1066 // this kind of equivalency just fine.
1068 // Create mapping from impl to skolemized.
1070 impl_m.generics.types.map(
1071 |d| ty::mk_param_from_def(tcx, d));
1073 impl_m.generics.regions.map(
1074 |l| ty::free_region_from_def(impl_m_body_id, l));
1075 let impl_to_skol_substs =
1076 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1078 // Create mapping from trait to skolemized.
1079 let trait_to_skol_substs =
1080 trait_to_impl_substs
1081 .subst(tcx, &impl_to_skol_substs)
1082 .with_method(skol_tps.get_slice(subst::FnSpace).to_vec(),
1083 skol_regions.get_slice(subst::FnSpace).to_vec());
1085 // Check region bounds.
1086 if !check_region_bounds_on_impl_method(tcx,
1092 &trait_to_skol_substs,
1093 &impl_to_skol_substs) {
1097 // Check bounds. Note that the bounds from the impl may reference
1098 // late-bound regions declared on the impl, so liberate those.
1099 // This requires two artificial binding scopes -- one for the impl,
1100 // and one for the method.
1102 // An example would be:
1104 // trait Foo<T> { fn method<U:Bound<T>>() { ... } }
1106 // impl<'a> Foo<&'a T> for &'a U {
1107 // fn method<U:Bound<&'a T>>() { ... }
1110 // Here, the region parameter `'a` is late-bound, so in the bound
1111 // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
1112 // depth of 3 (it is nested within 3 binders: the impl, method,
1113 // and trait-ref itself). So when we do the liberation, we have
1114 // two introduce two `ty::bind` scopes, one for the impl and one
1117 // The only late-bounded regions that can possibly appear here are
1118 // from the impl, not the method. This is because region
1119 // parameters declared on the method which appear in a type bound
1120 // would be early bound. On the trait side, there can be no
1121 // late-bound lifetimes because trait definitions do not introduce
1122 // a late region binder.
1124 trait_m.generics.types.get_slice(subst::FnSpace).iter()
1125 .map(|trait_param_def| &trait_param_def.bounds);
1127 impl_m.generics.types.get_slice(subst::FnSpace).iter()
1128 .map(|impl_param_def|
1129 liberate_late_bound_regions(
1132 &ty::bind(ty::bind(impl_param_def.bounds.clone()))).value.value);
1133 for (i, (trait_param_bounds, impl_param_bounds)) in
1134 trait_bounds.zip(impl_bounds).enumerate()
1136 // Check that the impl does not require any builtin-bounds
1137 // that the trait does not guarantee:
1139 impl_param_bounds.builtin_bounds -
1140 trait_param_bounds.builtin_bounds;
1141 if !extra_bounds.is_empty() {
1142 span_err!(tcx.sess, impl_m_span, E0051,
1143 "in method `{}`, type parameter {} requires `{}`, \
1144 which is not required by the corresponding type parameter \
1145 in the trait declaration",
1146 token::get_name(trait_m.name),
1148 extra_bounds.user_string(tcx));
1152 // Check that the trait bounds of the trait imply the bounds of its
1155 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1156 // traits, but I doubt that'll be wanted often, so meh.
1157 for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
1158 debug!("compare_impl_method(): impl-trait-bound subst");
1159 let impl_trait_bound =
1160 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1162 // There may be late-bound regions from the impl in the
1163 // impl's bound, so "liberate" those. Note that the
1164 // trait_to_skol_substs is derived from the impl's
1165 // trait-ref, and the late-bound regions appearing there
1166 // have already been liberated, so the result should match
1169 let found_match_in_trait =
1170 trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
1171 debug!("compare_impl_method(): trait-bound subst");
1173 trait_bound.subst(tcx, &trait_to_skol_substs);
1174 let infcx = infer::new_infer_ctxt(tcx);
1175 infer::mk_sub_trait_refs(&infcx,
1177 infer::Misc(impl_m_span),
1179 impl_trait_bound.clone()).is_ok()
1182 if !found_match_in_trait {
1183 span_err!(tcx.sess, impl_m_span, E0052,
1184 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1185 required by the corresponding type parameter in the trait declaration",
1186 token::get_name(trait_m.name),
1188 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1193 // Compute skolemized form of impl and trait method tys. Note
1194 // that we must liberate the late-bound regions from the impl.
1195 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1196 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1197 let impl_fty = liberate_late_bound_regions(
1198 tcx, impl_m_body_scope, &ty::bind(impl_fty)).value;
1199 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1200 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1202 // Check the impl method type IM is a subtype of the trait method
1203 // type TM. To see why this makes sense, think of a vtable. The
1204 // expected type of the function pointers in the vtable is the
1205 // type TM of the trait method. The actual type will be the type
1206 // IM of the impl method. Because we know that IM <: TM, that
1207 // means that anywhere a TM is expected, a IM will do instead. In
1208 // other words, anyone expecting to call a method with the type
1209 // from the trait, can safely call a method with the type from the
1211 debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
1213 trait_fty.repr(tcx));
1214 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1215 impl_fty, trait_fty) {
1218 span_err!(tcx.sess, impl_m_span, E0053,
1219 "method `{}` has an incompatible type for trait: {}",
1220 token::get_name(trait_m.name),
1221 ty::type_err_to_str(tcx, terr));
1222 ty::note_and_explain_type_err(tcx, terr);
1226 // Finally, resolve all regions. This catches wily misuses of lifetime
1228 infcx.resolve_regions_and_report_errors();
1230 /// Check that region bounds on impl method are the same as those on the trait. In principle,
1231 /// it could be ok for there to be fewer region bounds on the impl method, but this leads to an
1232 /// annoying corner case that is painful to handle (described below), so for now we can just
1235 /// Example (see `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1239 /// fn method1<'b>();
1240 /// fn method2<'b:'a>();
1243 /// impl<'a> Foo<'a> for ... {
1244 /// fn method1<'b:'a>() { .. case 1, definitely bad .. }
1245 /// fn method2<'b>() { .. case 2, could be ok .. }
1249 /// The "definitely bad" case is case #1. Here, the impl adds an extra constraint not present
1252 /// The "maybe bad" case is case #2. Here, the impl adds an extra constraint not present in the
1253 /// trait. We could in principle allow this, but it interacts in a complex way with early/late
1254 /// bound resolution of lifetimes. Basically the presence or absence of a lifetime bound
1255 /// affects whether the lifetime is early/late bound, and right now the code breaks if the
1256 /// trait has an early bound lifetime parameter and the method does not.
1257 fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
1259 impl_m: &ty::Method<'tcx>,
1260 impl_m_body_scope: CodeExtent,
1261 trait_generics: &ty::Generics<'tcx>,
1262 impl_generics: &ty::Generics<'tcx>,
1263 trait_to_skol_substs: &Substs<'tcx>,
1264 impl_to_skol_substs: &Substs<'tcx>)
1268 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1269 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1271 debug!("check_region_bounds_on_impl_method: \
1274 trait_to_skol_substs={} \
1275 impl_to_skol_substs={}",
1276 trait_generics.repr(tcx),
1277 impl_generics.repr(tcx),
1278 trait_to_skol_substs.repr(tcx),
1279 impl_to_skol_substs.repr(tcx));
1281 // Must have same number of early-bound lifetime parameters.
1282 // Unfortunately, if the user screws up the bounds, then this
1283 // will change classification between early and late. E.g.,
1284 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1285 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1286 // in trait but 0 in the impl. But if we report "expected 2
1287 // but found 0" it's confusing, because it looks like there
1288 // are zero. Since I don't quite know how to phrase things at
1289 // the moment, give a kind of vague error message.
1290 if trait_params.len() != impl_params.len() {
1293 format!("lifetime parameters or bounds on method `{}` do \
1294 not match the trait declaration",
1295 token::get_name(impl_m.name)).as_slice());
1299 // Each parameter `'a:'b+'c+'d` in trait should have the same
1300 // set of bounds in the impl, after subst.
1301 for (trait_param, impl_param) in
1302 trait_params.iter().zip(
1306 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1308 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1310 // The bounds may reference late-bound regions from the
1311 // impl declaration. In that case, we want to replace
1312 // those with the liberated variety so as to match the
1313 // versions appearing in the `trait_to_skol_substs`.
1314 // There are two-levels of binder to be aware of: the
1315 // impl, and the method.
1317 ty::liberate_late_bound_regions(
1318 tcx, impl_m_body_scope, &ty::bind(ty::bind(impl_bounds))).value.value;
1320 debug!("check_region_bounds_on_impl_method: \
1325 trait_param.repr(tcx),
1326 impl_param.repr(tcx),
1327 trait_bounds.repr(tcx),
1328 impl_bounds.repr(tcx));
1330 // Collect the set of bounds present in trait but not in
1332 let missing: Vec<ty::Region> =
1334 .filter(|&b| !impl_bounds.contains(b))
1338 // Collect set present in impl but not in trait.
1339 let extra: Vec<ty::Region> =
1341 .filter(|&b| !trait_bounds.contains(b))
1345 debug!("missing={} extra={}",
1346 missing.repr(tcx), extra.repr(tcx));
1348 let err = if missing.len() != 0 || extra.len() != 0 {
1352 "the lifetime parameter `{}` declared in the impl \
1353 has a distinct set of bounds \
1354 from its counterpart `{}` \
1355 declared in the trait",
1356 impl_param.name.user_string(tcx),
1357 trait_param.name.user_string(tcx)).as_slice());
1363 if missing.len() != 0 {
1366 format!("the impl is missing the following bounds: `{}`",
1367 missing.user_string(tcx)).as_slice());
1370 if extra.len() != 0 {
1373 format!("the impl has the following extra bounds: `{}`",
1374 extra.user_string(tcx)).as_slice());
1386 fn check_cast(fcx: &FnCtxt,
1387 cast_expr: &ast::Expr,
1390 let id = cast_expr.id;
1391 let span = cast_expr.span;
1393 // Find the type of `e`. Supply hints based on the type we are casting to,
1395 let t_1 = fcx.to_ty(t);
1396 let t_1 = structurally_resolved_type(fcx, span, t_1);
1398 if ty::type_is_scalar(t_1) {
1399 // Supply the type as a hint so as to influence integer
1400 // literals and other things that might care.
1401 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1))
1406 let t_e = fcx.expr_ty(e);
1408 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1409 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1411 if ty::type_is_error(t_e) {
1412 fcx.write_error(id);
1416 if !ty::type_is_sized(fcx.tcx(), t_1) {
1417 let tstr = fcx.infcx().ty_to_string(t_1);
1418 fcx.type_error_message(span, |actual| {
1419 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1422 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1423 let mtstr = match mt {
1424 ast::MutMutable => "mut ",
1425 ast::MutImmutable => ""
1427 if ty::type_is_trait(t_1) {
1428 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1430 span_help!(fcx.tcx().sess, span,
1431 "consider using an implicit coercion to `&{}{}` instead",
1435 ty::ty_uniq(..) => {
1436 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1439 span_help!(fcx.tcx().sess, e.span,
1440 "consider using a box or reference as appropriate");
1443 fcx.write_error(id);
1447 if ty::type_is_trait(t_1) {
1448 // This will be looked up later on.
1449 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1450 fcx.write_ty(id, t_1);
1454 let t_1 = structurally_resolved_type(fcx, span, t_1);
1455 let t_e = structurally_resolved_type(fcx, span, t_e);
1457 if ty::type_is_nil(t_e) {
1458 fcx.type_error_message(span, |actual| {
1459 format!("cast from nil: `{}` as `{}`",
1461 fcx.infcx().ty_to_string(t_1))
1463 } else if ty::type_is_nil(t_1) {
1464 fcx.type_error_message(span, |actual| {
1465 format!("cast to nil: `{}` as `{}`",
1467 fcx.infcx().ty_to_string(t_1))
1471 let t_1_is_scalar = ty::type_is_scalar(t_1);
1472 let t_1_is_char = ty::type_is_char(t_1);
1473 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1474 let t_1_is_float = ty::type_is_floating_point(t_1);
1476 // casts to scalars other than `char` and `bare fn` are trivial
1477 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1478 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1479 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1480 fcx.type_error_message(span, |actual| {
1481 format!("illegal cast; cast through an \
1482 integer first: `{}` as `{}`",
1484 fcx.infcx().ty_to_string(t_1))
1487 // casts from C-like enums are allowed
1488 } else if t_1_is_char {
1489 let t_e = fcx.infcx().shallow_resolve(t_e);
1490 if t_e.sty != ty::ty_uint(ast::TyU8) {
1491 fcx.type_error_message(span, |actual| {
1492 format!("only `u8` can be cast as \
1493 `char`, not `{}`", actual)
1496 } else if t_1.sty == ty::ty_bool {
1497 span_err!(fcx.tcx().sess, span, E0054,
1498 "cannot cast as `bool`, compare with zero instead");
1499 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1500 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1501 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1503 ty::ty_vec(_, Some(_)) => {}
1506 if ty::type_needs_infer(t2) {
1507 // This prevents this special case from going off when casting
1508 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1513 let el = ty::sequence_element_type(fcx.tcx(), t1);
1514 infer::mk_eqty(fcx.infcx(),
1521 // Due to the limitations of LLVM global constants,
1522 // region pointers end up pointing at copies of
1523 // vector elements instead of the original values.
1524 // To allow unsafe pointers to work correctly, we
1525 // need to special-case obtaining an unsafe pointer
1526 // from a region pointer to a vector.
1528 /* this cast is only allowed from &[T, ..n] to *T or
1530 match (&t_e.sty, &t_1.sty) {
1531 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1532 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1533 if types_compatible(fcx, e.span, mt1, mt2) => {
1534 /* this case is allowed */
1537 demand::coerce(fcx, e.span, t_1, &*e);
1540 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1542 If more type combinations should be supported than are
1543 supported here, then file an enhancement issue and
1544 record the issue number in this comment.
1546 fcx.type_error_message(span, |actual| {
1547 format!("non-scalar cast: `{}` as `{}`",
1549 fcx.infcx().ty_to_string(t_1))
1551 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1552 fcx.type_error_message(span, |actual| {
1553 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1556 fcx.infcx().ty_to_string(t_1))
1560 fcx.write_ty(id, t_1);
1563 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1564 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1566 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
1567 ty::lookup_item_type(self.tcx(), id)
1570 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1571 ty::lookup_trait_def(self.tcx(), id)
1574 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1575 self.infcx().next_ty_var()
1578 fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId)
1583 fn associated_type_binding(&self,
1585 _: Option<Ty<'tcx>>,
1589 self.tcx().sess.span_err(span, "unsupported associated type binding");
1594 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1595 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1597 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
1601 pub fn sess(&self) -> &Session {
1605 pub fn err_count_since_creation(&self) -> uint {
1606 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1610 impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
1611 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1612 Some(self.next_region_var(infer::MiscVariable(span)))
1615 fn anon_regions(&self, span: Span, count: uint)
1616 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1617 Ok(Vec::from_fn(count, |_| {
1618 self.next_region_var(infer::MiscVariable(span))
1623 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1624 pub fn tag(&self) -> String {
1625 format!("{}", self as *const FnCtxt)
1628 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1629 match self.inh.locals.borrow().get(&nid) {
1632 self.tcx().sess.span_bug(
1634 format!("no type for local variable {}",
1640 pub fn default_diverging_type_variables_to_nil(&self) {
1641 for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1642 if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
1643 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1649 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1650 debug!("write_ty({}, {}) in fcx {}",
1651 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1652 self.inh.node_types.borrow_mut().insert(node_id, ty);
1655 pub fn write_object_cast(&self,
1657 trait_ref: Rc<ty::TraitRef<'tcx>>) {
1658 debug!("write_object_cast key={} trait_ref={}",
1659 key, trait_ref.repr(self.tcx()));
1660 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1663 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1664 if !substs.substs.is_noop() {
1665 debug!("write_substs({}, {}) in fcx {}",
1667 substs.repr(self.tcx()),
1670 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1674 pub fn write_autoderef_adjustment(&self,
1675 node_id: ast::NodeId,
1678 if derefs == 0 { return; }
1679 self.write_adjustment(
1682 ty::AdjustDerefRef(ty::AutoDerefRef {
1688 pub fn write_adjustment(&self,
1689 node_id: ast::NodeId,
1691 adj: ty::AutoAdjustment<'tcx>) {
1692 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1694 if adj.is_identity() {
1698 // Careful: adjustments can imply trait obligations if we are
1699 // casting from a concrete type to an object type. I think
1700 // it'd probably be nicer to move the logic that creates the
1701 // obligation into the code that creates the adjustment, but
1702 // that's a bit awkward, so instead we go digging and pull the
1703 // obligation out here.
1704 self.register_adjustment_obligations(span, &adj);
1705 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1708 fn register_adjustment_obligations(&self,
1710 adj: &ty::AutoAdjustment<'tcx>) {
1712 ty::AdjustAddEnv(..) => { }
1713 ty::AdjustDerefRef(ref d_r) => {
1716 self.register_autoref_obligations(span, a_r);
1724 fn register_autoref_obligations(&self,
1726 autoref: &ty::AutoRef<'tcx>) {
1728 ty::AutoUnsize(ref unsize) => {
1729 self.register_unsize_obligations(span, unsize);
1731 ty::AutoPtr(_, _, None) |
1732 ty::AutoUnsafe(_, None) => {
1734 ty::AutoPtr(_, _, Some(ref a_r)) |
1735 ty::AutoUnsafe(_, Some(ref a_r)) => {
1736 self.register_autoref_obligations(span, &**a_r)
1738 ty::AutoUnsizeUniq(ref unsize) => {
1739 self.register_unsize_obligations(span, unsize);
1744 fn register_unsize_obligations(&self,
1746 unsize: &ty::UnsizeKind<'tcx>) {
1747 debug!("register_unsize_obligations: unsize={}", unsize);
1750 ty::UnsizeLength(..) => {}
1751 ty::UnsizeStruct(ref u, _) => {
1752 self.register_unsize_obligations(span, &**u)
1754 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1755 vtable::check_object_safety(self.tcx(), &ty_trait.principal, span);
1756 // If the type is `Foo+'a`, ensures that the type
1757 // being cast to `Foo+'a` implements `Foo`:
1758 vtable::register_object_cast_obligations(self,
1763 // If the type is `Foo+'a`, ensures that the type
1764 // being cast to `Foo+'a` outlives `'a`:
1765 let origin = infer::RelateObjectBound(span);
1766 self.register_region_obligation(origin, self_ty, ty_trait.bounds.region_bound);
1771 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1772 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1773 /// Registers any trait obligations specified on `def_id` at the same time.
1775 /// Note that function is only intended to be used with types (notably, not impls). This is
1776 /// because it doesn't do any instantiation of late-bound regions.
1777 pub fn instantiate_type(&self,
1780 -> TypeAndSubsts<'tcx>
1783 ty::lookup_item_type(self.tcx(), def_id);
1785 self.infcx().fresh_substs_for_generics(
1787 &polytype.generics);
1789 polytype.generics.to_bounds(self.tcx(), &substs);
1790 self.add_obligations_for_parameters(
1791 traits::ObligationCause::new(
1793 traits::ItemObligation(def_id)),
1797 polytype.ty.subst(self.tcx(), &substs);
1805 pub fn write_nil(&self, node_id: ast::NodeId) {
1806 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1808 pub fn write_error(&self, node_id: ast::NodeId) {
1809 self.write_ty(node_id, ty::mk_err());
1812 pub fn require_type_meets(&self,
1815 code: traits::ObligationCauseCode<'tcx>,
1816 bound: ty::BuiltinBound)
1818 let obligation = traits::obligation_for_builtin_bound(
1820 traits::ObligationCause::new(span, code),
1823 if let Ok(ob) = obligation {
1824 self.register_obligation(ob);
1828 pub fn require_type_is_sized(&self,
1831 code: traits::ObligationCauseCode<'tcx>)
1833 self.require_type_meets(ty, span, code, ty::BoundSized);
1836 pub fn require_expr_have_sized_type(&self,
1838 code: traits::ObligationCauseCode<'tcx>)
1840 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1843 pub fn register_obligation(&self,
1844 obligation: traits::Obligation<'tcx>)
1846 debug!("register_obligation({})",
1847 obligation.repr(self.tcx()));
1849 self.inh.fulfillment_cx
1851 .register_obligation(self.tcx(), obligation);
1854 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1855 let t = ast_ty_to_ty(self, self.infcx(), ast_t);
1857 let mut bounds_checker = wf::BoundsChecker::new(self,
1859 CodeExtent::from_node_id(self.body_id),
1861 bounds_checker.check_ty(t);
1866 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1867 pat.repr(self.tcx())
1870 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1871 match self.inh.node_types.borrow().get(&ex.id) {
1874 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1875 self.tag()).as_slice());
1880 /// Apply `adjustment` to the type of `expr`
1881 pub fn adjust_expr_ty(&self,
1883 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1886 let raw_ty = self.expr_ty(expr);
1887 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1888 ty::adjust_ty(self.tcx(),
1893 |method_call| self.inh.method_map.borrow()
1895 .map(|method| method.ty))
1898 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1899 match self.inh.node_types.borrow().get(&id) {
1902 self.tcx().sess.bug(
1903 format!("no type for node {}: {} in fcx {}",
1904 id, self.tcx().map.node_to_string(id),
1905 self.tag()).as_slice());
1910 pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts<'tcx>>> {
1911 self.inh.item_substs.borrow()
1914 pub fn opt_node_ty_substs(&self,
1916 f: |&ty::ItemSubsts<'tcx>|) {
1917 match self.inh.item_substs.borrow().get(&id) {
1923 pub fn mk_subty(&self,
1924 a_is_expected: bool,
1925 origin: infer::TypeOrigin,
1928 -> Result<(), ty::type_err<'tcx>> {
1929 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1932 pub fn mk_assignty(&self,
1936 -> Result<(), ty::type_err<'tcx>> {
1937 match infer::mk_coercety(self.infcx(),
1939 infer::ExprAssignable(expr.span),
1943 Err(ref e) => Err((*e)),
1944 Ok(Some(adjustment)) => {
1945 self.write_adjustment(expr.id, expr.span, adjustment);
1951 pub fn mk_eqty(&self,
1952 a_is_expected: bool,
1953 origin: infer::TypeOrigin,
1956 -> Result<(), ty::type_err<'tcx>> {
1957 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1960 pub fn mk_subr(&self,
1961 origin: infer::SubregionOrigin<'tcx>,
1964 infer::mk_subr(self.infcx(), origin, sub, sup)
1967 pub fn type_error_message(&self,
1969 mk_msg: |String| -> String,
1970 actual_ty: Ty<'tcx>,
1971 err: Option<&ty::type_err<'tcx>>) {
1972 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1975 pub fn report_mismatched_types(&self,
1979 err: &ty::type_err<'tcx>) {
1980 self.infcx().report_mismatched_types(sp, e, a, err)
1983 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1984 /// outlive the region `r`.
1985 pub fn register_region_obligation(&self,
1986 origin: infer::SubregionOrigin<'tcx>,
1990 let mut region_obligations = self.inh.region_obligations.borrow_mut();
1991 let region_obligation = RegionObligation { sub_region: r,
1995 match region_obligations.entry(self.body_id) {
1996 Vacant(entry) => { entry.set(vec![region_obligation]); },
1997 Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
2001 pub fn add_default_region_param_bounds(&self,
2002 substs: &Substs<'tcx>,
2005 for &ty in substs.types.iter() {
2006 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
2007 let origin = infer::RelateDefaultParamBound(expr.span, ty);
2008 self.register_region_obligation(origin, ty, default_bound);
2012 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
2013 /// type/region parameter was instantiated (`substs`), creates and registers suitable
2014 /// trait/region obligations.
2016 /// For example, if there is a function:
2019 /// fn foo<'a,T:'a>(...)
2022 /// and a reference:
2028 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
2029 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
2030 pub fn add_obligations_for_parameters(&self,
2031 cause: traits::ObligationCause<'tcx>,
2032 substs: &Substs<'tcx>,
2033 generic_bounds: &ty::GenericBounds<'tcx>)
2035 assert!(!generic_bounds.has_escaping_regions());
2037 debug!("add_obligations_for_parameters(substs={}, generic_bounds={})",
2038 substs.repr(self.tcx()),
2039 generic_bounds.repr(self.tcx()));
2041 self.add_trait_obligations_for_generics(cause, substs, generic_bounds);
2042 self.add_region_obligations_for_generics(cause, substs, generic_bounds);
2045 fn add_trait_obligations_for_generics(&self,
2046 cause: traits::ObligationCause<'tcx>,
2047 substs: &Substs<'tcx>,
2048 generic_bounds: &ty::GenericBounds<'tcx>) {
2049 assert!(!generic_bounds.has_escaping_regions());
2050 assert!(!substs.has_regions_escaping_depth(0));
2053 traits::obligations_for_generics(self.tcx(),
2057 obligations.map_move(|o| self.register_obligation(o));
2060 fn add_region_obligations_for_generics(&self,
2061 cause: traits::ObligationCause<'tcx>,
2062 substs: &Substs<'tcx>,
2063 generic_bounds: &ty::GenericBounds<'tcx>)
2065 assert!(!generic_bounds.has_escaping_regions());
2066 assert_eq!(generic_bounds.types.iter().len(), substs.types.iter().len());
2068 for (type_bounds, &type_param) in
2069 generic_bounds.types.iter().zip(
2070 substs.types.iter())
2072 self.add_region_obligations_for_type_parameter(
2073 cause.span, type_bounds, type_param);
2076 assert_eq!(generic_bounds.regions.iter().len(),
2077 substs.regions().iter().len());
2078 for (region_bounds, ®ion_param) in
2079 generic_bounds.regions.iter().zip(
2080 substs.regions().iter())
2082 self.add_region_obligations_for_region_parameter(
2083 cause.span, region_bounds.as_slice(), region_param);
2087 fn add_region_obligations_for_type_parameter(&self,
2089 param_bound: &ty::ParamBounds<'tcx>,
2092 // For each declared region bound `T:r`, `T` must outlive `r`.
2094 ty::required_region_bounds(
2096 param_bound.region_bounds.as_slice(),
2097 param_bound.builtin_bounds,
2098 param_bound.trait_bounds.as_slice());
2099 for &r in region_bounds.iter() {
2100 let origin = infer::RelateParamBound(span, ty);
2101 self.register_region_obligation(origin, ty, r);
2105 fn add_region_obligations_for_region_parameter(&self,
2107 region_bounds: &[ty::Region],
2108 region_param: ty::Region)
2110 for &b in region_bounds.iter() {
2111 // For each bound `region:b`, `b <= region` must hold
2112 // (i.e., `region` must outlive `b`).
2113 let origin = infer::RelateRegionParamBound(span);
2114 self.mk_subr(origin, b, region_param);
2120 pub enum LvaluePreference {
2125 impl Copy for LvaluePreference {}
2127 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
2128 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
2130 /// Note: this method does not modify the adjustments table. The caller is responsible for
2131 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
2132 pub fn autoderef<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
2134 expr_id: Option<ast::NodeId>,
2135 mut lvalue_pref: LvaluePreference,
2136 should_stop: |Ty<'tcx>, uint| -> Option<T>)
2137 -> (Ty<'tcx>, uint, Option<T>) {
2138 let mut t = base_ty;
2139 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
2140 let resolved_t = structurally_resolved_type(fcx, sp, t);
2142 if ty::type_is_error(resolved_t) {
2143 return (resolved_t, autoderefs, None);
2146 match should_stop(resolved_t, autoderefs) {
2147 Some(x) => return (resolved_t, autoderefs, Some(x)),
2151 // Otherwise, deref if type is derefable:
2152 let mt = match ty::deref(resolved_t, false) {
2153 Some(mt) => Some(mt),
2155 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
2156 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2162 if mt.mutbl == ast::MutImmutable {
2163 lvalue_pref = NoPreference;
2166 None => return (resolved_t, autoderefs, None)
2170 // We've reached the recursion limit, error gracefully.
2171 span_err!(fcx.tcx().sess, sp, E0055,
2172 "reached the recursion limit while auto-dereferencing {}",
2173 base_ty.repr(fcx.tcx()));
2174 (ty::mk_err(), 0, None)
2177 /// Attempts to resolve a call expression as an overloaded call.
2178 fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2179 call_expression: &ast::Expr,
2181 callee_type: Ty<'tcx>,
2182 args: &[&P<ast::Expr>])
2184 // Bail out if the callee is a bare function or a closure. We check those
2186 match *structure_of(fcx, callee.span, callee_type) {
2187 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
2191 // Try the options that are least restrictive on the caller first.
2192 for &(maybe_function_trait, method_name) in [
2193 (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
2194 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2195 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2197 let function_trait = match maybe_function_trait {
2199 Some(function_trait) => function_trait,
2202 match method::lookup_in_trait(fcx,
2203 call_expression.span,
2210 Some(method_callee) => method_callee,
2212 let method_call = MethodCall::expr(call_expression.id);
2213 let output_type = check_method_argument_types(fcx,
2214 call_expression.span,
2220 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2221 write_call(fcx, call_expression, output_type);
2223 if !fcx.tcx().sess.features.borrow().unboxed_closures {
2224 span_err!(fcx.tcx().sess, call_expression.span, E0056,
2225 "overloaded calls are experimental");
2226 span_help!(fcx.tcx().sess, call_expression.span,
2227 "add `#![feature(unboxed_closures)]` to \
2228 the crate attributes to enable");
2237 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2239 method_call: Option<MethodCall>,
2240 base_expr: Option<&ast::Expr>,
2242 lvalue_pref: LvaluePreference)
2243 -> Option<ty::mt<'tcx>>
2245 // Try DerefMut first, if preferred.
2246 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2247 (PreferMutLvalue, Some(trait_did)) => {
2248 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2249 token::intern("deref_mut"), trait_did,
2255 // Otherwise, fall back to Deref.
2256 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2257 (None, Some(trait_did)) => {
2258 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2259 token::intern("deref"), trait_did,
2262 (method, _) => method
2265 make_overloaded_lvalue_return_type(fcx, method_call, method)
2268 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2269 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2270 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2271 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2272 method_call: Option<MethodCall>,
2273 method: Option<MethodCallee<'tcx>>)
2274 -> Option<ty::mt<'tcx>>
2278 let ref_ty = ty::ty_fn_ret(method.ty);
2280 Some(method_call) => {
2281 fcx.inh.method_map.borrow_mut().insert(method_call,
2287 ty::FnConverging(ref_ty) => {
2288 ty::deref(ref_ty, true)
2290 ty::FnDiverging => {
2291 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2299 fn autoderef_for_index<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>,
2300 base_expr: &ast::Expr,
2302 lvalue_pref: LvaluePreference,
2303 step: |Ty<'tcx>, ty::AutoDerefRef<'tcx>| -> Option<T>)
2306 // FIXME(#18741) -- this is almost but not quite the same as the
2307 // autoderef that normal method probing does. They could likely be
2310 let (ty, autoderefs, final_mt) =
2311 autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
2312 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2313 step(adj_ty, autoderefref)
2316 if final_mt.is_some() {
2320 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2321 // do a final unsized coercion to yield [T].
2323 ty::ty_vec(element_ty, Some(n)) => {
2324 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2325 let autoderefref = ty::AutoDerefRef {
2326 autoderefs: autoderefs,
2327 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2329 step(adjusted_ty, autoderefref)
2337 /// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant
2338 /// method info and returns the result type (else None).
2339 fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2340 method_call: MethodCall,
2342 base_expr: &ast::Expr,
2344 start_expr: &Option<P<ast::Expr>>,
2345 end_expr: &Option<P<ast::Expr>>,
2346 mutbl: ast::Mutability)
2347 -> Option<Ty<'tcx>> // return type is result of slice
2349 let lvalue_pref = match mutbl {
2350 ast::MutMutable => PreferMutLvalue,
2351 ast::MutImmutable => NoPreference
2355 autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| {
2356 try_overloaded_slice_step(fcx, method_call, expr, base_expr,
2357 adjusted_ty, autoderefref, mutbl,
2358 start_expr, end_expr)
2361 // Regardless of whether the lookup succeeds, check the method arguments
2362 // so that we have *some* type for each argument.
2363 let method_ty_or_err = opt_method_ty.unwrap_or(ty::mk_err());
2365 let mut args = vec![];
2366 start_expr.as_ref().map(|x| args.push(x));
2367 end_expr.as_ref().map(|x| args.push(x));
2369 check_method_argument_types(fcx,
2375 DontTupleArguments);
2377 opt_method_ty.map(|method_ty| {
2378 let result_ty = ty::ty_fn_ret(method_ty);
2380 ty::FnConverging(result_ty) => result_ty,
2381 ty::FnDiverging => {
2382 fcx.tcx().sess.span_bug(expr.span,
2383 "slice trait does not define a `!` return")
2389 /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one,
2390 /// installs method info and returns type of method (else None).
2391 fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2392 method_call: MethodCall,
2394 base_expr: &ast::Expr,
2395 base_ty: Ty<'tcx>, // autoderef'd type
2396 autoderefref: ty::AutoDerefRef<'tcx>,
2397 mutbl: ast::Mutability,
2398 start_expr: &Option<P<ast::Expr>>,
2399 end_expr: &Option<P<ast::Expr>>)
2400 // result type is type of method being called
2403 let method = if mutbl == ast::MutMutable {
2404 // Try `SliceMut` first, if preferred.
2405 match fcx.tcx().lang_items.slice_mut_trait() {
2406 Some(trait_did) => {
2407 let method_name = match (start_expr, end_expr) {
2408 (&Some(_), &Some(_)) => "slice_or_fail_mut",
2409 (&Some(_), &None) => "slice_from_or_fail_mut",
2410 (&None, &Some(_)) => "slice_to_or_fail_mut",
2411 (&None, &None) => "as_mut_slice_",
2414 method::lookup_in_trait_adjusted(fcx,
2417 token::intern(method_name),
2426 // Otherwise, fall back to `Slice`.
2427 // FIXME(#17293) this will not coerce base_expr, so we miss the Slice
2428 // trait for `&mut [T]`.
2429 match fcx.tcx().lang_items.slice_trait() {
2430 Some(trait_did) => {
2431 let method_name = match (start_expr, end_expr) {
2432 (&Some(_), &Some(_)) => "slice_or_fail",
2433 (&Some(_), &None) => "slice_from_or_fail",
2434 (&None, &Some(_)) => "slice_to_or_fail",
2435 (&None, &None) => "as_slice_",
2438 method::lookup_in_trait_adjusted(fcx,
2441 token::intern(method_name),
2451 // If some lookup succeeded, install method in table
2452 method.map(|method| {
2454 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2459 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2460 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2461 /// This loop implements one step in that search; the autoderef loop is implemented by
2462 /// `autoderef_for_index`.
2463 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2464 method_call: MethodCall,
2466 base_expr: &ast::Expr,
2467 adjusted_ty: Ty<'tcx>,
2468 adjustment: ty::AutoDerefRef<'tcx>,
2469 lvalue_pref: LvaluePreference)
2470 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2472 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={})",
2473 expr.repr(fcx.tcx()),
2474 base_expr.repr(fcx.tcx()),
2475 adjusted_ty.repr(fcx.tcx()),
2478 // Try built-in indexing first.
2479 match ty::index(adjusted_ty) {
2481 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2482 return Some((ty::mk_uint(), ty));
2488 let input_ty = fcx.infcx().next_ty_var();
2489 let return_ty = fcx.infcx().next_ty_var();
2491 // Try `IndexMut` first, if preferred.
2492 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2493 (PreferMutLvalue, Some(trait_did)) => {
2494 method::lookup_in_trait_adjusted(fcx,
2497 token::intern("index_mut"),
2501 Some(vec![input_ty, return_ty]))
2506 // Otherwise, fall back to `Index`.
2507 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2508 (None, Some(trait_did)) => {
2509 method::lookup_in_trait_adjusted(fcx,
2512 token::intern("index"),
2516 Some(vec![input_ty, return_ty]))
2518 (method, _) => method,
2521 // If some lookup succeeds, write callee into table and extract index/element
2522 // type from the method signature.
2523 // If some lookup succeeded, install method in table
2524 method.map(|method| {
2525 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method));
2526 (input_ty, return_ty)
2530 /// Given the head of a `for` expression, looks up the `next` method in the
2531 /// `Iterator` trait. Panics if the expression does not implement `next`.
2533 /// The return type of this function represents the concrete element type
2534 /// `A` in the type `Iterator<A>` that the method returns.
2535 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2536 iterator_expr: &ast::Expr,
2537 loop_id: ast::NodeId)
2539 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2540 Ok(trait_did) => trait_did,
2541 Err(ref err_string) => {
2542 fcx.tcx().sess.span_err(iterator_expr.span,
2543 err_string.as_slice());
2548 let expr_type = fcx.expr_ty(&*iterator_expr);
2549 let method = method::lookup_in_trait(fcx,
2551 Some(&*iterator_expr),
2552 token::intern("next"),
2557 // Regardless of whether the lookup succeeds, check the method arguments
2558 // so that we have *some* type for each argument.
2559 let method_type = match method {
2560 Some(ref method) => method.ty,
2562 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
2564 if !ty::type_is_error(true_expr_type) {
2565 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2566 fcx.tcx().sess.span_err(iterator_expr.span,
2567 format!("`for` loop expression has type `{}` which does \
2568 not implement the `Iterator` trait; \
2570 ty_string).as_slice());
2575 let return_type = check_method_argument_types(fcx,
2581 DontTupleArguments);
2585 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2588 // We expect the return type to be `Option` or something like it.
2589 // Grab the first parameter of its type substitution.
2590 let return_type = match return_type {
2591 ty::FnConverging(return_type) =>
2592 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2593 ty::FnDiverging => ty::mk_err()
2595 match return_type.sty {
2596 ty::ty_enum(_, ref substs)
2597 if !substs.types.is_empty_in(subst::TypeSpace) => {
2598 *substs.types.get(subst::TypeSpace, 0)
2604 fcx.tcx().sess.span_err(iterator_expr.span,
2605 format!("`next` method of the `Iterator` \
2606 trait has an unexpected type `{}`",
2607 fcx.infcx().ty_to_string(return_type))
2613 None => ty::mk_err()
2617 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2619 method_fn_ty: Ty<'tcx>,
2620 callee_expr: &ast::Expr,
2621 args_no_rcvr: &[&P<ast::Expr>],
2622 deref_args: DerefArgs,
2623 tuple_arguments: TupleArgumentsFlag)
2624 -> ty::FnOutput<'tcx> {
2625 if ty::type_is_error(method_fn_ty) {
2626 let err_inputs = err_args(args_no_rcvr.len());
2628 let err_inputs = match tuple_arguments {
2629 DontTupleArguments => err_inputs,
2630 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2633 check_argument_types(fcx,
2635 err_inputs.as_slice(),
2641 ty::FnConverging(ty::mk_err())
2643 match method_fn_ty.sty {
2644 ty::ty_bare_fn(ref fty) => {
2645 // HACK(eddyb) ignore self in the definition (see above).
2646 check_argument_types(fcx,
2648 fty.sig.inputs.slice_from(1),
2657 fcx.tcx().sess.span_bug(callee_expr.span,
2658 "method without bare fn type");
2664 /// Generic function that factors out common logic from function calls, method calls and overloaded
2666 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2668 fn_inputs: &[Ty<'tcx>],
2669 _callee_expr: &ast::Expr,
2670 args: &[&P<ast::Expr>],
2671 deref_args: DerefArgs,
2673 tuple_arguments: TupleArgumentsFlag) {
2674 let tcx = fcx.ccx.tcx;
2676 // Grab the argument types, supplying fresh type variables
2677 // if the wrong number of arguments were supplied
2678 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2684 let expected_arg_count = fn_inputs.len();
2685 let formal_tys = if tuple_arguments == TupleArguments {
2686 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2687 match tuple_type.sty {
2688 ty::ty_tup(ref arg_types) => {
2689 if arg_types.len() != args.len() {
2690 span_err!(tcx.sess, sp, E0057,
2691 "this function takes {} parameter{} but {} parameter{} supplied",
2693 if arg_types.len() == 1 {""} else {"s"},
2695 if args.len() == 1 {" was"} else {"s were"});
2696 err_args(args.len())
2698 (*arg_types).clone()
2702 span_err!(tcx.sess, sp, E0059,
2703 "cannot use call notation; the first type parameter \
2704 for the function trait is neither a tuple nor unit");
2705 err_args(args.len())
2708 } else if expected_arg_count == supplied_arg_count {
2709 fn_inputs.iter().map(|a| *a).collect()
2710 } else if variadic {
2711 if supplied_arg_count >= expected_arg_count {
2712 fn_inputs.iter().map(|a| *a).collect()
2714 span_err!(tcx.sess, sp, E0060,
2715 "this function takes at least {} parameter{} \
2716 but {} parameter{} supplied",
2718 if expected_arg_count == 1 {""} else {"s"},
2720 if supplied_arg_count == 1 {" was"} else {"s were"});
2721 err_args(supplied_arg_count)
2724 span_err!(tcx.sess, sp, E0061,
2725 "this function takes {} parameter{} but {} parameter{} supplied",
2727 if expected_arg_count == 1 {""} else {"s"},
2729 if supplied_arg_count == 1 {" was"} else {"s were"});
2730 err_args(supplied_arg_count)
2733 debug!("check_argument_types: formal_tys={}",
2734 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2736 // Check the arguments.
2737 // We do this in a pretty awful way: first we typecheck any arguments
2738 // that are not anonymous functions, then we typecheck the anonymous
2739 // functions. This is so that we have more information about the types
2740 // of arguments when we typecheck the functions. This isn't really the
2741 // right way to do this.
2742 let xs = [false, true];
2743 for check_blocks in xs.iter() {
2744 let check_blocks = *check_blocks;
2745 debug!("check_blocks={}", check_blocks);
2747 // More awful hacks: before we check the blocks, try to do
2748 // an "opportunistic" vtable resolution of any trait
2749 // bounds on the call.
2751 vtable::select_new_fcx_obligations(fcx);
2754 // For variadic functions, we don't have a declared type for all of
2755 // the arguments hence we only do our usual type checking with
2756 // the arguments who's types we do know.
2757 let t = if variadic {
2759 } else if tuple_arguments == TupleArguments {
2764 for (i, arg) in args.iter().take(t).enumerate() {
2765 let is_block = match arg.node {
2766 ast::ExprClosure(..) | ast::ExprProc(..) => true,
2770 if is_block == check_blocks {
2771 debug!("checking the argument");
2772 let mut formal_ty = formal_tys[i];
2776 match formal_ty.sty {
2777 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2780 // So we hit this case when one implements the
2781 // operator traits but leaves an argument as
2782 // just T instead of &T. We'll catch it in the
2783 // mismatch impl/trait method phase no need to
2786 formal_ty = ty::mk_err();
2793 check_expr_coercable_to_type(fcx, &***arg, formal_ty);
2798 // We also need to make sure we at least write the ty of the other
2799 // arguments which we skipped above.
2801 for arg in args.iter().skip(expected_arg_count) {
2802 check_expr(fcx, &***arg);
2804 // There are a few types which get autopromoted when passed via varargs
2805 // in C but we just error out instead and require explicit casts.
2806 let arg_ty = structurally_resolved_type(fcx, arg.span,
2807 fcx.expr_ty(&***arg));
2809 ty::ty_float(ast::TyF32) => {
2810 fcx.type_error_message(arg.span,
2812 format!("can't pass an {} to variadic \
2813 function, cast to c_double", t)
2816 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2817 fcx.type_error_message(arg.span, |t| {
2818 format!("can't pass {} to variadic \
2819 function, cast to c_int",
2823 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2824 fcx.type_error_message(arg.span, |t| {
2825 format!("can't pass {} to variadic \
2826 function, cast to c_uint",
2836 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2837 fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
2838 Vec::from_fn(len, |_| ty::mk_err())
2841 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2842 call_expr: &ast::Expr,
2843 output: ty::FnOutput<'tcx>) {
2844 fcx.write_ty(call_expr.id, match output {
2845 ty::FnConverging(output_ty) => output_ty,
2846 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2850 // AST fragment checking
2851 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2853 expected: Expectation<'tcx>)
2856 let tcx = fcx.ccx.tcx;
2859 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2860 ast::LitBinary(..) => {
2861 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2863 ast::LitByte(_) => ty::mk_u8(),
2864 ast::LitChar(_) => ty::mk_char(),
2865 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2866 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2867 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2868 let opt_ty = expected.map_to_option(fcx, |sty| {
2870 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2871 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2872 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2873 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2874 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2878 opt_ty.unwrap_or_else(
2879 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2881 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2882 ast::LitFloatUnsuffixed(_) => {
2883 let opt_ty = expected.map_to_option(fcx, |sty| {
2885 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2889 opt_ty.unwrap_or_else(
2890 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2892 ast::LitBool(_) => ty::mk_bool()
2896 pub fn valid_range_bounds(ccx: &CrateCtxt,
2900 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2901 Some(val) => Some(val <= 0),
2906 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2908 expected: Ty<'tcx>) {
2909 check_expr_with_unifier(
2910 fcx, expr, ExpectHasType(expected), NoPreference,
2911 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2914 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2916 expected: Ty<'tcx>) {
2917 check_expr_with_unifier(
2918 fcx, expr, ExpectHasType(expected), NoPreference,
2919 || demand::coerce(fcx, expr.span, expected, expr));
2922 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2923 expected: Ty<'tcx>) {
2924 check_expr_with_unifier(
2925 fcx, expr, ExpectHasType(expected), NoPreference,
2929 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2931 expected: Expectation<'tcx>) {
2932 check_expr_with_unifier(
2933 fcx, expr, expected, NoPreference,
2937 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2939 expected: Expectation<'tcx>,
2940 lvalue_pref: LvaluePreference)
2942 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2945 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2946 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2949 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2950 lvalue_pref: LvaluePreference) {
2951 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2954 // determine the `self` type, using fresh variables for all variables
2955 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2956 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2958 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2959 span: Span, // (potential) receiver for this impl
2961 -> TypeAndSubsts<'tcx> {
2962 let tcx = fcx.tcx();
2964 let ity = ty::lookup_item_type(tcx, did);
2965 let (n_tps, rps, raw_ty) =
2966 (ity.generics.types.len(subst::TypeSpace),
2967 ity.generics.regions.get_slice(subst::TypeSpace),
2970 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2971 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2972 let substs = subst::Substs::new_type(tps, rps);
2973 let substd_ty = raw_ty.subst(tcx, &substs);
2975 TypeAndSubsts { substs: substs, ty: substd_ty }
2978 // Only for fields! Returns <none> for methods>
2979 // Indifferent to privacy flags
2980 pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
2981 class_id: ast::DefId,
2982 items: &[ty::field_ty],
2983 fieldname: ast::Name,
2984 substs: &subst::Substs<'tcx>)
2985 -> Option<Ty<'tcx>> {
2987 let o_field = items.iter().find(|f| f.name == fieldname);
2988 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2991 pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
2992 class_id: ast::DefId,
2993 items: &[ty::field_ty],
2995 substs: &subst::Substs<'tcx>)
2996 -> Option<Ty<'tcx>> {
2998 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
2999 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
3002 // Controls whether the arguments are automatically referenced. This is useful
3003 // for overloaded binary and unary operators.
3004 pub enum DerefArgs {
3009 impl Copy for DerefArgs {}
3011 /// Controls whether the arguments are tupled. This is used for the call
3014 /// Tupling means that all call-side arguments are packed into a tuple and
3015 /// passed as a single parameter. For example, if tupling is enabled, this
3018 /// fn f(x: (int, int))
3020 /// Can be called as:
3027 #[deriving(Clone, Eq, PartialEq)]
3028 enum TupleArgumentsFlag {
3034 /// If an expression has any sub-expressions that result in a type error,
3035 /// inspecting that expression's type with `ty::type_is_error` will return
3036 /// true. Likewise, if an expression is known to diverge, inspecting its
3037 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
3038 /// strict, _|_ can appear in the type of an expression that does not,
3039 /// itself, diverge: for example, fn() -> _|_.)
3040 /// Note that inspecting a type's structure *directly* may expose the fact
3041 /// that there are actually multiple representations for `ty_err`, so avoid
3042 /// that when err needs to be handled differently.
3043 fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3045 expected: Expectation<'tcx>,
3046 lvalue_pref: LvaluePreference,
3049 debug!(">> typechecking: expr={} expected={}",
3050 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
3052 // A generic function for doing all of the checking for call expressions
3053 fn check_call(fcx: &FnCtxt,
3054 call_expr: &ast::Expr,
3056 args: &[&P<ast::Expr>]) {
3057 // Store the type of `f` as the type of the callee
3058 let fn_ty = fcx.expr_ty(f);
3060 // Extract the function signature from `in_fty`.
3061 let fn_sty = structure_of(fcx, f.span, fn_ty);
3063 // This is the "default" function signature, used in case of error.
3064 // In that case, we check each argument against "error" in order to
3065 // set up all the node type bindings.
3066 let error_fn_sig = FnSig {
3067 inputs: err_args(args.len()),
3068 output: ty::FnConverging(ty::mk_err()),
3072 let fn_sig = match *fn_sty {
3073 ty::ty_bare_fn(ty::BareFnTy {ref sig, ..}) |
3074 ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
3076 fcx.type_error_message(call_expr.span, |actual| {
3077 format!("expected function, found `{}`", actual)
3083 // Replace any bound regions that appear in the function
3084 // signature with region variables
3086 fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
3090 // Call the generic checker.
3091 check_argument_types(fcx,
3093 fn_sig.inputs.as_slice(),
3098 DontTupleArguments);
3100 write_call(fcx, call_expr, fn_sig.output);
3103 // Checks a method call.
3104 fn check_method_call(fcx: &FnCtxt,
3106 method_name: ast::SpannedIdent,
3107 args: &[P<ast::Expr>],
3109 lvalue_pref: LvaluePreference) {
3110 let rcvr = &*args[0];
3111 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
3113 // no need to check for bot/err -- callee does that
3114 let expr_t = structurally_resolved_type(fcx,
3116 fcx.expr_ty(&*rcvr));
3118 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
3119 let fn_ty = match method::lookup(fcx,
3121 method_name.node.name,
3127 let method_ty = method.ty;
3128 let method_call = MethodCall::expr(expr.id);
3129 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3133 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
3134 fcx.write_error(expr.id);
3139 // Call the generic checker.
3140 let args: Vec<_> = args[1..].iter().map(|x| x).collect();
3141 let ret_ty = check_method_argument_types(fcx,
3147 DontTupleArguments);
3149 write_call(fcx, expr, ret_ty);
3152 // A generic function for checking the then and else in an if
3154 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3155 cond_expr: &ast::Expr,
3156 then_blk: &ast::Block,
3157 opt_else_expr: Option<&ast::Expr>,
3160 expected: Expectation<'tcx>) {
3161 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
3163 // Disregard "castable to" expectations because they
3164 // can lead us astray. Consider for example `if cond
3165 // {22} else {c} as u8` -- if we propagate the
3166 // "castable to u8" constraint to 22, it will pick the
3167 // type 22u8, which is overly constrained (c might not
3168 // be a u8). In effect, the problem is that the
3169 // "castable to" expectation is not the tightest thing
3170 // we can say, so we want to drop it in this case.
3171 // The tightest thing we can say is "must unify with
3172 // else branch". Note that in the case of a "has type"
3173 // constraint, this limitation does not hold.
3175 // If the expected type is just a type variable, then don't use
3176 // an expected type. Otherwise, we might write parts of the type
3177 // when checking the 'then' block which are incompatible with the
3179 let expected = match expected.only_has_type() {
3180 ExpectHasType(ety) => {
3181 let ety = fcx.infcx().shallow_resolve(ety);
3182 if !ty::type_is_ty_var(ety) {
3190 check_block_with_expected(fcx, then_blk, expected);
3191 let then_ty = fcx.node_ty(then_blk.id);
3193 let branches_ty = match opt_else_expr {
3194 Some(ref else_expr) => {
3195 check_expr_with_expectation(fcx, &**else_expr, expected);
3196 let else_ty = fcx.expr_ty(&**else_expr);
3197 infer::common_supertype(fcx.infcx(),
3198 infer::IfExpression(sp),
3204 infer::common_supertype(fcx.infcx(),
3205 infer::IfExpressionWithNoElse(sp),
3208 ty::mk_nil(fcx.tcx()))
3212 let cond_ty = fcx.expr_ty(cond_expr);
3213 let if_ty = if ty::type_is_error(cond_ty) {
3219 fcx.write_ty(id, if_ty);
3222 fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
3226 trait_did: Option<ast::DefId>,
3228 rhs: Option<&P<ast::Expr>>,
3229 unbound_method: ||) -> Ty<'tcx> {
3230 let method = match trait_did {
3231 Some(trait_did) => {
3232 // We do eager coercions to make using operators
3235 // - If the input is of type &'a T (resp. &'a mut T),
3236 // then reborrow it to &'b T (resp. &'b mut T) where
3237 // 'b <= 'a. This makes things like `x == y`, where
3238 // `x` and `y` are both region pointers, work. We
3239 // could also solve this with variance or different
3240 // traits that don't force left and right to have same
3242 let (adj_ty, adjustment) = match lhs_ty.sty {
3243 ty::ty_rptr(r_in, mt) => {
3244 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
3245 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, r_in);
3246 let adjusted_ty = ty::mk_rptr(fcx.tcx(), r_adj, mt);
3247 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
3248 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
3249 (adjusted_ty, adjustment)
3252 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
3256 debug!("adjusted_ty={} adjustment={}",
3257 adj_ty.repr(fcx.tcx()),
3260 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
3261 trait_did, adjustment, adj_ty, None)
3265 let args = match rhs {
3266 Some(rhs) => vec![rhs],
3271 let method_ty = method.ty;
3272 // HACK(eddyb) Fully qualified path to work around a resolve bug.
3273 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
3274 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3275 match check_method_argument_types(fcx,
3281 DontTupleArguments) {
3282 ty::FnConverging(result_type) => result_type,
3283 ty::FnDiverging => ty::mk_err()
3288 // Check the args anyway
3289 // so we get all the error messages
3290 let expected_ty = ty::mk_err();
3291 check_method_argument_types(fcx,
3297 DontTupleArguments);
3303 // could be either an expr_binop or an expr_assign_binop
3304 fn check_binop(fcx: &FnCtxt,
3309 is_binop_assignment: IsBinopAssignment) {
3310 let tcx = fcx.ccx.tcx;
3312 let lvalue_pref = match is_binop_assignment {
3313 BinopAssignment => PreferMutLvalue,
3314 SimpleBinop => NoPreference
3316 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
3318 // Callee does bot / err checking
3319 let lhs_t = structurally_resolved_type(fcx, lhs.span,
3320 fcx.expr_ty(&*lhs));
3322 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
3323 // Shift is a special case: rhs must be uint, no matter what lhs is
3324 check_expr_has_type(fcx, &**rhs, ty::mk_uint());
3325 fcx.write_ty(expr.id, lhs_t);
3329 if ty::is_binopable(tcx, lhs_t, op) {
3330 let tvar = fcx.infcx().next_ty_var();
3331 demand::suptype(fcx, expr.span, tvar, lhs_t);
3332 check_expr_has_type(fcx, &**rhs, tvar);
3334 let result_t = match op {
3335 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
3337 if ty::type_is_simd(tcx, lhs_t) {
3338 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
3339 fcx.type_error_message(expr.span,
3341 format!("binary comparison \
3342 operation `{}` not \
3343 supported for floating \
3344 point SIMD vector `{}`",
3345 ast_util::binop_to_string(op),
3362 fcx.write_ty(expr.id, result_t);
3366 if op == ast::BiOr || op == ast::BiAnd {
3367 // This is an error; one of the operands must have the wrong
3369 fcx.write_error(expr.id);
3370 fcx.write_error(rhs.id);
3371 fcx.type_error_message(expr.span,
3373 format!("binary operation `{}` cannot be applied \
3375 ast_util::binop_to_string(op),
3382 // Check for overloaded operators if not an assignment.
3383 let result_t = if is_binop_assignment == SimpleBinop {
3384 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3386 fcx.type_error_message(expr.span,
3388 format!("binary assignment \
3390 cannot be applied to \
3392 ast_util::binop_to_string(op),
3397 check_expr(fcx, &**rhs);
3401 fcx.write_ty(expr.id, result_t);
3402 if ty::type_is_error(result_t) {
3403 fcx.write_ty(rhs.id, result_t);
3407 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3409 lhs_expr: &ast::Expr,
3410 lhs_resolved_t: Ty<'tcx>,
3412 rhs: &P<ast::Expr>) -> Ty<'tcx> {
3413 let tcx = fcx.ccx.tcx;
3414 let lang = &tcx.lang_items;
3415 let (name, trait_did) = match op {
3416 ast::BiAdd => ("add", lang.add_trait()),
3417 ast::BiSub => ("sub", lang.sub_trait()),
3418 ast::BiMul => ("mul", lang.mul_trait()),
3419 ast::BiDiv => ("div", lang.div_trait()),
3420 ast::BiRem => ("rem", lang.rem_trait()),
3421 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3422 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3423 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3424 ast::BiShl => ("shl", lang.shl_trait()),
3425 ast::BiShr => ("shr", lang.shr_trait()),
3426 ast::BiLt => ("lt", lang.ord_trait()),
3427 ast::BiLe => ("le", lang.ord_trait()),
3428 ast::BiGe => ("ge", lang.ord_trait()),
3429 ast::BiGt => ("gt", lang.ord_trait()),
3430 ast::BiEq => ("eq", lang.eq_trait()),
3431 ast::BiNe => ("ne", lang.eq_trait()),
3432 ast::BiAnd | ast::BiOr => {
3433 check_expr(fcx, &**rhs);
3434 return ty::mk_err();
3437 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3438 trait_did, lhs_expr, Some(rhs), || {
3439 fcx.type_error_message(ex.span, |actual| {
3440 format!("binary operation `{}` cannot be applied to type `{}`",
3441 ast_util::binop_to_string(op),
3443 }, lhs_resolved_t, None)
3447 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3450 trait_did: Option<ast::DefId>,
3452 rhs_expr: &ast::Expr,
3453 rhs_t: Ty<'tcx>) -> Ty<'tcx> {
3454 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3455 trait_did, rhs_expr, None, || {
3456 fcx.type_error_message(ex.span, |actual| {
3457 format!("cannot apply unary operator `{}` to type `{}`",
3463 // Check field access expressions
3464 fn check_field(fcx: &FnCtxt,
3466 lvalue_pref: LvaluePreference,
3468 field: &ast::SpannedIdent) {
3469 let tcx = fcx.ccx.tcx;
3470 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3471 let expr_t = structurally_resolved_type(fcx, expr.span,
3473 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3474 let (_, autoderefs, field_ty) =
3475 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3477 ty::ty_struct(base_id, ref substs) => {
3478 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3479 let fields = ty::lookup_struct_fields(tcx, base_id);
3480 lookup_field_ty(tcx, base_id, fields.as_slice(),
3481 field.node.name, &(*substs))
3488 fcx.write_ty(expr.id, field_ty);
3489 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3495 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3496 fcx.type_error_message(
3499 format!("attempted to take value of method `{}` on type \
3500 `{}`", token::get_ident(field.node), actual)
3504 tcx.sess.span_help(field.span,
3505 "maybe a `()` to call it is missing? \
3506 If not, try an anonymous function");
3508 fcx.type_error_message(
3511 format!("attempted access of field `{}` on \
3512 type `{}`, but no field with that \
3514 token::get_ident(field.node),
3520 fcx.write_error(expr.id);
3523 // Check tuple index expressions
3524 fn check_tup_field(fcx: &FnCtxt,
3526 lvalue_pref: LvaluePreference,
3528 idx: codemap::Spanned<uint>) {
3529 let tcx = fcx.ccx.tcx;
3530 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3531 let expr_t = structurally_resolved_type(fcx, expr.span,
3533 let mut tuple_like = false;
3534 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3535 let (_, autoderefs, field_ty) =
3536 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3538 ty::ty_struct(base_id, ref substs) => {
3539 tuple_like = ty::is_tuple_struct(tcx, base_id);
3541 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3542 let fields = ty::lookup_struct_fields(tcx, base_id);
3543 lookup_tup_field_ty(tcx, base_id, fields.as_slice(),
3544 idx.node, &(*substs))
3549 ty::ty_tup(ref v) => {
3551 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3558 fcx.write_ty(expr.id, field_ty);
3559 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3564 fcx.type_error_message(
3568 format!("attempted out-of-bounds tuple index `{}` on \
3573 format!("attempted tuple index `{}` on type `{}`, but the \
3574 type was not a tuple or tuple struct",
3581 fcx.write_error(expr.id);
3584 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3585 struct_ty: Ty<'tcx>,
3587 class_id: ast::DefId,
3588 node_id: ast::NodeId,
3589 substitutions: subst::Substs<'tcx>,
3590 field_types: &[ty::field_ty],
3591 ast_fields: &[ast::Field],
3592 check_completeness: bool) {
3593 let tcx = fcx.ccx.tcx;
3595 let mut class_field_map = FnvHashMap::new();
3596 let mut fields_found = 0;
3597 for field in field_types.iter() {
3598 class_field_map.insert(field.name, (field.id, false));
3601 let mut error_happened = false;
3603 // Typecheck each field.
3604 for field in ast_fields.iter() {
3605 let mut expected_field_type = ty::mk_err();
3607 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3610 fcx.type_error_message(
3613 format!("structure `{}` has no field named `{}`",
3614 actual, token::get_ident(field.ident.node))
3618 error_happened = true;
3620 Some((_, true)) => {
3621 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3622 "field `{}` specified more than once",
3623 token::get_ident(field.ident.node));
3624 error_happened = true;
3626 Some((field_id, false)) => {
3627 expected_field_type =
3628 ty::lookup_field_type(
3629 tcx, class_id, field_id, &substitutions);
3630 class_field_map.insert(
3631 field.ident.node.name, (field_id, true));
3635 // Make sure to give a type to the field even if there's
3636 // an error, so we can continue typechecking
3637 check_expr_coercable_to_type(
3640 expected_field_type);
3644 fcx.write_error(node_id);
3647 if check_completeness && !error_happened {
3648 // Make sure the programmer specified all the fields.
3649 assert!(fields_found <= field_types.len());
3650 if fields_found < field_types.len() {
3651 let mut missing_fields = Vec::new();
3652 for class_field in field_types.iter() {
3653 let name = class_field.name;
3654 let (_, seen) = class_field_map[name];
3656 missing_fields.push(
3657 format!("`{}`", token::get_name(name).get()))
3661 span_err!(tcx.sess, span, E0063,
3662 "missing field{}: {}",
3663 if missing_fields.len() == 1 {""} else {"s"},
3664 missing_fields.connect(", "));
3668 if !error_happened {
3669 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3670 class_id, substitutions));
3674 fn check_struct_constructor(fcx: &FnCtxt,
3676 span: codemap::Span,
3677 class_id: ast::DefId,
3678 fields: &[ast::Field],
3679 base_expr: Option<&ast::Expr>) {
3680 let tcx = fcx.ccx.tcx;
3682 // Generate the struct type.
3684 ty: mut struct_type,
3685 substs: struct_substs
3686 } = fcx.instantiate_type(span, class_id);
3688 // Look up and check the fields.
3689 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3690 check_struct_or_variant_fields(fcx,
3696 class_fields.as_slice(),
3698 base_expr.is_none());
3699 if ty::type_is_error(fcx.node_ty(id)) {
3700 struct_type = ty::mk_err();
3703 // Check the base expression if necessary.
3706 Some(base_expr) => {
3707 check_expr_has_type(fcx, &*base_expr, struct_type);
3711 // Write in the resulting type.
3712 fcx.write_ty(id, struct_type);
3715 fn check_struct_enum_variant(fcx: &FnCtxt,
3717 span: codemap::Span,
3718 enum_id: ast::DefId,
3719 variant_id: ast::DefId,
3720 fields: &[ast::Field]) {
3721 let tcx = fcx.ccx.tcx;
3723 // Look up the number of type parameters and the raw type, and
3724 // determine whether the enum is region-parameterized.
3727 substs: substitutions
3728 } = fcx.instantiate_type(span, enum_id);
3730 // Look up and check the enum variant fields.
3731 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3732 check_struct_or_variant_fields(fcx,
3738 variant_fields.as_slice(),
3741 fcx.write_ty(id, enum_type);
3744 fn check_struct_fields_on_error(fcx: &FnCtxt,
3746 fields: &[ast::Field],
3747 base_expr: &Option<P<ast::Expr>>) {
3748 // Make sure to still write the types
3749 // otherwise we might ICE
3750 fcx.write_error(id);
3751 for field in fields.iter() {
3752 check_expr(fcx, &*field.expr);
3755 Some(ref base) => check_expr(fcx, &**base),
3760 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3762 let tcx = fcx.ccx.tcx;
3765 ast::ExprBox(ref place, ref subexpr) => {
3766 check_expr(fcx, &**place);
3767 check_expr(fcx, &**subexpr);
3769 let mut checked = false;
3770 if let ast::ExprPath(ref path) = place.node {
3771 // FIXME(pcwalton): For now we hardcode the two permissible
3772 // places: the exchange heap and the managed heap.
3773 let definition = lookup_def(fcx, path.span, place.id);
3774 let def_id = definition.def_id();
3775 let referent_ty = fcx.expr_ty(&**subexpr);
3776 if tcx.lang_items.exchange_heap() == Some(def_id) {
3777 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3783 span_err!(tcx.sess, expr.span, E0066,
3784 "only the managed heap and exchange heap are currently supported");
3785 fcx.write_ty(id, ty::mk_err());
3789 ast::ExprLit(ref lit) => {
3790 let typ = check_lit(fcx, &**lit, expected);
3791 fcx.write_ty(id, typ);
3793 ast::ExprBinary(op, ref lhs, ref rhs) => {
3794 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3796 let lhs_ty = fcx.expr_ty(&**lhs);
3797 let rhs_ty = fcx.expr_ty(&**rhs);
3798 if ty::type_is_error(lhs_ty) ||
3799 ty::type_is_error(rhs_ty) {
3800 fcx.write_error(id);
3803 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3804 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3806 let lhs_t = fcx.expr_ty(&**lhs);
3807 let result_t = fcx.expr_ty(expr);
3808 demand::suptype(fcx, expr.span, result_t, lhs_t);
3810 let tcx = fcx.tcx();
3811 if !ty::expr_is_lval(tcx, &**lhs) {
3812 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3815 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3817 // Overwrite result of check_binop...this preserves existing behavior
3818 // but seems quite dubious with regard to user-defined methods
3819 // and so forth. - Niko
3820 if !ty::type_is_error(result_t) {
3821 fcx.write_nil(expr.id);
3824 ast::ExprUnary(unop, ref oprnd) => {
3825 let expected_inner = expected.map(fcx, |sty| {
3827 ast::UnUniq => match *sty {
3828 ty::ty_uniq(ty) => {
3835 ast::UnNot | ast::UnNeg => {
3843 let lvalue_pref = match unop {
3844 ast::UnDeref => lvalue_pref,
3847 check_expr_with_expectation_and_lvalue_pref(
3848 fcx, &**oprnd, expected_inner, lvalue_pref);
3849 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3851 if !ty::type_is_error(oprnd_t) {
3854 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3857 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3858 oprnd_t = match ty::deref(oprnd_t, true) {
3860 None => match try_overloaded_deref(fcx, expr.span,
3861 Some(MethodCall::expr(expr.id)),
3862 Some(&**oprnd), oprnd_t, lvalue_pref) {
3865 let is_newtype = match oprnd_t.sty {
3866 ty::ty_struct(did, ref substs) => {
3867 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3869 && fields[0].name ==
3870 token::special_idents::unnamed_field.name
3875 // This is an obsolete struct deref
3876 span_err!(tcx.sess, expr.span, E0068,
3877 "single-field tuple-structs can \
3878 no longer be dereferenced");
3880 fcx.type_error_message(expr.span, |actual| {
3881 format!("type `{}` cannot be \
3882 dereferenced", actual)
3891 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3893 if !(ty::type_is_integral(oprnd_t) ||
3894 oprnd_t.sty == ty::ty_bool) {
3895 oprnd_t = check_user_unop(fcx, "!", "not",
3896 tcx.lang_items.not_trait(),
3897 expr, &**oprnd, oprnd_t);
3901 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3903 if !(ty::type_is_integral(oprnd_t) ||
3904 ty::type_is_fp(oprnd_t)) {
3905 oprnd_t = check_user_unop(fcx, "-", "neg",
3906 tcx.lang_items.neg_trait(),
3907 expr, &**oprnd, oprnd_t);
3912 fcx.write_ty(id, oprnd_t);
3914 ast::ExprAddrOf(mutbl, ref oprnd) => {
3915 let expected = expected.only_has_type();
3916 let hint = expected.map(fcx, |sty| {
3917 match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3918 _ => NoExpectation }
3920 let lvalue_pref = match mutbl {
3921 ast::MutMutable => PreferMutLvalue,
3922 ast::MutImmutable => NoPreference
3924 check_expr_with_expectation_and_lvalue_pref(fcx,
3929 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3930 let oprnd_t = if ty::type_is_error(tm.ty) {
3933 // Note: at this point, we cannot say what the best lifetime
3934 // is to use for resulting pointer. We want to use the
3935 // shortest lifetime possible so as to avoid spurious borrowck
3936 // errors. Moreover, the longest lifetime will depend on the
3937 // precise details of the value whose address is being taken
3938 // (and how long it is valid), which we don't know yet until type
3939 // inference is complete.
3941 // Therefore, here we simply generate a region variable. The
3942 // region inferencer will then select the ultimate value.
3943 // Finally, borrowck is charged with guaranteeing that the
3944 // value whose address was taken can actually be made to live
3945 // as long as it needs to live.
3947 // String literals are already, implicitly converted to slices.
3948 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3949 // Empty slices live in static memory.
3950 ast::ExprVec(ref elements) if elements.len() == 0 => {
3951 // Note: we do not assign a lifetime of
3952 // static. This is because the resulting type
3953 // `&'static [T]` would require that T outlives
3955 let region = fcx.infcx().next_region_var(
3956 infer::AddrOfSlice(expr.span));
3957 ty::mk_rptr(tcx, region, tm)
3960 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3961 ty::mk_rptr(tcx, region, tm)
3965 fcx.write_ty(id, oprnd_t);
3967 ast::ExprPath(ref pth) => {
3968 let defn = lookup_def(fcx, pth.span, id);
3969 let pty = polytype_for_def(fcx, expr.span, defn);
3970 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3972 // We always require that the type provided as the value for
3973 // a type parameter outlives the moment of instantiation.
3974 constrain_path_type_parameters(fcx, expr);
3976 ast::ExprInlineAsm(ref ia) => {
3977 for &(_, ref input) in ia.inputs.iter() {
3978 check_expr(fcx, &**input);
3980 for &(_, ref out, _) in ia.outputs.iter() {
3981 check_expr(fcx, &**out);
3985 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3986 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3987 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3988 ast::ExprRet(ref expr_opt) => {
3990 ty::FnConverging(result_type) => {
3993 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3994 result_type, ty::mk_nil(fcx.tcx())) {
3995 span_err!(tcx.sess, expr.span, E0069,
3996 "`return;` in function returning non-nil");
3999 check_expr_coercable_to_type(fcx, &**e, result_type);
4003 ty::FnDiverging => {
4004 if let Some(ref e) = *expr_opt {
4005 check_expr(fcx, &**e);
4007 span_err!(tcx.sess, expr.span, E0166,
4008 "`return` in a function declared as diverging");
4011 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4013 ast::ExprParen(ref a) => {
4014 check_expr_with_expectation_and_lvalue_pref(fcx,
4018 fcx.write_ty(id, fcx.expr_ty(&**a));
4020 ast::ExprAssign(ref lhs, ref rhs) => {
4021 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4023 let tcx = fcx.tcx();
4024 if !ty::expr_is_lval(tcx, &**lhs) {
4025 span_err!(tcx.sess, expr.span, E0070,
4026 "illegal left-hand side expression");
4029 let lhs_ty = fcx.expr_ty(&**lhs);
4030 check_expr_has_type(fcx, &**rhs, lhs_ty);
4031 let rhs_ty = fcx.expr_ty(&**rhs);
4033 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4035 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4036 fcx.write_error(id);
4041 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4042 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4043 id, expr.span, expected);
4045 ast::ExprIfLet(..) => {
4046 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
4048 ast::ExprWhile(ref cond, ref body, _) => {
4049 check_expr_has_type(fcx, &**cond, ty::mk_bool());
4050 check_block_no_value(fcx, &**body);
4051 let cond_ty = fcx.expr_ty(&**cond);
4052 let body_ty = fcx.node_ty(body.id);
4053 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4054 fcx.write_error(id);
4060 ast::ExprWhileLet(..) => {
4061 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
4063 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4064 check_expr(fcx, &**head);
4065 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4066 vtable::select_new_fcx_obligations(fcx);
4068 let pcx = pat_ctxt {
4070 map: pat_id_map(&tcx.def_map, &**pat),
4072 _match::check_pat(&pcx, &**pat, typ);
4074 check_block_no_value(fcx, &**block);
4077 ast::ExprLoop(ref body, _) => {
4078 check_block_no_value(fcx, &**body);
4079 if !may_break(tcx, expr.id, &**body) {
4080 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4085 ast::ExprMatch(ref discrim, ref arms, _) => {
4086 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
4088 ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
4089 closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
4091 ast::ExprProc(ref decl, ref body) => {
4092 closure::check_boxed_closure(fcx,
4099 ast::ExprBlock(ref b) => {
4100 check_block_with_expected(fcx, &**b, expected);
4101 fcx.write_ty(id, fcx.node_ty(b.id));
4103 ast::ExprCall(ref f, ref args) => {
4104 // Index expressions need to be handled separately, to inform them
4105 // that they appear in call position.
4106 check_expr(fcx, &**f);
4107 let f_ty = fcx.expr_ty(&**f);
4109 let args: Vec<_> = args.iter().map(|x| x).collect();
4110 if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
4111 check_call(fcx, expr, &**f, args.as_slice());
4112 let args_err = args.iter().fold(false,
4114 // is this not working?
4115 let a_ty = fcx.expr_ty(&***a);
4116 rest_err || ty::type_is_error(a_ty)});
4117 if ty::type_is_error(f_ty) || args_err {
4118 fcx.write_error(id);
4122 ast::ExprMethodCall(ident, ref tps, ref args) => {
4123 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref);
4124 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4125 let args_err = arg_tys.fold(false,
4127 rest_err || ty::type_is_error(a)});
4129 fcx.write_error(id);
4132 ast::ExprCast(ref e, ref t) => {
4133 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
4134 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
4136 check_cast(fcx, expr, &**e, &**t);
4138 ast::ExprVec(ref args) => {
4139 let uty = match expected {
4140 ExpectHasType(uty) => {
4142 ty::ty_vec(ty, _) => Some(ty),
4149 let typ = match uty {
4151 for e in args.iter() {
4152 check_expr_coercable_to_type(fcx, &**e, uty);
4157 let t: Ty = fcx.infcx().next_ty_var();
4158 for e in args.iter() {
4159 check_expr_has_type(fcx, &**e, t);
4164 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4165 fcx.write_ty(id, typ);
4167 ast::ExprRepeat(ref element, ref count_expr) => {
4168 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
4169 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4171 let uty = match expected {
4172 ExpectHasType(uty) => {
4174 ty::ty_vec(ty, _) => Some(ty),
4181 let (element_ty, t) = match uty {
4183 check_expr_coercable_to_type(fcx, &**element, uty);
4187 let t: Ty = fcx.infcx().next_ty_var();
4188 check_expr_has_type(fcx, &**element, t);
4189 (fcx.expr_ty(&**element), t)
4194 // For [foo, ..n] where n > 1, `foo` must have
4196 fcx.require_type_meets(
4203 if ty::type_is_error(element_ty) {
4204 fcx.write_error(id);
4206 let t = ty::mk_vec(tcx, t, Some(count));
4207 fcx.write_ty(id, t);
4210 ast::ExprTup(ref elts) => {
4211 let expected = expected.only_has_type();
4212 let flds = expected.map_to_option(fcx, |sty| {
4214 ty::ty_tup(ref flds) => Some((*flds).clone()),
4218 let mut err_field = false;
4220 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4221 let t = match flds {
4222 Some(ref fs) if i < fs.len() => {
4224 check_expr_coercable_to_type(fcx, &**e, ety);
4228 check_expr_with_expectation(fcx, &**e, NoExpectation);
4232 err_field = err_field || ty::type_is_error(t);
4236 fcx.write_error(id);
4238 let typ = ty::mk_tup(tcx, elt_ts);
4239 fcx.write_ty(id, typ);
4242 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4243 // Resolve the path.
4244 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
4245 let struct_id = match def {
4246 Some(def::DefVariant(enum_id, variant_id, true)) => {
4247 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4248 variant_id, fields.as_slice());
4251 Some(def::DefTrait(def_id)) => {
4252 span_err!(tcx.sess, path.span, E0159,
4253 "use of trait `{}` as a struct constructor",
4254 pprust::path_to_string(path));
4255 check_struct_fields_on_error(fcx,
4262 // Verify that this was actually a struct.
4263 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4265 ty::ty_struct(struct_did, _) => {
4266 check_struct_constructor(fcx,
4271 base_expr.as_ref().map(|e| &**e));
4274 span_err!(tcx.sess, path.span, E0071,
4275 "`{}` does not name a structure",
4276 pprust::path_to_string(path));
4277 check_struct_fields_on_error(fcx,
4287 tcx.sess.span_bug(path.span,
4288 "structure constructor wasn't resolved")
4292 // Turn the path into a type and verify that that type unifies with
4293 // the resulting structure type. This is needed to handle type
4294 // parameters correctly.
4295 let actual_structure_type = fcx.expr_ty(&*expr);
4296 if !ty::type_is_error(actual_structure_type) {
4297 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4301 match fcx.mk_subty(false,
4302 infer::Misc(path.span),
4303 actual_structure_type,
4304 type_and_substs.ty) {
4306 Err(type_error) => {
4307 let type_error_description =
4308 ty::type_err_to_str(tcx, &type_error);
4311 .span_err(path.span,
4312 format!("structure constructor specifies a \
4313 structure of type `{}`, but this \
4314 structure has type `{}`: {}",
4316 .ty_to_string(type_and_substs.ty),
4319 actual_structure_type),
4320 type_error_description).as_slice());
4321 ty::note_and_explain_type_err(tcx, &type_error);
4326 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4328 ast::ExprField(ref base, ref field) => {
4329 check_field(fcx, expr, lvalue_pref, &**base, field);
4331 ast::ExprTupField(ref base, idx) => {
4332 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
4334 ast::ExprIndex(ref base, ref idx) => {
4335 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4336 check_expr(fcx, &**idx);
4337 let base_t = fcx.expr_ty(&**base);
4338 let idx_t = fcx.expr_ty(&**idx);
4339 if ty::type_is_error(base_t) {
4340 fcx.write_ty(id, base_t);
4341 } else if ty::type_is_error(idx_t) {
4342 fcx.write_ty(id, idx_t);
4344 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
4347 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
4349 MethodCall::expr(expr.id),
4358 Some((index_ty, element_ty)) => {
4359 check_expr_has_type(fcx, &**idx, index_ty);
4360 fcx.write_ty(id, element_ty);
4363 check_expr_has_type(fcx, &**idx, ty::mk_err());
4364 fcx.type_error_message(
4367 format!("cannot index a value of type `{}`",
4372 fcx.write_ty(id, ty::mk_err())
4377 ast::ExprSlice(ref base, ref start, ref end, mutbl) => {
4378 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4379 let raw_base_t = fcx.expr_ty(&**base);
4381 let mut some_err = false;
4382 if ty::type_is_error(raw_base_t) {
4383 fcx.write_ty(id, raw_base_t);
4388 let check_slice_idx = |e: &ast::Expr| {
4390 let e_t = fcx.expr_ty(e);
4391 if ty::type_is_error(e_t) {
4392 fcx.write_ty(id, e_t);
4396 start.as_ref().map(|e| check_slice_idx(&**e));
4397 end.as_ref().map(|e| check_slice_idx(&**e));
4401 let base_t = structurally_resolved_type(fcx,
4404 let method_call = MethodCall::expr(expr.id);
4405 match try_overloaded_slice(fcx,
4413 Some(ty) => fcx.write_ty(id, ty),
4415 fcx.type_error_message(expr.span,
4417 format!("cannot take a {}slice of a value with type `{}`",
4418 if mutbl == ast::MutMutable {
4427 fcx.write_ty(id, ty::mk_err())
4434 debug!("type of expr({}) {} is...", expr.id,
4435 syntax::print::pprust::expr_to_string(expr));
4436 debug!("... {}, expected is {}",
4437 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4438 expected.repr(tcx));
4443 fn constrain_path_type_parameters(fcx: &FnCtxt,
4446 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4447 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4451 impl<'tcx> Expectation<'tcx> {
4452 fn only_has_type(self) -> Expectation<'tcx> {
4454 NoExpectation | ExpectCastableToType(..) => NoExpectation,
4455 ExpectHasType(t) => ExpectHasType(t)
4459 // Resolves `expected` by a single level if it is a variable. If
4460 // there is no expected type or resolution is not possible (e.g.,
4461 // no constraints yet present), just returns `None`.
4462 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4467 ExpectCastableToType(t) => {
4468 ExpectCastableToType(
4469 fcx.infcx().resolve_type_vars_if_possible(t))
4471 ExpectHasType(t) => {
4473 fcx.infcx().resolve_type_vars_if_possible(t))
4478 fn map<'a>(self, fcx: &FnCtxt<'a, 'tcx>,
4479 unpack: |&ty::sty<'tcx>| -> Expectation<'tcx>)
4480 -> Expectation<'tcx> {
4481 match self.resolve(fcx) {
4482 NoExpectation => NoExpectation,
4483 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
4487 fn map_to_option<'a, O>(self,
4488 fcx: &FnCtxt<'a, 'tcx>,
4489 unpack: |&ty::sty<'tcx>| -> Option<O>)
4492 match self.resolve(fcx) {
4493 NoExpectation => None,
4494 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
4499 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4500 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4502 NoExpectation => format!("NoExpectation"),
4503 ExpectHasType(t) => format!("ExpectHasType({})",
4505 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4511 pub fn check_decl_initializer(fcx: &FnCtxt,
4515 let local_ty = fcx.local_ty(init.span, nid);
4516 check_expr_coercable_to_type(fcx, init, local_ty)
4519 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4520 let tcx = fcx.ccx.tcx;
4522 let t = fcx.local_ty(local.span, local.id);
4523 fcx.write_ty(local.id, t);
4525 if let Some(ref init) = local.init {
4526 check_decl_initializer(fcx, local.id, &**init);
4527 let init_ty = fcx.expr_ty(&**init);
4528 if ty::type_is_error(init_ty) {
4529 fcx.write_ty(local.id, init_ty);
4533 let pcx = pat_ctxt {
4535 map: pat_id_map(&tcx.def_map, &*local.pat),
4537 _match::check_pat(&pcx, &*local.pat, t);
4538 let pat_ty = fcx.node_ty(local.pat.id);
4539 if ty::type_is_error(pat_ty) {
4540 fcx.write_ty(local.id, pat_ty);
4544 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4546 let mut saw_bot = false;
4547 let mut saw_err = false;
4549 ast::StmtDecl(ref decl, id) => {
4552 ast::DeclLocal(ref l) => {
4553 check_decl_local(fcx, &**l);
4554 let l_t = fcx.node_ty(l.id);
4555 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4556 saw_err = saw_err || ty::type_is_error(l_t);
4558 ast::DeclItem(_) => {/* ignore for now */ }
4561 ast::StmtExpr(ref expr, id) => {
4563 // Check with expected type of ()
4564 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4565 let expr_ty = fcx.expr_ty(&**expr);
4566 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4567 saw_err = saw_err || ty::type_is_error(expr_ty);
4569 ast::StmtSemi(ref expr, id) => {
4571 check_expr(fcx, &**expr);
4572 let expr_ty = fcx.expr_ty(&**expr);
4573 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4574 saw_err |= ty::type_is_error(expr_ty);
4576 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4579 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4582 fcx.write_error(node_id);
4585 fcx.write_nil(node_id)
4589 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4590 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4591 let blkty = fcx.node_ty(blk.id);
4592 if ty::type_is_error(blkty) {
4593 fcx.write_error(blk.id);
4595 let nilty = ty::mk_nil(fcx.tcx());
4596 demand::suptype(fcx, blk.span, nilty, blkty);
4600 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4602 expected: Expectation<'tcx>) {
4604 let mut fcx_ps = fcx.ps.borrow_mut();
4605 let fn_style_state = fcx_ps.recurse(blk);
4606 replace(&mut *fcx_ps, fn_style_state)
4609 let mut warned = false;
4610 let mut any_diverges = false;
4611 let mut any_err = false;
4612 for s in blk.stmts.iter() {
4613 check_stmt(fcx, &**s);
4614 let s_id = ast_util::stmt_id(&**s);
4615 let s_ty = fcx.node_ty(s_id);
4616 if any_diverges && !warned && match s.node {
4617 ast::StmtDecl(ref decl, _) => {
4619 ast::DeclLocal(_) => true,
4623 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4629 .add_lint(lint::builtin::UNREACHABLE_CODE,
4632 "unreachable statement".to_string());
4635 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4636 any_err = any_err || ty::type_is_error(s_ty);
4639 None => if any_err {
4640 fcx.write_error(blk.id);
4641 } else if any_diverges {
4642 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4644 fcx.write_nil(blk.id);
4647 if any_diverges && !warned {
4651 .add_lint(lint::builtin::UNREACHABLE_CODE,
4654 "unreachable expression".to_string());
4656 let ety = match expected {
4657 ExpectHasType(ety) => {
4658 check_expr_coercable_to_type(fcx, &**e, ety);
4662 check_expr_with_expectation(fcx, &**e, expected);
4668 fcx.write_error(blk.id);
4669 } else if any_diverges {
4670 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4672 fcx.write_ty(blk.id, ety);
4677 *fcx.ps.borrow_mut() = prev;
4680 /// Checks a constant appearing in a type. At the moment this is just the
4681 /// length expression in a fixed-length vector, but someday it might be
4682 /// extended to type-level numeric literals.
4683 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4685 expected_type: Ty<'tcx>) {
4686 let inh = static_inherited_fields(ccx);
4687 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4688 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4691 fn check_const(ccx: &CrateCtxt,
4695 let inh = static_inherited_fields(ccx);
4696 let rty = ty::node_id_to_type(ccx.tcx, id);
4697 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4698 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4699 check_const_with_ty(&fcx, sp, e, declty);
4702 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4706 // Gather locals in statics (because of block expressions).
4707 // This is technically unnecessary because locals in static items are forbidden,
4708 // but prevents type checking from blowing up before const checking can properly
4710 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4712 check_expr_with_hint(fcx, e, declty);
4713 demand::coerce(fcx, e.span, declty, e);
4714 vtable::select_all_fcx_obligations_or_error(fcx);
4715 regionck::regionck_expr(fcx, e);
4716 writeback::resolve_type_vars_in_expr(fcx, e);
4719 /// Checks whether a type can be represented in memory. In particular, it
4720 /// identifies types that contain themselves without indirection through a
4721 /// pointer, which would mean their size is unbounded. This is different from
4722 /// the question of whether a type can be instantiated. See the definition of
4723 /// `check_instantiable`.
4724 pub fn check_representable(tcx: &ty::ctxt,
4726 item_id: ast::NodeId,
4727 designation: &str) -> bool {
4728 let rty = ty::node_id_to_type(tcx, item_id);
4730 // Check that it is possible to represent this type. This call identifies
4731 // (1) types that contain themselves and (2) types that contain a different
4732 // recursive type. It is only necessary to throw an error on those that
4733 // contain themselves. For case 2, there must be an inner type that will be
4734 // caught by case 1.
4735 match ty::is_type_representable(tcx, sp, rty) {
4736 ty::SelfRecursive => {
4737 span_err!(tcx.sess, sp, E0072,
4738 "illegal recursive {} type; \
4739 wrap the inner value in a box to make it representable",
4743 ty::Representable | ty::ContainsRecursive => (),
4748 /// Checks whether a type can be created without an instance of itself.
4749 /// This is similar but different from the question of whether a type
4750 /// can be represented. For example, the following type:
4752 /// enum foo { None, Some(foo) }
4754 /// is instantiable but is not representable. Similarly, the type
4756 /// enum foo { Some(@foo) }
4758 /// is representable, but not instantiable.
4759 pub fn check_instantiable(tcx: &ty::ctxt,
4761 item_id: ast::NodeId)
4763 let item_ty = ty::node_id_to_type(tcx, item_id);
4764 if !ty::is_instantiable(tcx, item_ty) {
4765 span_err!(tcx.sess, sp, E0073,
4766 "this type cannot be instantiated without an \
4767 instance of itself");
4768 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4769 ppaux::ty_to_string(tcx, item_ty));
4776 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4777 let t = ty::node_id_to_type(tcx, id);
4778 if ty::type_needs_subst(t) {
4779 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4783 ty::ty_struct(did, ref substs) => {
4784 let fields = ty::lookup_struct_fields(tcx, did);
4785 if fields.is_empty() {
4786 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4789 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4790 if !fields.iter().all(
4791 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4792 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4795 if !ty::type_is_machine(e) {
4796 span_err!(tcx.sess, sp, E0077,
4797 "SIMD vector element type should be machine type");
4805 pub fn check_enum_variants(ccx: &CrateCtxt,
4807 vs: &[P<ast::Variant>],
4810 fn disr_in_range(ccx: &CrateCtxt,
4812 disr: ty::Disr) -> bool {
4813 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4815 ast::TyU8 => disr as u8 as Disr == disr,
4816 ast::TyU16 => disr as u16 as Disr == disr,
4817 ast::TyU32 => disr as u32 as Disr == disr,
4818 ast::TyU64 => disr as u64 as Disr == disr,
4819 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4822 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4824 ast::TyI8 => disr as i8 as Disr == disr,
4825 ast::TyI16 => disr as i16 as Disr == disr,
4826 ast::TyI32 => disr as i32 as Disr == disr,
4827 ast::TyI64 => disr as i64 as Disr == disr,
4828 ast::TyI => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4832 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4833 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4837 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4838 vs: &[P<ast::Variant>],
4840 hint: attr::ReprAttr)
4841 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4843 let rty = ty::node_id_to_type(ccx.tcx, id);
4844 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4845 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4846 let mut prev_disr_val: Option<ty::Disr> = None;
4848 for v in vs.iter() {
4850 // If the discriminant value is specified explicitly in the enum check whether the
4851 // initialization expression is valid, otherwise use the last value plus one.
4852 let mut current_disr_val = match prev_disr_val {
4853 Some(prev_disr_val) => prev_disr_val + 1,
4854 None => ty::INITIAL_DISCRIMINANT_VALUE
4857 match v.node.disr_expr {
4859 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4861 let inh = static_inherited_fields(ccx);
4862 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4863 let declty = match hint {
4864 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4865 attr::ReprInt(_, attr::SignedInt(ity)) => {
4866 ty::mk_mach_int(ity)
4868 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4869 ty::mk_mach_uint(ity)
4872 check_const_with_ty(&fcx, e.span, &**e, declty);
4873 // check_expr (from check_const pass) doesn't guarantee
4874 // that the expression is in a form that eval_const_expr can
4875 // handle, so we may still get an internal compiler error
4877 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4878 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4879 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4881 span_err!(ccx.tcx.sess, e.span, E0079,
4882 "expected signed integer constant");
4885 span_err!(ccx.tcx.sess, e.span, E0080,
4886 "expected constant: {}", *err);
4893 // Check for duplicate discriminant values
4894 match disr_vals.iter().position(|&x| x == current_disr_val) {
4896 span_err!(ccx.tcx.sess, v.span, E0081,
4897 "discriminant value `{}` already exists", disr_vals[i]);
4898 span_note!(ccx.tcx.sess, ccx.tcx().map.span(variants[i].id.node),
4899 "conflicting discriminant here")
4903 // Check for unrepresentable discriminant values
4905 attr::ReprAny | attr::ReprExtern => (),
4906 attr::ReprInt(sp, ity) => {
4907 if !disr_in_range(ccx, ity, current_disr_val) {
4908 span_err!(ccx.tcx.sess, v.span, E0082,
4909 "discriminant value outside specified type");
4910 span_note!(ccx.tcx.sess, sp,
4911 "discriminant type specified here");
4914 attr::ReprPacked => {
4915 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4918 disr_vals.push(current_disr_val);
4920 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4922 prev_disr_val = Some(current_disr_val);
4924 variants.push(variant_info);
4930 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4931 .as_slice().get(0).unwrap_or(&attr::ReprAny);
4933 if hint != attr::ReprAny && vs.len() <= 1 {
4935 span_err!(ccx.tcx.sess, sp, E0083,
4936 "unsupported representation for univariant enum");
4938 span_err!(ccx.tcx.sess, sp, E0084,
4939 "unsupported representation for zero-variant enum");
4943 let variants = do_check(ccx, vs, id, hint);
4945 // cache so that ty::enum_variants won't repeat this work
4946 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4948 check_representable(ccx.tcx, sp, id, "enum");
4950 // Check that it is possible to instantiate this enum:
4952 // This *sounds* like the same that as representable, but it's
4953 // not. See def'n of `check_instantiable()` for details.
4954 check_instantiable(ccx.tcx, sp, id);
4957 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4958 lookup_def_ccx(fcx.ccx, sp, id)
4961 // Returns the type parameter count and the type for the given definition.
4962 pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4967 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4968 let typ = fcx.local_ty(sp, nid);
4969 return no_params(typ);
4971 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4972 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4973 def::DefStruct(id) | def::DefConst(id) => {
4974 return ty::lookup_item_type(fcx.ccx.tcx, id);
4978 def::DefAssociatedTy(..) |
4980 def::DefTyParam(..)=> {
4981 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4983 def::DefMod(..) | def::DefForeignMod(..) => {
4984 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4986 def::DefUse(..) => {
4987 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4989 def::DefRegion(..) => {
4990 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4992 def::DefTyParamBinder(..) => {
4993 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4995 def::DefLabel(..) => {
4996 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4998 def::DefSelfTy(..) => {
4999 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5004 // Instantiates the given path, which must refer to an item with the given
5005 // number of type parameters and type.
5006 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5008 polytype: Polytype<'tcx>,
5011 node_id: ast::NodeId) {
5012 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
5013 path.repr(fcx.tcx()),
5014 def.repr(fcx.tcx()),
5016 polytype.repr(fcx.tcx()));
5018 // We need to extract the type parameters supplied by the user in
5019 // the path `path`. Due to the current setup, this is a bit of a
5020 // tricky-process; the problem is that resolve only tells us the
5021 // end-point of the path resolution, and not the intermediate steps.
5022 // Luckily, we can (at least for now) deduce the intermediate steps
5023 // just from the end-point.
5025 // There are basically three cases to consider:
5027 // 1. Reference to a *type*, such as a struct or enum:
5029 // mod a { struct Foo<T> { ... } }
5031 // Because we don't allow types to be declared within one
5032 // another, a path that leads to a type will always look like
5033 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
5034 // that only the final segment can have type parameters, and
5035 // they are located in the TypeSpace.
5037 // *Note:* Generally speaking, references to types don't
5038 // actually pass through this function, but rather the
5039 // `ast_ty_to_ty` function in `astconv`. However, in the case
5040 // of struct patterns (and maybe literals) we do invoke
5041 // `instantiate_path` to get the general type of an instance of
5042 // a struct. (In these cases, there are actually no type
5043 // parameters permitted at present, but perhaps we will allow
5044 // them in the future.)
5046 // 1b. Reference to a enum variant or tuple-like struct:
5048 // struct foo<T>(...)
5049 // enum E<T> { foo(...) }
5051 // In these cases, the parameters are declared in the type
5054 // 2. Reference to a *fn item*:
5058 // In this case, the path will again always have the form
5059 // `a::b::foo::<T>` where only the final segment should have
5060 // type parameters. However, in this case, those parameters are
5061 // declared on a value, and hence are in the `FnSpace`.
5063 // 3. Reference to a *method*:
5065 // impl<A> SomeStruct<A> {
5069 // Here we can have a path like
5070 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5071 // may appear in two places. The penultimate segment,
5072 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5073 // final segment, `foo::<B>` contains parameters in fn space.
5075 // The first step then is to categorize the segments appropriately.
5077 assert!(path.segments.len() >= 1);
5078 let mut segment_spaces;
5080 // Case 1 and 1b. Reference to a *type* or *enum variant*.
5081 def::DefSelfTy(..) |
5082 def::DefStruct(..) |
5083 def::DefVariant(..) |
5084 def::DefTyParamBinder(..) |
5086 def::DefAssociatedTy(..) |
5088 def::DefPrimTy(..) |
5089 def::DefTyParam(..) => {
5090 // Everything but the final segment should have no
5091 // parameters at all.
5092 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5093 segment_spaces.push(Some(subst::TypeSpace));
5096 // Case 2. Reference to a top-level value.
5099 def::DefStatic(..) => {
5100 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5101 segment_spaces.push(Some(subst::FnSpace));
5104 // Case 3. Reference to a method.
5105 def::DefStaticMethod(_, providence) |
5106 def::DefMethod(_, _, providence) => {
5107 assert!(path.segments.len() >= 2);
5110 def::FromTrait(trait_did) => {
5111 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
5113 def::FromImpl(_) => {}
5116 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
5117 segment_spaces.push(Some(subst::TypeSpace));
5118 segment_spaces.push(Some(subst::FnSpace));
5121 // Other cases. Various nonsense that really shouldn't show up
5122 // here. If they do, an error will have been reported
5123 // elsewhere. (I hope)
5125 def::DefForeignMod(..) |
5128 def::DefRegion(..) |
5130 def::DefUpvar(..) => {
5131 segment_spaces = Vec::from_elem(path.segments.len(), None);
5134 assert_eq!(segment_spaces.len(), path.segments.len());
5136 debug!("segment_spaces={}", segment_spaces);
5138 // Next, examine the definition, and determine how many type
5139 // parameters we expect from each space.
5140 let type_defs = &polytype.generics.types;
5141 let region_defs = &polytype.generics.regions;
5143 // Now that we have categorized what space the parameters for each
5144 // segment belong to, let's sort out the parameters that the user
5145 // provided (if any) into their appropriate spaces. We'll also report
5146 // errors if type parameters are provided in an inappropriate place.
5147 let mut substs = Substs::empty();
5148 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5151 report_error_if_segment_contains_type_parameters(fcx, segment);
5155 push_explicit_parameters_from_segment_to_substs(fcx,
5166 // Now we have to compare the types that the user *actually*
5167 // provided against the types that were *expected*. If the user
5168 // did not provide any types, then we want to substitute inference
5169 // variables. If the user provided some types, we may still need
5170 // to add defaults. If the user provided *too many* types, that's
5172 for &space in ParamSpace::all().iter() {
5173 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5174 assert_eq!(substs.types.len(space), type_defs.len(space));
5176 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5177 assert_eq!(substs.regions().len(space), region_defs.len(space));
5180 // The things we are substituting into the type should not contain
5181 // escaping late-bound regions.
5182 assert!(!substs.has_regions_escaping_depth(0));
5184 // In the case of static items taken from impls, there may be
5185 // late-bound regions associated with the impl (not declared on
5186 // the fn itself). Those should be replaced with fresh variables
5187 // now. These can appear either on the type being referenced, or
5188 // on the associated bounds.
5189 let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs);
5190 let (ty_late_bound, bounds) =
5191 fcx.infcx().replace_late_bound_regions_with_fresh_var(
5194 &ty::bind((polytype.ty, bounds))).0.value;
5196 debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx()));
5197 debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx()));
5199 fcx.add_obligations_for_parameters(
5200 traits::ObligationCause::new(span, traits::ItemObligation(def.def_id())),
5204 // Substitute the values for the type parameters into the type of
5205 // the referenced item.
5206 let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs);
5208 debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx()));
5210 fcx.write_ty(node_id, ty_substituted);
5211 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
5214 fn report_error_if_segment_contains_type_parameters(
5216 segment: &ast::PathSegment)
5218 for typ in segment.parameters.types().iter() {
5219 span_err!(fcx.tcx().sess, typ.span, E0085,
5220 "type parameters may not appear here");
5224 for lifetime in segment.parameters.lifetimes().iter() {
5225 span_err!(fcx.tcx().sess, lifetime.span, E0086,
5226 "lifetime parameters may not appear here");
5231 /// Finds the parameters that the user provided and adds them to `substs`. If too many
5232 /// parameters are provided, then reports an error and clears the output vector.
5234 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
5235 /// use inference variables. This seems less likely to lead to derived errors.
5237 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
5238 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
5239 /// here because we can easily use the precise span of the N+1'th parameter.
5240 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
5241 fcx: &FnCtxt<'a, 'tcx>,
5242 space: subst::ParamSpace,
5244 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5245 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5246 segment: &ast::PathSegment,
5247 substs: &mut Substs<'tcx>)
5249 match segment.parameters {
5250 ast::AngleBracketedParameters(ref data) => {
5251 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
5252 fcx, space, type_defs, region_defs, data, substs);
5255 ast::ParenthesizedParameters(ref data) => {
5256 push_explicit_parenthesized_parameters_from_segment_to_substs(
5257 fcx, space, span, type_defs, data, substs);
5262 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
5263 fcx: &FnCtxt<'a, 'tcx>,
5264 space: subst::ParamSpace,
5265 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5266 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5267 data: &ast::AngleBracketedParameterData,
5268 substs: &mut Substs<'tcx>)
5271 let type_count = type_defs.len(space);
5272 assert_eq!(substs.types.len(space), 0);
5273 for (i, typ) in data.types.iter().enumerate() {
5274 let t = fcx.to_ty(&**typ);
5276 substs.types.push(space, t);
5277 } else if i == type_count {
5278 span_err!(fcx.tcx().sess, typ.span, E0087,
5279 "too many type parameters provided: \
5280 expected at most {} parameter(s), \
5281 found {} parameter(s)",
5282 type_count, data.types.len());
5283 substs.types.truncate(space, 0);
5289 let region_count = region_defs.len(space);
5290 assert_eq!(substs.regions().len(space), 0);
5291 for (i, lifetime) in data.lifetimes.iter().enumerate() {
5292 let r = ast_region_to_region(fcx.tcx(), lifetime);
5293 if i < region_count {
5294 substs.mut_regions().push(space, r);
5295 } else if i == region_count {
5296 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5297 "too many lifetime parameters provided: \
5298 expected {} parameter(s), found {} parameter(s)",
5300 data.lifetimes.len());
5301 substs.mut_regions().truncate(space, 0);
5308 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
5309 /// but intended for `Foo(A,B) -> C` form. This expands to
5310 /// roughly the same thing as `Foo<(A,B),C>`. One important
5311 /// difference has to do with the treatment of anonymous
5312 /// regions, which are translated into bound regions (NYI).
5313 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
5314 fcx: &FnCtxt<'a, 'tcx>,
5315 space: subst::ParamSpace,
5317 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5318 data: &ast::ParenthesizedParameterData,
5319 substs: &mut Substs<'tcx>)
5321 let type_count = type_defs.len(space);
5323 span_err!(fcx.tcx().sess, span, E0167,
5324 "parenthesized form always supplies 2 type parameters, \
5325 but only {} parameter(s) were expected",
5329 let input_tys: Vec<Ty> =
5330 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
5333 ty::mk_tup(fcx.tcx(), input_tys);
5335 if type_count >= 1 {
5336 substs.types.push(space, tuple_ty);
5339 let output_ty: Option<Ty> =
5340 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
5343 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
5345 if type_count >= 2 {
5346 substs.types.push(space, output_ty);
5350 fn adjust_type_parameters<'a, 'tcx>(
5351 fcx: &FnCtxt<'a, 'tcx>,
5354 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5355 substs: &mut Substs<'tcx>)
5357 let provided_len = substs.types.len(space);
5358 let desired = defs.get_slice(space);
5359 let required_len = desired.iter()
5360 .take_while(|d| d.default.is_none())
5363 debug!("adjust_type_parameters(space={}, \
5372 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5373 assert!(provided_len <= desired.len());
5375 // Nothing specified at all: supply inference variables for
5377 if provided_len == 0 {
5378 substs.types.replace(space,
5379 fcx.infcx().next_ty_vars(desired.len()));
5383 // Too few parameters specified: report an error and use Err
5385 if provided_len < required_len {
5387 if desired.len() != required_len { "at least " } else { "" };
5388 span_err!(fcx.tcx().sess, span, E0089,
5389 "too few type parameters provided: expected {}{} parameter(s) \
5390 , found {} parameter(s)",
5391 qualifier, required_len, provided_len);
5392 substs.types.replace(space,
5393 Vec::from_elem(desired.len(), ty::mk_err()));
5397 // Otherwise, add in any optional parameters that the user
5398 // omitted. The case of *too many* parameters is handled
5400 // push_explicit_parameters_from_segment_to_substs(). Note
5401 // that the *default* type are expressed in terms of all prior
5402 // parameters, so we have to substitute as we go with the
5403 // partial substitution that we have built up.
5404 for i in range(provided_len, desired.len()) {
5405 let default = desired[i].default.unwrap();
5406 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5407 substs.types.push(space, default);
5409 assert_eq!(substs.types.len(space), desired.len());
5411 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5414 fn adjust_region_parameters(
5418 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5419 substs: &mut Substs)
5421 let provided_len = substs.mut_regions().len(space);
5422 let desired = defs.get_slice(space);
5424 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5425 assert!(provided_len <= desired.len());
5427 // If nothing was provided, just use inference variables.
5428 if provided_len == 0 {
5429 substs.mut_regions().replace(
5431 fcx.infcx().region_vars_for_defs(span, desired));
5435 // If just the right number were provided, everybody is happy.
5436 if provided_len == desired.len() {
5440 // Otherwise, too few were provided. Report an error and then
5441 // use inference variables.
5442 span_err!(fcx.tcx().sess, span, E0090,
5443 "too few lifetime parameters provided: expected {} parameter(s), \
5444 found {} parameter(s)",
5445 desired.len(), provided_len);
5447 substs.mut_regions().replace(
5449 fcx.infcx().region_vars_for_defs(span, desired));
5453 // Resolves `typ` by a single level if `typ` is a type variable. If no
5454 // resolution is possible, then an error is reported.
5455 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5456 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5457 // If `ty` is a type variable, see whether we already know what it is.
5458 ty = fcx.infcx().shallow_resolve(ty);
5460 // If not, try resolve pending fcx obligations. Those can shed light.
5462 // FIXME(#18391) -- This current strategy can lead to bad performance in
5463 // extreme cases. We probably ought to smarter in general about
5464 // only resolving when we need help and only resolving obligations
5465 // will actually help.
5466 if ty::type_is_ty_var(ty) {
5467 vtable::select_fcx_obligations_where_possible(fcx);
5468 ty = fcx.infcx().shallow_resolve(ty);
5472 if ty::type_is_ty_var(ty) {
5473 fcx.type_error_message(sp, |_actual| {
5474 "the type of this value must be known in this \
5475 context".to_string()
5477 demand::suptype(fcx, sp, ty::mk_err(), ty);
5484 // Returns the one-level-deep structure of the given type.
5485 pub fn structure_of<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, typ: Ty<'tcx>)
5486 -> &'tcx ty::sty<'tcx> {
5487 &structurally_resolved_type(fcx, sp, typ).sty
5490 // Returns true if b contains a break that can exit from b
5491 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5492 // First: is there an unlabeled break immediately
5494 (loop_query(&*b, |e| {
5496 ast::ExprBreak(_) => true,
5500 // Second: is there a labeled break with label
5501 // <id> nested anywhere inside the loop?
5502 (block_query(b, |e| {
5504 ast::ExprBreak(Some(_)) => {
5505 match cx.def_map.borrow().get(&e.id) {
5506 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5514 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5516 tps: &OwnedSlice<ast::TyParam>,
5518 debug!("check_bounds_are_used(n_tps={}, ty={})",
5519 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5521 // make a vector of booleans initially false, set to true when used
5522 if tps.len() == 0u { return; }
5523 let mut tps_used = Vec::from_elem(tps.len(), false);
5525 ty::walk_ty(ty, |t| {
5527 ty::ty_param(ParamTy {idx, ..}) => {
5528 debug!("Found use of ty param num {}", idx);
5529 tps_used[idx] = true;
5535 for (i, b) in tps_used.iter().enumerate() {
5537 span_err!(ccx.tcx.sess, span, E0091,
5538 "type parameter `{}` is unused",
5539 token::get_ident(tps[i].ident));
5544 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5545 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: uint) -> Ty<'tcx> {
5546 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5550 let name = token::get_ident(it.ident);
5551 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5552 let split : Vec<&str> = name.get().split('_').collect();
5553 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5555 //We only care about the operation here
5556 let (n_tps, inputs, output) = match split[1] {
5557 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5561 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5563 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5566 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5567 "min" | "umax" | "umin" => {
5568 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5572 (0, Vec::new(), ty::mk_nil(tcx))
5575 span_err!(tcx.sess, it.span, E0092,
5576 "unrecognized atomic operation function: `{}`", op);
5580 (n_tps, inputs, ty::FnConverging(output))
5581 } else if name.get() == "abort" || name.get() == "unreachable" {
5582 (0, Vec::new(), ty::FnDiverging)
5584 let (n_tps, inputs, output) = match name.get() {
5585 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5587 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5588 "init" => (1u, Vec::new(), param(ccx, 0u)),
5589 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5590 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5591 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5592 "move_val_init" => {
5595 ty::mk_mut_rptr(tcx, ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0)),
5601 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5602 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5605 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5607 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5609 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5611 mutbl: ast::MutImmutable
5613 (1u, Vec::new(), td_ptr)
5616 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5620 ty::mk_struct(ccx.tcx, did,
5621 subst::Substs::empty())),
5623 tcx.sess.span_fatal(it.span, msg.as_slice());
5630 ty::mk_ptr(tcx, ty::mt {
5632 mutbl: ast::MutImmutable
5636 ty::mk_ptr(tcx, ty::mt {
5638 mutbl: ast::MutImmutable
5641 "copy_memory" | "copy_nonoverlapping_memory" |
5642 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5645 ty::mk_ptr(tcx, ty::mt {
5647 mutbl: ast::MutMutable
5649 ty::mk_ptr(tcx, ty::mt {
5651 mutbl: ast::MutImmutable
5657 "set_memory" | "volatile_set_memory" => {
5660 ty::mk_ptr(tcx, ty::mt {
5662 mutbl: ast::MutMutable
5669 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5670 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5673 vec!( ty::mk_f32(), ty::mk_i32() ),
5678 vec!( ty::mk_f64(), ty::mk_i32() ),
5681 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5682 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5683 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5684 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5687 vec!( ty::mk_f32(), ty::mk_f32() ),
5692 vec!( ty::mk_f64(), ty::mk_f64() ),
5695 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5696 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5697 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5698 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5699 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5700 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5701 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5702 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5703 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5704 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5707 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5712 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5715 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5716 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5717 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5718 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5719 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5720 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5721 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5722 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5723 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5724 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5725 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5726 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5727 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5728 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5729 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5730 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5731 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5732 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5733 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5734 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5735 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5736 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5737 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5738 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5739 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5740 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5741 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5742 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5743 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5744 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5745 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5748 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5750 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5752 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5753 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5754 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5756 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5757 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5758 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5760 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5761 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5762 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5764 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5765 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5766 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5768 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5769 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5770 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5772 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5773 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5774 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5776 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5777 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5778 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5780 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5781 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5782 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5784 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5786 "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
5789 span_err!(tcx.sess, it.span, E0093,
5790 "unrecognized intrinsic function: `{}`", *other);
5794 (n_tps, inputs, ty::FnConverging(output))
5796 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5797 fn_style: ast::UnsafeFn,
5798 abi: abi::RustIntrinsic,
5805 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5806 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5807 if i_n_tps != n_tps {
5808 span_err!(tcx.sess, it.span, E0094,
5809 "intrinsic has wrong number of type \
5810 parameters: found {}, expected {}",
5813 require_same_types(tcx,
5820 format!("intrinsic has wrong type: expected `{}`",
5821 ppaux::ty_to_string(ccx.tcx, fty))
5826 impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
5827 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
5828 format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5829 self.sub_region.repr(tcx),
5830 self.sup_type.repr(tcx),
5831 self.origin.repr(tcx))