1 // Copyright 2012-2015 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::Expectation::*;
81 pub use self::compare_method::{compare_impl_method, compare_const_impl};
82 use self::TupleArgumentsFlag::*;
84 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
85 use check::_match::pat_ctxt;
86 use fmt_macros::{Parser, Piece, Position};
87 use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
90 use middle::infer::type_variable;
91 use middle::pat_util::{self, pat_id_map};
92 use middle::privacy::{AllPublic, LastMod};
93 use middle::region::{self, CodeExtent};
94 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
95 use middle::traits::{self, report_fulfillment_errors};
96 use middle::ty::{FnSig, GenericPredicates, TypeScheme};
97 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
98 use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
99 use middle::ty::{MethodCall, MethodCallee};
100 use middle::ty_fold::{TypeFolder, TypeFoldable};
101 use require_c_abi_if_variadic;
102 use rscope::{ElisionFailureInfo, RegionScope};
103 use session::Session;
104 use {CrateCtxt, lookup_full_def, require_same_types};
107 use util::common::{block_query, ErrorReported, indenter, loop_query};
108 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
109 use util::lev_distance::lev_distance;
111 use std::cell::{Cell, Ref, RefCell};
112 use std::collections::HashSet;
113 use std::mem::replace;
115 use syntax::{self, abi, attr};
116 use syntax::attr::AttrMetaMethods;
117 use syntax::ast::{self, DefId, Visibility};
118 use syntax::ast_util::{self, local_def};
119 use syntax::codemap::{self, Span};
120 use syntax::feature_gate::emit_feature_err;
121 use syntax::owned_slice::OwnedSlice;
122 use syntax::parse::token;
123 use syntax::print::pprust;
125 use syntax::visit::{self, Visitor};
143 /// closures defined within the function. For example:
146 /// bar(move|| { ... })
149 /// Here, the function `foo()` and the closure passed to
150 /// `bar()` will each have their own `FnCtxt`, but they will
151 /// share the inherited fields.
152 pub struct Inherited<'a, 'tcx: 'a> {
153 infcx: infer::InferCtxt<'a, 'tcx>,
154 locals: RefCell<NodeMap<Ty<'tcx>>>,
156 tables: &'a RefCell<ty::Tables<'tcx>>,
158 // A mapping from each fn's id to its signature, with all bound
159 // regions replaced with free ones. Unlike the other tables, this
160 // one is never copied into the tcx: it is only used by regionck.
161 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
163 // When we process a call like `c()` where `c` is a closure type,
164 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
165 // `FnOnce` closure. In that case, we defer full resolution of the
166 // call until upvar inference can kick in and make the
167 // decision. We keep these deferred resolutions grouped by the
168 // def-id of the closure, so that once we decide, we can easily go
169 // back and process them.
170 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
172 deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
175 trait DeferredCallResolution<'tcx> {
176 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
179 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
181 /// When type-checking an expression, we propagate downward
182 /// whatever type hint we are able in the form of an `Expectation`.
183 #[derive(Copy, Clone, Debug)]
184 pub enum Expectation<'tcx> {
185 /// We know nothing about what type this expression should have.
188 /// This expression should have the type given (or some subtype)
189 ExpectHasType(Ty<'tcx>),
191 /// This expression will be cast to the `Ty`
192 ExpectCastableToType(Ty<'tcx>),
194 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
195 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
196 ExpectRvalueLikeUnsized(Ty<'tcx>),
199 impl<'tcx> Expectation<'tcx> {
200 // Disregard "castable to" expectations because they
201 // can lead us astray. Consider for example `if cond
202 // {22} else {c} as u8` -- if we propagate the
203 // "castable to u8" constraint to 22, it will pick the
204 // type 22u8, which is overly constrained (c might not
205 // be a u8). In effect, the problem is that the
206 // "castable to" expectation is not the tightest thing
207 // we can say, so we want to drop it in this case.
208 // The tightest thing we can say is "must unify with
209 // else branch". Note that in the case of a "has type"
210 // constraint, this limitation does not hold.
212 // If the expected type is just a type variable, then don't use
213 // an expected type. Otherwise, we might write parts of the type
214 // when checking the 'then' block which are incompatible with the
216 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
218 ExpectHasType(ety) => {
219 let ety = fcx.infcx().shallow_resolve(ety);
220 if !ety.is_ty_var() {
226 ExpectRvalueLikeUnsized(ety) => {
227 ExpectRvalueLikeUnsized(ety)
234 #[derive(Copy, Clone)]
235 pub struct UnsafetyState {
236 pub def: ast::NodeId,
237 pub unsafety: ast::Unsafety,
238 pub unsafe_push_count: u32,
243 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
244 UnsafetyState { def: def, unsafety: unsafety, unsafe_push_count: 0, from_fn: true }
247 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
248 match self.unsafety {
249 // If this unsafe, then if the outer function was already marked as
250 // unsafe we shouldn't attribute the unsafe'ness to the block. This
251 // way the block can be warned about instead of ignoring this
252 // extraneous block (functions are never warned about).
253 ast::Unsafety::Unsafe if self.from_fn => *self,
256 let (unsafety, def, count) = match blk.rules {
257 ast::PushUnsafeBlock(..) =>
258 (unsafety, blk.id, self.unsafe_push_count.checked_add(1).unwrap()),
259 ast::PopUnsafeBlock(..) =>
260 (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
261 ast::UnsafeBlock(..) =>
262 (ast::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
264 (unsafety, self.def, self.unsafe_push_count),
266 UnsafetyState{ def: def,
268 unsafe_push_count: count,
276 pub struct FnCtxt<'a, 'tcx: 'a> {
277 body_id: ast::NodeId,
279 // This flag is set to true if, during the writeback phase, we encounter
280 // a type error in this function.
281 writeback_errors: Cell<bool>,
283 // Number of errors that had been reported when we started
284 // checking this function. On exit, if we find that *more* errors
285 // have been reported, we will skip regionck and other work that
286 // expects the types within the function to be consistent.
287 err_count_on_creation: usize,
289 ret_ty: ty::FnOutput<'tcx>,
291 ps: RefCell<UnsafetyState>,
293 inh: &'a Inherited<'a, 'tcx>,
295 ccx: &'a CrateCtxt<'a, 'tcx>,
298 impl<'a, 'tcx> Inherited<'a, 'tcx> {
299 fn new(tcx: &'a ty::ctxt<'tcx>,
300 tables: &'a RefCell<ty::Tables<'tcx>>,
301 param_env: ty::ParameterEnvironment<'a, 'tcx>)
302 -> Inherited<'a, 'tcx> {
305 infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), true),
306 locals: RefCell::new(NodeMap()),
308 fn_sig_map: RefCell::new(NodeMap()),
309 deferred_call_resolutions: RefCell::new(DefIdMap()),
310 deferred_cast_checks: RefCell::new(Vec::new()),
314 fn normalize_associated_types_in<T>(&self,
316 body_id: ast::NodeId,
319 where T : TypeFoldable<'tcx> + HasTypeFlags
321 let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
322 assoc::normalize_associated_types_in(&self.infcx,
331 // Used by check_const and check_enum_variants
332 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
333 inh: &'a Inherited<'a, 'tcx>,
334 rty: ty::FnOutput<'tcx>,
335 body_id: ast::NodeId)
336 -> FnCtxt<'a, 'tcx> {
339 writeback_errors: Cell::new(false),
340 err_count_on_creation: ccx.tcx.sess.err_count(),
342 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
348 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
349 tables: &'a RefCell<ty::Tables<'tcx>>)
350 -> Inherited<'a, 'tcx> {
351 // It's kind of a kludge to manufacture a fake function context
352 // and statement context, but we might as well do write the code only once
353 let param_env = ccx.tcx.empty_parameter_environment();
354 Inherited::new(ccx.tcx, &tables, param_env)
357 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
358 struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
360 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
361 fn visit_item(&mut self, i: &'tcx ast::Item) {
362 check_item_type(self.ccx, i);
363 visit::walk_item(self, i);
366 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
368 ast::TyFixedLengthVec(_, ref expr) => {
369 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
374 visit::walk_ty(self, t);
378 impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
379 fn visit_item(&mut self, i: &'tcx ast::Item) {
380 check_item_body(self.ccx, i);
381 visit::walk_item(self, i);
385 pub fn check_item_types(ccx: &CrateCtxt) {
386 let krate = ccx.tcx.map.krate();
387 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
388 visit::walk_crate(&mut visit, krate);
390 // If types are not well-formed, it leads to all manner of errors
391 // downstream, so stop reporting errors at this point.
392 ccx.tcx.sess.abort_if_errors();
394 let mut visit = CheckItemTypesVisitor { ccx: ccx };
395 visit::walk_crate(&mut visit, krate);
397 ccx.tcx.sess.abort_if_errors();
399 let mut visit = CheckItemBodiesVisitor { ccx: ccx };
400 visit::walk_crate(&mut visit, krate);
402 ccx.tcx.sess.abort_if_errors();
404 for drop_method_did in ccx.tcx.destructors.borrow().iter() {
405 if drop_method_did.krate == ast::LOCAL_CRATE {
406 let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
407 match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
410 assert!(ccx.tcx.sess.has_errors());
416 ccx.tcx.sess.abort_if_errors();
419 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
420 decl: &'tcx ast::FnDecl,
421 body: &'tcx ast::Block,
425 param_env: ty::ParameterEnvironment<'a, 'tcx>)
428 ty::TyBareFn(_, ref fn_ty) => {
429 let tables = RefCell::new(ty::Tables::empty());
430 let inh = Inherited::new(ccx.tcx, &tables, param_env);
432 // Compute the fty from point of view of inside fn.
434 fn_ty.sig.subst(ccx.tcx, &inh.infcx.parameter_environment.free_substs);
436 ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id),
439 inh.normalize_associated_types_in(body.span,
443 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
444 decl, fn_id, body, &inh);
446 fcx.select_all_obligations_and_apply_defaults();
447 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
448 fcx.select_all_obligations_or_error();
451 fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
453 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
454 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
456 _ => ccx.tcx.sess.impossible_case(body.span,
457 "check_bare_fn: function type expected")
461 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
462 fcx: &'a FnCtxt<'a, 'tcx>
465 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
466 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
469 // infer the variable's type
470 let var_ty = self.fcx.infcx().next_ty_var();
471 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
475 // take type that the user specified
476 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
483 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
484 // Add explicitly-declared locals.
485 fn visit_local(&mut self, local: &'tcx ast::Local) {
486 let o_ty = match local.ty {
487 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
490 self.assign(local.span, local.id, o_ty);
491 debug!("Local variable {:?} is assigned type {}",
493 self.fcx.infcx().ty_to_string(
494 self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
495 visit::walk_local(self, local);
498 // Add pattern bindings.
499 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
500 if let ast::PatIdent(_, ref path1, _) = p.node {
501 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
502 let var_ty = self.assign(p.span, p.id, None);
504 self.fcx.require_type_is_sized(var_ty, p.span,
505 traits::VariableType(p.id));
507 debug!("Pattern binding {} is assigned to {} with type {:?}",
508 token::get_ident(path1.node),
509 self.fcx.infcx().ty_to_string(
510 self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
514 visit::walk_pat(self, p);
517 fn visit_block(&mut self, b: &'tcx ast::Block) {
518 // non-obvious: the `blk` variable maps to region lb, so
519 // we have to keep this up-to-date. This
520 // is... unfortunate. It'd be nice to not need this.
521 visit::walk_block(self, b);
524 // Since an expr occurs as part of the type fixed size arrays we
525 // need to record the type for that node
526 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
528 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
529 self.visit_ty(&**ty);
530 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
532 _ => visit::walk_ty(self, t)
536 // Don't descend into fns and items
537 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
538 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
539 fn visit_item(&mut self, _: &ast::Item) { }
543 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
544 /// body and returns the function context used for that purpose, since in the case of a fn item
545 /// there is still a bit more to do.
548 /// * inherited: other fields inherited from the enclosing fn (if any)
549 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
550 unsafety: ast::Unsafety,
551 unsafety_id: ast::NodeId,
552 fn_sig: &ty::FnSig<'tcx>,
553 decl: &'tcx ast::FnDecl,
555 body: &'tcx ast::Block,
556 inherited: &'a Inherited<'a, 'tcx>)
560 let err_count_on_creation = tcx.sess.err_count();
562 let arg_tys = &fn_sig.inputs;
563 let ret_ty = fn_sig.output;
565 debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
570 // Create the function context. This is either derived from scratch or,
571 // in the case of function expressions, based on the outer context.
574 writeback_errors: Cell::new(false),
575 err_count_on_creation: err_count_on_creation,
577 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
582 // Remember return type so that regionck can access it later.
583 let mut fn_sig_tys: Vec<Ty> =
588 if let ty::FnConverging(ret_ty) = ret_ty {
589 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
590 fn_sig_tys.push(ret_ty);
593 debug!("fn-sig-map: fn_id={} fn_sig_tys={:?}",
597 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
600 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
602 // Add formal parameters.
603 for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
604 // Create type variables for each argument.
605 pat_util::pat_bindings(
608 |_bm, pat_id, sp, _path| {
609 let var_ty = visit.assign(sp, pat_id, None);
610 fcx.require_type_is_sized(var_ty, sp,
611 traits::VariableType(pat_id));
614 // Check the pattern.
617 map: pat_id_map(&tcx.def_map, &*input.pat),
619 _match::check_pat(&pcx, &*input.pat, *arg_ty);
622 visit.visit_block(body);
625 check_block_with_expected(&fcx, body, match ret_ty {
626 ty::FnConverging(result_type) => ExpectHasType(result_type),
627 ty::FnDiverging => NoExpectation
630 for (input, arg) in decl.inputs.iter().zip(arg_tys) {
631 fcx.write_ty(input.id, arg);
637 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
640 check_representable(tcx, span, id, "struct");
641 check_instantiable(tcx, span, id);
643 if tcx.lookup_simd(local_def(id)) {
644 check_simd(tcx, span, id);
648 pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
649 debug!("check_item_type(it.id={}, it.ident={})",
651 ccx.tcx.item_path_str(local_def(it.id)));
652 let _indenter = indenter();
654 // Consts can play a role in type-checking, so they are included here.
655 ast::ItemStatic(_, _, ref e) |
656 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
657 ast::ItemEnum(ref enum_definition, _) => {
658 check_enum_variants(ccx,
660 &enum_definition.variants,
663 ast::ItemFn(..) => {} // entirely within check_item_body
664 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
665 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
666 match ccx.tcx.impl_trait_ref(local_def(it.id)) {
667 Some(impl_trait_ref) => {
668 check_impl_items_against_trait(ccx,
676 ast::ItemTrait(_, ref generics, _, _) => {
677 check_trait_on_unimplemented(ccx, generics, it);
679 ast::ItemStruct(..) => {
680 check_struct(ccx, it.id, it.span);
682 ast::ItemTy(ref t, ref generics) => {
683 let pty_ty = ccx.tcx.node_id_to_type(it.id);
684 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
686 ast::ItemForeignMod(ref m) => {
687 if m.abi == abi::RustIntrinsic {
688 for item in &m.items {
689 check_intrinsic_type(ccx, &**item);
692 for item in &m.items {
693 let pty = ccx.tcx.lookup_item_type(local_def(item.id));
694 if !pty.generics.types.is_empty() {
695 span_err!(ccx.tcx.sess, item.span, E0044,
696 "foreign items may not have type parameters");
699 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
700 require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span);
705 _ => {/* nothing to do */ }
709 pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
710 debug!("check_item_body(it.id={}, it.ident={})",
712 ccx.tcx.item_path_str(local_def(it.id)));
713 let _indenter = indenter();
715 ast::ItemFn(ref decl, _, _, _, _, ref body) => {
716 let fn_pty = ccx.tcx.lookup_item_type(ast_util::local_def(it.id));
717 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
718 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
720 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
721 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
723 let impl_pty = ccx.tcx.lookup_item_type(ast_util::local_def(it.id));
725 for impl_item in impl_items {
726 match impl_item.node {
727 ast::ConstImplItem(_, ref expr) => {
728 check_const(ccx, impl_item.span, &*expr, impl_item.id)
730 ast::MethodImplItem(ref sig, ref body) => {
731 check_method_body(ccx, &impl_pty.generics, sig, body,
732 impl_item.id, impl_item.span);
734 ast::TypeImplItem(_) |
735 ast::MacImplItem(_) => {
736 // Nothing to do here.
741 ast::ItemTrait(_, _, _, ref trait_items) => {
742 let trait_def = ccx.tcx.lookup_trait_def(local_def(it.id));
743 for trait_item in trait_items {
744 match trait_item.node {
745 ast::ConstTraitItem(_, Some(ref expr)) => {
746 check_const(ccx, trait_item.span, &*expr, trait_item.id)
748 ast::MethodTraitItem(ref sig, Some(ref body)) => {
749 check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
751 check_method_body(ccx, &trait_def.generics, sig, body,
752 trait_item.id, trait_item.span);
754 ast::MethodTraitItem(ref sig, None) => {
755 check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
757 ast::ConstTraitItem(_, None) |
758 ast::TypeTraitItem(..) => {
764 _ => {/* nothing to do */ }
768 fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
770 constness: ast::Constness)
773 ast::Constness::NotConst => {
776 ast::Constness::Const => {
777 span_err!(ccx.tcx.sess, span, E0379, "trait fns cannot be declared const");
782 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
783 generics: &ast::Generics,
785 if let Some(ref attr) = item.attrs.iter().find(|a| {
786 a.check_name("rustc_on_unimplemented")
788 if let Some(ref istring) = attr.value_str() {
789 let parser = Parser::new(&istring);
790 let types = &*generics.ty_params;
791 for token in parser {
793 Piece::String(_) => (), // Normal string, no need to check it
794 Piece::NextArgument(a) => match a.position {
795 // `{Self}` is allowed
796 Position::ArgumentNamed(s) if s == "Self" => (),
797 // So is `{A}` if A is a type parameter
798 Position::ArgumentNamed(s) => match types.iter().find(|t| {
799 t.ident.as_str() == s
803 span_err!(ccx.tcx.sess, attr.span, E0230,
804 "there is no type parameter \
806 s, item.ident.as_str());
809 // `{:1}` and `{}` are not to be used
810 Position::ArgumentIs(_) | Position::ArgumentNext => {
811 span_err!(ccx.tcx.sess, attr.span, E0231,
812 "only named substitution \
813 parameters are allowed");
819 span_err!(ccx.tcx.sess, attr.span, E0232,
820 "this attribute must have a value, \
821 eg `#[rustc_on_unimplemented = \"foo\"]`")
826 /// Type checks a method body.
830 /// * `item_generics`: generics defined on the impl/trait that contains
832 /// * `self_bound`: bound for the `Self` type parameter, if any
833 /// * `method`: the method definition
834 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
835 item_generics: &ty::Generics<'tcx>,
836 sig: &'tcx ast::MethodSig,
837 body: &'tcx ast::Block,
838 id: ast::NodeId, span: Span) {
839 debug!("check_method_body(item_generics={:?}, id={})",
841 let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
843 let fty = ccx.tcx.node_id_to_type(id);
844 debug!("check_method_body: fty={:?}", fty);
846 check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
849 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
851 impl_trait_ref: &ty::TraitRef<'tcx>,
852 impl_items: &[P<ast::ImplItem>]) {
853 // Locate trait methods
855 let trait_items = tcx.trait_items(impl_trait_ref.def_id);
856 let mut overridden_associated_type = None;
858 // Check existing impl methods to see if they are both present in trait
859 // and compatible with trait signature
860 for impl_item in impl_items {
861 let ty_impl_item = ccx.tcx.impl_or_trait_item(local_def(impl_item.id));
862 let ty_trait_item = trait_items.iter()
863 .find(|ac| ac.name() == ty_impl_item.name())
865 // This is checked by resolve
866 tcx.sess.span_bug(impl_item.span,
867 &format!("impl-item `{}` is not a member of `{:?}`",
868 token::get_name(ty_impl_item.name()),
871 match impl_item.node {
872 ast::ConstImplItem(..) => {
873 let impl_const = match ty_impl_item {
874 ty::ConstTraitItem(ref cti) => cti,
875 _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
878 // Find associated const definition.
879 if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
880 compare_const_impl(ccx.tcx,
886 span_err!(tcx.sess, impl_item.span, E0323,
887 "item `{}` is an associated const, \
888 which doesn't match its trait `{:?}`",
889 token::get_name(impl_const.name),
893 ast::MethodImplItem(ref sig, ref body) => {
894 check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
896 let impl_method = match ty_impl_item {
897 ty::MethodTraitItem(ref mti) => mti,
898 _ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
901 if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
902 compare_impl_method(ccx.tcx,
909 span_err!(tcx.sess, impl_item.span, E0324,
910 "item `{}` is an associated method, \
911 which doesn't match its trait `{:?}`",
912 token::get_name(impl_method.name),
916 ast::TypeImplItem(_) => {
917 let impl_type = match ty_impl_item {
918 ty::TypeTraitItem(ref tti) => tti,
919 _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
922 if let &ty::TypeTraitItem(ref at) = ty_trait_item {
923 if let Some(_) = at.ty {
924 overridden_associated_type = Some(impl_item);
927 span_err!(tcx.sess, impl_item.span, E0325,
928 "item `{}` is an associated type, \
929 which doesn't match its trait `{:?}`",
930 token::get_name(impl_type.name),
934 ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
939 // Check for missing items from trait
940 let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
941 let associated_consts = tcx.associated_consts(impl_trait_ref.def_id);
942 let mut missing_items = Vec::new();
943 let mut invalidated_items = Vec::new();
944 let associated_type_overridden = overridden_associated_type.is_some();
945 for trait_item in trait_items.iter() {
947 ty::ConstTraitItem(ref associated_const) => {
948 let is_implemented = impl_items.iter().any(|ii| {
950 ast::ConstImplItem(..) => {
951 ii.ident.name == associated_const.name
957 associated_consts.iter().any(|ac| ac.default.is_some() &&
958 ac.name == associated_const.name);
961 missing_items.push(associated_const.name);
962 } else if associated_type_overridden {
963 invalidated_items.push(associated_const.name);
967 ty::MethodTraitItem(ref trait_method) => {
969 impl_items.iter().any(|ii| {
971 ast::MethodImplItem(..) => {
972 ii.ident.name == trait_method.name
978 provided_methods.iter().any(|m| m.name == trait_method.name);
981 missing_items.push(trait_method.name);
982 } else if associated_type_overridden {
983 invalidated_items.push(trait_method.name);
987 ty::TypeTraitItem(ref associated_type) => {
988 let is_implemented = impl_items.iter().any(|ii| {
990 ast::TypeImplItem(_) => {
991 ii.ident.name == associated_type.name
996 let is_provided = associated_type.ty.is_some();
999 missing_items.push(associated_type.name);
1000 } else if associated_type_overridden {
1001 invalidated_items.push(associated_type.name);
1008 if !missing_items.is_empty() {
1009 span_err!(tcx.sess, impl_span, E0046,
1010 "not all trait items implemented, missing: `{}`",
1011 missing_items.iter()
1012 .map(<ast::Name>::as_str)
1013 .collect::<Vec<_>>().join("`, `"))
1016 if !invalidated_items.is_empty() {
1017 let invalidator = overridden_associated_type.unwrap();
1018 span_err!(tcx.sess, invalidator.span, E0399,
1019 "the following trait items need to be reimplemented \
1020 as `{}` was overridden: `{}`",
1021 invalidator.ident.as_str(),
1022 invalidated_items.iter()
1023 .map(<ast::Name>::as_str)
1024 .collect::<Vec<_>>().join("`, `"))
1028 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1035 let tstr = fcx.infcx().ty_to_string(t_cast);
1036 fcx.type_error_message(span, |actual| {
1037 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1040 ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
1041 let mtstr = match mt {
1042 ast::MutMutable => "mut ",
1043 ast::MutImmutable => ""
1045 if t_cast.is_trait() {
1046 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1048 fcx.tcx().sess.span_suggestion(t_span,
1049 "try casting to a reference instead:",
1050 format!("&{}{}", mtstr, s));
1053 span_help!(fcx.tcx().sess, t_span,
1054 "did you mean `&{}{}`?", mtstr, tstr),
1057 span_help!(fcx.tcx().sess, span,
1058 "consider using an implicit coercion to `&{}{}` instead",
1063 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1065 fcx.tcx().sess.span_suggestion(t_span,
1066 "try casting to a `Box` instead:",
1067 format!("Box<{}>", s));
1070 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
1074 span_help!(fcx.tcx().sess, e_span,
1075 "consider using a box or reference as appropriate");
1078 fcx.write_error(id);
1082 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1083 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1085 fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
1086 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
1088 Ok(self.tcx().lookup_item_type(id))
1091 fn get_trait_def(&self, _: Span, id: ast::DefId)
1092 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
1094 Ok(self.tcx().lookup_trait_def(id))
1097 fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
1098 // all super predicates are ensured during collect pass
1102 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1103 Some(&self.inh.infcx.parameter_environment.free_substs)
1106 fn get_type_parameter_bounds(&self,
1108 node_id: ast::NodeId)
1109 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1111 let def = self.tcx().type_parameter_def(node_id);
1112 let r = self.inh.infcx.parameter_environment
1115 .filter_map(|predicate| {
1117 ty::Predicate::Trait(ref data) => {
1118 if data.0.self_ty().is_param(def.space, def.index) {
1119 Some(data.to_poly_trait_ref())
1133 fn trait_defines_associated_type_named(&self,
1134 trait_def_id: ast::DefId,
1135 assoc_name: ast::Name)
1138 let trait_def = self.ccx.tcx.lookup_trait_def(trait_def_id);
1139 trait_def.associated_type_names.contains(&assoc_name)
1142 fn ty_infer(&self, ty_param_def: Option<ty::TypeParameterDef<'tcx>>, span: Span) -> Ty<'tcx> {
1143 let default = ty_param_def.and_then(|t|
1144 t.default.map(|ty| type_variable::Default { ty: ty, origin_span: span, definition_span: span }));
1145 self.infcx().next_ty_var_with_default(default)
1148 fn projected_ty_from_poly_trait_ref(&self,
1150 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1151 item_name: ast::Name)
1154 let (trait_ref, _) =
1155 self.infcx().replace_late_bound_regions_with_fresh_var(
1157 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1160 self.normalize_associated_type(span, trait_ref, item_name)
1163 fn projected_ty(&self,
1165 trait_ref: ty::TraitRef<'tcx>,
1166 item_name: ast::Name)
1169 self.normalize_associated_type(span, trait_ref, item_name)
1173 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1174 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1176 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1180 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1181 &self.inh.infcx.parameter_environment
1184 pub fn sess(&self) -> &Session {
1188 pub fn err_count_since_creation(&self) -> usize {
1189 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1192 /// Resolves type variables in `ty` if possible. Unlike the infcx
1193 /// version, this version will also select obligations if it seems
1194 /// useful, in an effort to get more type information.
1195 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1196 debug!("resolve_type_vars_if_possible(ty={:?})", ty);
1198 // No TyInfer()? Nothing needs doing.
1199 if !ty.has_infer_types() {
1200 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1204 // If `ty` is a type variable, see whether we already know what it is.
1205 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1206 if !ty.has_infer_types() {
1207 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1211 // If not, try resolving any new fcx obligations that have cropped up.
1212 self.select_new_obligations();
1213 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1214 if !ty.has_infer_types() {
1215 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1219 // If not, try resolving *all* pending obligations as much as
1220 // possible. This can help substantially when there are
1221 // indirect dependencies that don't seem worth tracking
1223 self.select_obligations_where_possible();
1224 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1226 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1230 fn record_deferred_call_resolution(&self,
1231 closure_def_id: ast::DefId,
1232 r: DeferredCallResolutionHandler<'tcx>) {
1233 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1234 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1237 fn remove_deferred_call_resolutions(&self,
1238 closure_def_id: ast::DefId)
1239 -> Vec<DeferredCallResolutionHandler<'tcx>>
1241 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1242 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1245 pub fn tag(&self) -> String {
1246 let self_ptr: *const FnCtxt = self;
1247 format!("{:?}", self_ptr)
1250 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1251 match self.inh.locals.borrow().get(&nid) {
1254 self.tcx().sess.span_err(
1256 &format!("no type for local variable {}", nid));
1257 self.tcx().types.err
1263 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1264 debug!("write_ty({}, {:?}) in fcx {}",
1265 node_id, ty, self.tag());
1266 self.inh.tables.borrow_mut().node_types.insert(node_id, ty);
1269 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1270 if !substs.substs.is_noop() {
1271 debug!("write_substs({}, {:?}) in fcx {}",
1276 self.inh.tables.borrow_mut().item_substs.insert(node_id, substs);
1280 pub fn write_autoderef_adjustment(&self,
1281 node_id: ast::NodeId,
1283 self.write_adjustment(
1285 ty::AdjustDerefRef(ty::AutoDerefRef {
1293 pub fn write_adjustment(&self,
1294 node_id: ast::NodeId,
1295 adj: ty::AutoAdjustment<'tcx>) {
1296 debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
1298 if adj.is_identity() {
1302 self.inh.tables.borrow_mut().adjustments.insert(node_id, adj);
1305 /// Basically whenever we are converting from a type scheme into
1306 /// the fn body space, we always want to normalize associated
1307 /// types as well. This function combines the two.
1308 fn instantiate_type_scheme<T>(&self,
1310 substs: &Substs<'tcx>,
1313 where T : TypeFoldable<'tcx> + HasTypeFlags
1315 let value = value.subst(self.tcx(), substs);
1316 let result = self.normalize_associated_types_in(span, &value);
1317 debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
1324 /// As `instantiate_type_scheme`, but for the bounds found in a
1325 /// generic type scheme.
1326 fn instantiate_bounds(&self,
1328 substs: &Substs<'tcx>,
1329 bounds: &ty::GenericPredicates<'tcx>)
1330 -> ty::InstantiatedPredicates<'tcx>
1332 ty::InstantiatedPredicates {
1333 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1338 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1339 where T : TypeFoldable<'tcx> + HasTypeFlags
1341 self.inh.normalize_associated_types_in(span, self.body_id, value)
1344 fn normalize_associated_type(&self,
1346 trait_ref: ty::TraitRef<'tcx>,
1347 item_name: ast::Name)
1350 let cause = traits::ObligationCause::new(span,
1352 traits::ObligationCauseCode::MiscObligation);
1357 .normalize_projection_type(self.infcx(),
1359 trait_ref: trait_ref,
1360 item_name: item_name,
1365 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1366 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1367 /// Registers any trait obligations specified on `def_id` at the same time.
1369 /// Note that function is only intended to be used with types (notably, not fns). This is
1370 /// because it doesn't do any instantiation of late-bound regions.
1371 pub fn instantiate_type(&self,
1374 -> TypeAndSubsts<'tcx>
1377 self.tcx().lookup_item_type(def_id);
1378 let type_predicates =
1379 self.tcx().lookup_predicates(def_id);
1381 self.infcx().fresh_substs_for_generics(
1383 &type_scheme.generics);
1385 self.instantiate_bounds(span, &substs, &type_predicates);
1386 self.add_obligations_for_parameters(
1387 traits::ObligationCause::new(
1390 traits::ItemObligation(def_id)),
1393 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1401 /// Returns the type that this AST path refers to. If the path has no type
1402 /// parameters and the corresponding type has type parameters, fresh type
1403 /// and/or region variables are substituted.
1405 /// This is used when checking the constructor in struct literals.
1406 fn instantiate_struct_literal_ty(&self,
1409 -> TypeAndSubsts<'tcx>
1411 let tcx = self.tcx();
1413 let ty::TypeScheme { generics, ty: decl_ty } =
1414 tcx.lookup_item_type(did);
1416 let substs = astconv::ast_path_substs_for_ty(self, self,
1418 PathParamMode::Optional,
1420 path.segments.last().unwrap());
1422 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1424 TypeAndSubsts { substs: substs, ty: ty }
1427 pub fn write_nil(&self, node_id: ast::NodeId) {
1428 self.write_ty(node_id, self.tcx().mk_nil());
1430 pub fn write_error(&self, node_id: ast::NodeId) {
1431 self.write_ty(node_id, self.tcx().types.err);
1434 pub fn require_type_meets(&self,
1437 code: traits::ObligationCauseCode<'tcx>,
1438 bound: ty::BuiltinBound)
1440 self.register_builtin_bound(
1443 traits::ObligationCause::new(span, self.body_id, code));
1446 pub fn require_type_is_sized(&self,
1449 code: traits::ObligationCauseCode<'tcx>)
1451 self.require_type_meets(ty, span, code, ty::BoundSized);
1454 pub fn require_expr_have_sized_type(&self,
1456 code: traits::ObligationCauseCode<'tcx>)
1458 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1461 pub fn type_is_known_to_be_sized(&self,
1466 traits::type_known_to_meet_builtin_bound(self.infcx(),
1472 pub fn register_builtin_bound(&self,
1474 builtin_bound: ty::BuiltinBound,
1475 cause: traits::ObligationCause<'tcx>)
1477 self.inh.infcx.fulfillment_cx.borrow_mut()
1478 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1481 pub fn register_predicate(&self,
1482 obligation: traits::PredicateObligation<'tcx>)
1484 debug!("register_predicate({:?})",
1486 self.inh.infcx.fulfillment_cx
1488 .register_predicate_obligation(self.infcx(), obligation);
1491 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1492 let t = ast_ty_to_ty(self, self, ast_t);
1494 let mut bounds_checker = wf::BoundsChecker::new(self,
1497 bounds_checker.check_ty(t, ast_t.span);
1502 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1503 match self.inh.tables.borrow().node_types.get(&ex.id) {
1506 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1512 /// Apply `adjustment` to the type of `expr`
1513 pub fn adjust_expr_ty(&self,
1515 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1518 let raw_ty = self.expr_ty(expr);
1519 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1520 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1521 raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| {
1522 self.inh.tables.borrow().method_map.get(&method_call)
1523 .map(|method| resolve_ty(method.ty))
1527 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1528 match self.inh.tables.borrow().node_types.get(&id) {
1530 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1532 self.tcx().sess.bug(
1533 &format!("no type for node {}: {} in fcx {}",
1534 id, self.tcx().map.node_to_string(id),
1540 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1541 // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if
1542 // it changes when we upgrade the snapshot compiler
1543 fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
1544 -> &'a NodeMap<ty::ItemSubsts<'tcx>> {
1548 Ref::map(self.inh.tables.borrow(), project_item_susbts)
1551 pub fn opt_node_ty_substs<F>(&self,
1554 F: FnOnce(&ty::ItemSubsts<'tcx>),
1556 match self.inh.tables.borrow().item_substs.get(&id) {
1562 pub fn mk_subty(&self,
1563 a_is_expected: bool,
1564 origin: infer::TypeOrigin,
1567 -> Result<(), ty::TypeError<'tcx>> {
1568 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1571 pub fn mk_eqty(&self,
1572 a_is_expected: bool,
1573 origin: infer::TypeOrigin,
1576 -> Result<(), ty::TypeError<'tcx>> {
1577 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1580 pub fn mk_subr(&self,
1581 origin: infer::SubregionOrigin<'tcx>,
1584 infer::mk_subr(self.infcx(), origin, sub, sup)
1587 pub fn type_error_message<M>(&self,
1590 actual_ty: Ty<'tcx>,
1591 err: Option<&ty::TypeError<'tcx>>) where
1592 M: FnOnce(String) -> String,
1594 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1597 pub fn report_mismatched_types(&self,
1601 err: &ty::TypeError<'tcx>) {
1602 self.infcx().report_mismatched_types(sp, e, a, err)
1605 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1606 /// outlive the region `r`.
1607 pub fn register_region_obligation(&self,
1610 cause: traits::ObligationCause<'tcx>)
1612 let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1613 fulfillment_cx.register_region_obligation(ty, region, cause);
1616 pub fn add_default_region_param_bounds(&self,
1617 substs: &Substs<'tcx>,
1620 for &ty in &substs.types {
1621 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1622 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1623 traits::MiscObligation);
1624 self.register_region_obligation(ty, default_bound, cause);
1628 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1629 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1630 /// trait/region obligations.
1632 /// For example, if there is a function:
1635 /// fn foo<'a,T:'a>(...)
1638 /// and a reference:
1644 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1645 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1646 pub fn add_obligations_for_parameters(&self,
1647 cause: traits::ObligationCause<'tcx>,
1648 predicates: &ty::InstantiatedPredicates<'tcx>)
1650 assert!(!predicates.has_escaping_regions());
1652 debug!("add_obligations_for_parameters(predicates={:?})",
1655 for obligation in traits::predicates_for_generics(cause, predicates) {
1656 self.register_predicate(obligation);
1660 // Only for fields! Returns <none> for methods>
1661 // Indifferent to privacy flags
1662 pub fn lookup_field_ty(&self,
1664 class_id: ast::DefId,
1665 items: &[ty::FieldTy],
1666 fieldname: ast::Name,
1667 substs: &subst::Substs<'tcx>)
1670 let o_field = items.iter().find(|f| f.name == fieldname);
1671 o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
1672 .map(|t| self.normalize_associated_types_in(span, &t))
1675 pub fn lookup_tup_field_ty(&self,
1677 class_id: ast::DefId,
1678 items: &[ty::FieldTy],
1680 substs: &subst::Substs<'tcx>)
1683 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1684 o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
1685 .map(|t| self.normalize_associated_types_in(span, &t))
1688 fn check_casts(&self) {
1689 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1690 for cast in deferred_cast_checks.drain(..) {
1695 fn select_all_obligations_and_apply_defaults(&self) {
1696 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1698 // For the time being this errs on the side of being memory wasteful but provides better
1700 // let type_variables = self.infcx().type_variables.clone();
1702 // There is a possibility that this algorithm will have to run an arbitrary number of times
1703 // to terminate so we bound it by the compiler's recursion limit.
1704 for _ in (0..self.tcx().sess.recursion_limit.get()) {
1705 // First we try to solve all obligations, it is possible that the last iteration
1706 // has made it possible to make more progress.
1707 self.select_obligations_where_possible();
1709 let mut conflicts = Vec::new();
1711 // Collect all unsolved type, integral and floating point variables.
1712 let unsolved_variables = self.inh.infcx.unsolved_variables();
1714 // We must collect the defaults *before* we do any unification. Because we have
1715 // directly attached defaults to the type variables any unification that occurs
1716 // will erase defaults causing conflicting defaults to be completely ignored.
1717 let default_map: FnvHashMap<_, _> =
1720 .filter_map(|t| self.infcx().default(t).map(|d| (t, d)))
1723 let mut unbound_tyvars = HashSet::new();
1725 debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);
1727 // We loop over the unsolved variables, resolving them and if they are
1728 // and unconstrainted numberic type we add them to the set of unbound
1729 // variables. We do this so we only apply literal fallback to type
1730 // variables without defaults.
1731 for ty in &unsolved_variables {
1732 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1733 if self.infcx().type_var_diverges(resolved) {
1734 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1736 match self.infcx().type_is_unconstrained_numeric(resolved) {
1737 UnconstrainedInt | UnconstrainedFloat => {
1738 unbound_tyvars.insert(resolved);
1745 // We now remove any numeric types that also have defaults, and instead insert
1746 // the type variable with a defined fallback.
1747 for ty in &unsolved_variables {
1748 if let Some(_default) = default_map.get(ty) {
1749 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1751 debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
1754 match resolved.sty {
1755 ty::TyInfer(ty::TyVar(_)) => {
1756 unbound_tyvars.insert(ty);
1759 ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
1760 unbound_tyvars.insert(ty);
1761 if unbound_tyvars.contains(resolved) {
1762 unbound_tyvars.remove(resolved);
1771 // If there are no more fallbacks to apply at this point we have applied all possible
1772 // defaults and type inference will procede as normal.
1773 if unbound_tyvars.is_empty() {
1777 // Finally we go through each of the unbound type variables and unify them with
1778 // the proper fallback, reporting a conflicting default error if any of the
1779 // unifications fail. We know it must be a conflicting default because the
1780 // variable would only be in `unbound_tyvars` and have a concrete value if
1781 // it had been solved by previously applying a default.
1783 // We take a snapshot for use in error reporting.
1784 let snapshot = self.infcx().type_variables.borrow_mut().snapshot();
1786 for ty in &unbound_tyvars {
1787 if self.infcx().type_var_diverges(ty) {
1788 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1790 match self.infcx().type_is_unconstrained_numeric(ty) {
1791 UnconstrainedInt => {
1792 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1794 UnconstrainedFloat => {
1795 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1798 if let Some(default) = default_map.get(ty) {
1799 let default = default.clone();
1800 match infer::mk_eqty(self.infcx(), false,
1801 infer::Misc(default.origin_span),
1805 conflicts.push((*ty, default));
1814 // There were some errors to report
1815 if conflicts.len() > 0 {
1816 self.infcx().type_variables.borrow_mut().rollback_to(snapshot);
1818 for (conflict, default) in conflicts {
1819 let conflicting_default =
1820 self.find_conflicting_default(
1823 conflict).unwrap_or(type_variable::Default {
1824 ty: self.infcx().next_ty_var(),
1825 origin_span: codemap::DUMMY_SP,
1826 definition_span: codemap::DUMMY_SP
1829 self.infcx().report_conflicting_default_types(
1830 conflicting_default.origin_span,
1831 conflicting_default,
1835 self.infcx().type_variables.borrow_mut().commit(snapshot)
1839 self.select_obligations_where_possible();
1842 // For use in error handling related to default type parameter fallback. We explicitly
1843 // apply the default that caused conflict first to a local version of the type variable
1844 // table then apply defaults until we find a conflict. That default must be the one
1845 // that caused conflict earlier.
1846 fn find_conflicting_default(&self,
1847 unbound_vars: &HashSet<Ty<'tcx>>,
1848 default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
1850 -> Option<type_variable::Default<'tcx>> {
1851 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1853 // Ensure that the conflicting default is applied first
1854 let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
1855 unbound_tyvars.push(conflict);
1856 unbound_tyvars.extend(unbound_vars.iter());
1858 let mut result = None;
1859 // We run the same code as above applying defaults in order, this time when
1860 // we find the conflict we just return it for error reporting above.
1861 for ty in &unbound_tyvars {
1862 if self.infcx().type_var_diverges(ty) {
1863 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1865 match self.infcx().type_is_unconstrained_numeric(ty) {
1866 UnconstrainedInt => {
1867 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1869 UnconstrainedFloat => {
1870 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1873 if let Some(default) = default_map.get(ty) {
1874 let default = default.clone();
1875 match infer::mk_eqty(self.infcx(), false,
1876 infer::Misc(default.origin_span),
1880 result = Some(default);
1892 fn select_all_obligations_or_error(&self) {
1893 debug!("select_all_obligations_or_error");
1895 // upvar inference should have ensured that all deferred call
1896 // resolutions are handled by now.
1897 assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
1899 self.select_all_obligations_and_apply_defaults();
1900 let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1901 match fulfillment_cx.select_all_or_error(self.infcx()) {
1903 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1907 /// Select as many obligations as we can at present.
1908 fn select_obligations_where_possible(&self) {
1910 self.inh.infcx.fulfillment_cx
1912 .select_where_possible(self.infcx())
1915 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1919 /// Try to select any fcx obligation that we haven't tried yet, in an effort
1920 /// to improve inference. You could just call
1921 /// `select_obligations_where_possible` except that it leads to repeated
1923 fn select_new_obligations(&self) {
1925 self.inh.infcx.fulfillment_cx
1927 .select_new_obligations(self.infcx())
1930 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1936 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1937 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1938 Some(self.base_object_lifetime_default(span))
1941 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
1942 // RFC #599 specifies that object lifetime defaults take
1943 // precedence over other defaults. But within a fn body we
1944 // don't have a *default* region, rather we use inference to
1945 // find the *correct* region, which is strictly more general
1946 // (and anyway, within a fn body the right region may not even
1947 // be something the user can write explicitly, since it might
1948 // be some expression).
1949 self.infcx().next_region_var(infer::MiscVariable(span))
1952 fn anon_regions(&self, span: Span, count: usize)
1953 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
1954 Ok((0..count).map(|_| {
1955 self.infcx().next_region_var(infer::MiscVariable(span))
1960 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1961 pub enum LvaluePreference {
1966 impl LvaluePreference {
1967 pub fn from_mutbl(m: ast::Mutability) -> Self {
1969 ast::MutMutable => PreferMutLvalue,
1970 ast::MutImmutable => NoPreference,
1975 /// Whether `autoderef` requires types to resolve.
1976 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1977 pub enum UnresolvedTypeAction {
1978 /// Produce an error and return `TyError` whenever a type cannot
1979 /// be resolved (i.e. it is `TyInfer`).
1981 /// Go on without emitting any errors, and return the unresolved
1982 /// type. Useful for probing, e.g. in coercions.
1986 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1987 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1989 /// Note: this method does not modify the adjustments table. The caller is responsible for
1990 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1991 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1994 opt_expr: Option<&ast::Expr>,
1995 unresolved_type_action: UnresolvedTypeAction,
1996 mut lvalue_pref: LvaluePreference,
1998 -> (Ty<'tcx>, usize, Option<T>)
1999 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
2001 debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
2006 let mut t = base_ty;
2007 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
2008 let resolved_t = match unresolved_type_action {
2009 UnresolvedTypeAction::Error => {
2010 structurally_resolved_type(fcx, sp, t)
2012 UnresolvedTypeAction::Ignore => {
2013 // We can continue even when the type cannot be resolved
2014 // (i.e. it is an inference variable) because `Ty::builtin_deref`
2015 // and `try_overloaded_deref` both simply return `None`
2016 // in such a case without producing spurious errors.
2017 fcx.resolve_type_vars_if_possible(t)
2020 if resolved_t.references_error() {
2021 return (resolved_t, autoderefs, None);
2024 match should_stop(resolved_t, autoderefs) {
2025 Some(x) => return (resolved_t, autoderefs, Some(x)),
2029 // Otherwise, deref if type is derefable:
2030 let mt = match resolved_t.builtin_deref(false) {
2031 Some(mt) => Some(mt),
2034 opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
2036 // Super subtle: it might seem as though we should
2037 // pass `opt_expr` to `try_overloaded_deref`, so that
2038 // the (implicit) autoref of using an overloaded deref
2039 // would get added to the adjustment table. However we
2040 // do not do that, because it's kind of a
2041 // "meta-adjustment" -- instead, we just leave it
2042 // unrecorded and know that there "will be" an
2043 // autoref. regionck and other bits of the code base,
2044 // when they encounter an overloaded autoderef, have
2045 // to do some reconstructive surgery. This is a pretty
2046 // complex mess that is begging for a proper MIR.
2047 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2053 if mt.mutbl == ast::MutImmutable {
2054 lvalue_pref = NoPreference;
2057 None => return (resolved_t, autoderefs, None)
2061 // We've reached the recursion limit, error gracefully.
2062 span_err!(fcx.tcx().sess, sp, E0055,
2063 "reached the recursion limit while auto-dereferencing {:?}",
2065 (fcx.tcx().types.err, 0, None)
2068 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2070 method_call: Option<MethodCall>,
2071 base_expr: Option<&ast::Expr>,
2073 lvalue_pref: LvaluePreference)
2074 -> Option<ty::TypeAndMut<'tcx>>
2076 // Try DerefMut first, if preferred.
2077 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2078 (PreferMutLvalue, Some(trait_did)) => {
2079 method::lookup_in_trait(fcx, span, base_expr,
2080 token::intern("deref_mut"), trait_did,
2086 // Otherwise, fall back to Deref.
2087 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2088 (None, Some(trait_did)) => {
2089 method::lookup_in_trait(fcx, span, base_expr,
2090 token::intern("deref"), trait_did,
2093 (method, _) => method
2096 make_overloaded_lvalue_return_type(fcx, method_call, method)
2099 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2100 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2101 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2102 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2103 method_call: Option<MethodCall>,
2104 method: Option<MethodCallee<'tcx>>)
2105 -> Option<ty::TypeAndMut<'tcx>>
2109 // extract method method return type, which will be &T;
2110 // all LB regions should have been instantiated during method lookup
2111 let ret_ty = method.ty.fn_ret();
2112 let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
2114 if let Some(method_call) = method_call {
2115 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2118 // method returns &T, but the type as visible to user is T, so deref
2119 ret_ty.builtin_deref(true)
2125 fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2127 base_expr: &'tcx ast::Expr,
2130 lvalue_pref: LvaluePreference)
2131 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2133 // FIXME(#18741) -- this is almost but not quite the same as the
2134 // autoderef that normal method probing does. They could likely be
2137 let (ty, autoderefs, final_mt) = autoderef(fcx,
2141 UnresolvedTypeAction::Error,
2144 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2145 adj_ty, idx, false, lvalue_pref, idx_ty)
2148 if final_mt.is_some() {
2152 // After we have fully autoderef'd, if the resulting type is [T; n], then
2153 // do a final unsized coercion to yield [T].
2154 if let ty::TyArray(element_ty, _) = ty.sty {
2155 let adjusted_ty = fcx.tcx().mk_slice(element_ty);
2156 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2157 adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
2163 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2164 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2165 /// This loop implements one step in that search; the autoderef loop is implemented by
2166 /// `lookup_indexing`.
2167 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2168 method_call: MethodCall,
2170 base_expr: &'tcx ast::Expr,
2171 adjusted_ty: Ty<'tcx>,
2174 lvalue_pref: LvaluePreference,
2176 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2178 let tcx = fcx.tcx();
2179 debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
2180 autoderefs={}, unsize={}, index_ty={:?})",
2188 let input_ty = fcx.infcx().next_ty_var();
2190 // First, try built-in indexing.
2191 match (adjusted_ty.builtin_index(), &index_ty.sty) {
2192 (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
2193 debug!("try_index_step: success, using built-in indexing");
2194 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2196 fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
2197 return Some((tcx.types.usize, ty));
2202 // Try `IndexMut` first, if preferred.
2203 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2204 (PreferMutLvalue, Some(trait_did)) => {
2205 method::lookup_in_trait_adjusted(fcx,
2208 token::intern("index_mut"),
2213 Some(vec![input_ty]))
2218 // Otherwise, fall back to `Index`.
2219 let method = match (method, tcx.lang_items.index_trait()) {
2220 (None, Some(trait_did)) => {
2221 method::lookup_in_trait_adjusted(fcx,
2224 token::intern("index"),
2229 Some(vec![input_ty]))
2231 (method, _) => method,
2234 // If some lookup succeeds, write callee into table and extract index/element
2235 // type from the method signature.
2236 // If some lookup succeeded, install method in table
2237 method.and_then(|method| {
2238 debug!("try_index_step: success, using overloaded indexing");
2239 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2240 map(|ret| (input_ty, ret.ty))
2244 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2246 method_fn_ty: Ty<'tcx>,
2247 callee_expr: &'tcx ast::Expr,
2248 args_no_rcvr: &'tcx [P<ast::Expr>],
2249 tuple_arguments: TupleArgumentsFlag,
2250 expected: Expectation<'tcx>)
2251 -> ty::FnOutput<'tcx> {
2252 if method_fn_ty.references_error() {
2253 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2255 let err_inputs = match tuple_arguments {
2256 DontTupleArguments => err_inputs,
2257 TupleArguments => vec![fcx.tcx().mk_tup(err_inputs)],
2260 check_argument_types(fcx,
2267 ty::FnConverging(fcx.tcx().types.err)
2269 match method_fn_ty.sty {
2270 ty::TyBareFn(_, ref fty) => {
2271 // HACK(eddyb) ignore self in the definition (see above).
2272 let expected_arg_tys = expected_types_for_fn_args(fcx,
2276 &fty.sig.0.inputs[1..]);
2277 check_argument_types(fcx,
2279 &fty.sig.0.inputs[1..],
2280 &expected_arg_tys[..],
2287 fcx.tcx().sess.span_bug(callee_expr.span,
2288 "method without bare fn type");
2294 /// Generic function that factors out common logic from function calls, method calls and overloaded
2296 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2298 fn_inputs: &[Ty<'tcx>],
2299 expected_arg_tys: &[Ty<'tcx>],
2300 args: &'tcx [P<ast::Expr>],
2302 tuple_arguments: TupleArgumentsFlag) {
2303 let tcx = fcx.ccx.tcx;
2305 // Grab the argument types, supplying fresh type variables
2306 // if the wrong number of arguments were supplied
2307 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2313 let mut expected_arg_tys = expected_arg_tys;
2314 let expected_arg_count = fn_inputs.len();
2315 let formal_tys = if tuple_arguments == TupleArguments {
2316 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2317 match tuple_type.sty {
2318 ty::TyTuple(ref arg_types) => {
2319 if arg_types.len() != args.len() {
2320 span_err!(tcx.sess, sp, E0057,
2321 "this function takes {} parameter{} but {} parameter{} supplied",
2323 if arg_types.len() == 1 {""} else {"s"},
2325 if args.len() == 1 {" was"} else {"s were"});
2326 expected_arg_tys = &[];
2327 err_args(fcx.tcx(), args.len())
2329 expected_arg_tys = match expected_arg_tys.get(0) {
2330 Some(&ty) => match ty.sty {
2331 ty::TyTuple(ref tys) => &**tys,
2336 (*arg_types).clone()
2340 span_err!(tcx.sess, sp, E0059,
2341 "cannot use call notation; the first type parameter \
2342 for the function trait is neither a tuple nor unit");
2343 expected_arg_tys = &[];
2344 err_args(fcx.tcx(), args.len())
2347 } else if expected_arg_count == supplied_arg_count {
2349 } else if variadic {
2350 if supplied_arg_count >= expected_arg_count {
2353 span_err!(tcx.sess, sp, E0060,
2354 "this function takes at least {} parameter{} \
2355 but {} parameter{} supplied",
2357 if expected_arg_count == 1 {""} else {"s"},
2359 if supplied_arg_count == 1 {" was"} else {"s were"});
2360 expected_arg_tys = &[];
2361 err_args(fcx.tcx(), supplied_arg_count)
2364 span_err!(tcx.sess, sp, E0061,
2365 "this function takes {} parameter{} but {} parameter{} supplied",
2367 if expected_arg_count == 1 {""} else {"s"},
2369 if supplied_arg_count == 1 {" was"} else {"s were"});
2370 expected_arg_tys = &[];
2371 err_args(fcx.tcx(), supplied_arg_count)
2374 debug!("check_argument_types: formal_tys={:?}",
2375 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2377 // Check the arguments.
2378 // We do this in a pretty awful way: first we typecheck any arguments
2379 // that are not anonymous functions, then we typecheck the anonymous
2380 // functions. This is so that we have more information about the types
2381 // of arguments when we typecheck the functions. This isn't really the
2382 // right way to do this.
2383 let xs = [false, true];
2384 for check_blocks in &xs {
2385 let check_blocks = *check_blocks;
2386 debug!("check_blocks={}", check_blocks);
2388 // More awful hacks: before we check argument types, try to do
2389 // an "opportunistic" vtable resolution of any trait bounds on
2390 // the call. This helps coercions.
2392 fcx.select_new_obligations();
2395 // For variadic functions, we don't have a declared type for all of
2396 // the arguments hence we only do our usual type checking with
2397 // the arguments who's types we do know.
2398 let t = if variadic {
2400 } else if tuple_arguments == TupleArguments {
2405 for (i, arg) in args.iter().take(t).enumerate() {
2406 let is_block = match arg.node {
2407 ast::ExprClosure(..) => true,
2411 if is_block == check_blocks {
2412 debug!("checking the argument");
2413 let formal_ty = formal_tys[i];
2415 // The special-cased logic below has three functions:
2416 // 1. Provide as good of an expected type as possible.
2417 let expected = expected_arg_tys.get(i).map(|&ty| {
2418 Expectation::rvalue_hint(ty)
2421 check_expr_with_unifier(fcx, &**arg,
2422 expected.unwrap_or(ExpectHasType(formal_ty)),
2424 // 2. Coerce to the most detailed type that could be coerced
2425 // to, which is `expected_ty` if `rvalue_hint` returns an
2426 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2427 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2428 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2430 // 3. Relate the expected type and the formal one,
2431 // if the expected type was used for the coercion.
2432 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2438 // We also need to make sure we at least write the ty of the other
2439 // arguments which we skipped above.
2441 for arg in args.iter().skip(expected_arg_count) {
2442 check_expr(fcx, &**arg);
2444 // There are a few types which get autopromoted when passed via varargs
2445 // in C but we just error out instead and require explicit casts.
2446 let arg_ty = structurally_resolved_type(fcx, arg.span,
2447 fcx.expr_ty(&**arg));
2449 ty::TyFloat(ast::TyF32) => {
2450 fcx.type_error_message(arg.span,
2452 format!("can't pass an {} to variadic \
2453 function, cast to c_double", t)
2456 ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
2457 fcx.type_error_message(arg.span, |t| {
2458 format!("can't pass {} to variadic \
2459 function, cast to c_int",
2463 ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
2464 fcx.type_error_message(arg.span, |t| {
2465 format!("can't pass {} to variadic \
2466 function, cast to c_uint",
2476 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2477 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2478 (0..len).map(|_| tcx.types.err).collect()
2481 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2482 call_expr: &ast::Expr,
2483 output: ty::FnOutput<'tcx>) {
2484 fcx.write_ty(call_expr.id, match output {
2485 ty::FnConverging(output_ty) => output_ty,
2486 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2490 // AST fragment checking
2491 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2493 expected: Expectation<'tcx>)
2496 let tcx = fcx.ccx.tcx;
2499 ast::LitStr(..) => tcx.mk_static_str(),
2500 ast::LitBinary(ref v) => {
2501 tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
2502 tcx.mk_array(tcx.types.u8, v.len()))
2504 ast::LitByte(_) => tcx.types.u8,
2505 ast::LitChar(_) => tcx.types.char,
2506 ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
2507 ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
2508 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2509 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2511 ty::TyInt(_) | ty::TyUint(_) => Some(ty),
2512 ty::TyChar => Some(tcx.types.u8),
2513 ty::TyRawPtr(..) => Some(tcx.types.usize),
2514 ty::TyBareFn(..) => Some(tcx.types.usize),
2518 opt_ty.unwrap_or_else(
2519 || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
2521 ast::LitFloat(_, t) => tcx.mk_mach_float(t),
2522 ast::LitFloatUnsuffixed(_) => {
2523 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2525 ty::TyFloat(_) => Some(ty),
2529 opt_ty.unwrap_or_else(
2530 || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
2532 ast::LitBool(_) => tcx.types.bool
2536 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2537 expr: &'tcx ast::Expr,
2538 expected: Ty<'tcx>) {
2539 check_expr_with_unifier(
2540 fcx, expr, ExpectHasType(expected), NoPreference,
2541 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2544 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2545 expr: &'tcx ast::Expr,
2546 expected: Ty<'tcx>) {
2547 check_expr_with_unifier(
2548 fcx, expr, ExpectHasType(expected), NoPreference,
2549 || demand::coerce(fcx, expr.span, expected, expr));
2552 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2553 expected: Ty<'tcx>) {
2554 check_expr_with_unifier(
2555 fcx, expr, ExpectHasType(expected), NoPreference,
2559 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2560 expr: &'tcx ast::Expr,
2561 expected: Expectation<'tcx>) {
2562 check_expr_with_unifier(
2563 fcx, expr, expected, NoPreference,
2567 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2568 expr: &'tcx ast::Expr,
2569 expected: Expectation<'tcx>,
2570 lvalue_pref: LvaluePreference)
2572 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2575 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2576 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2579 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2580 lvalue_pref: LvaluePreference) {
2581 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2584 // determine the `self` type, using fresh variables for all variables
2585 // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
2586 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2588 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2589 span: Span, // (potential) receiver for this impl
2591 -> TypeAndSubsts<'tcx> {
2592 let tcx = fcx.tcx();
2594 let ity = tcx.lookup_item_type(did);
2595 let (tps, rps, raw_ty) =
2596 (ity.generics.types.get_slice(subst::TypeSpace),
2597 ity.generics.regions.get_slice(subst::TypeSpace),
2600 debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
2602 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2603 let tps = fcx.inh.infcx.type_vars_for_defs(span, tps);
2604 let substs = subst::Substs::new_type(tps, rps);
2605 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2607 TypeAndSubsts { substs: substs, ty: substd_ty }
2610 /// Controls whether the arguments are tupled. This is used for the call
2613 /// Tupling means that all call-side arguments are packed into a tuple and
2614 /// passed as a single parameter. For example, if tupling is enabled, this
2617 /// fn f(x: (isize, isize))
2619 /// Can be called as:
2626 #[derive(Clone, Eq, PartialEq)]
2627 enum TupleArgumentsFlag {
2632 /// Unifies the return type with the expected type early, for more coercions
2633 /// and forward type information on the argument expressions.
2634 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2636 expected_ret: Expectation<'tcx>,
2637 formal_ret: ty::FnOutput<'tcx>,
2638 formal_args: &[Ty<'tcx>])
2640 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2641 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2642 fcx.infcx().commit_regions_if_ok(|| {
2643 // Attempt to apply a subtyping relationship between the formal
2644 // return type (likely containing type variables if the function
2645 // is polymorphic) and the expected return type.
2646 // No argument expectations are produced if unification fails.
2647 let origin = infer::Misc(call_span);
2648 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2649 // FIXME(#15760) can't use try! here, FromError doesn't default
2650 // to identity so the resulting type is not constrained.
2651 if let Err(e) = ures {
2655 // Record all the argument types, with the substitutions
2656 // produced from the above subtyping unification.
2657 Ok(formal_args.iter().map(|ty| {
2658 fcx.infcx().resolve_type_vars_if_possible(ty)
2664 }).unwrap_or(vec![]);
2665 debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
2666 formal_args, formal_ret,
2667 expected_args, expected_ret);
2672 /// If an expression has any sub-expressions that result in a type error,
2673 /// inspecting that expression's type with `ty.references_error()` will return
2674 /// true. Likewise, if an expression is known to diverge, inspecting its
2675 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2676 /// strict, _|_ can appear in the type of an expression that does not,
2677 /// itself, diverge: for example, fn() -> _|_.)
2678 /// Note that inspecting a type's structure *directly* may expose the fact
2679 /// that there are actually multiple representations for `TyError`, so avoid
2680 /// that when err needs to be handled differently.
2681 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2682 expr: &'tcx ast::Expr,
2683 expected: Expectation<'tcx>,
2684 lvalue_pref: LvaluePreference,
2688 debug!(">> typechecking: expr={:?} expected={:?}",
2691 // Checks a method call.
2692 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2693 expr: &'tcx ast::Expr,
2694 method_name: ast::SpannedIdent,
2695 args: &'tcx [P<ast::Expr>],
2697 expected: Expectation<'tcx>,
2698 lvalue_pref: LvaluePreference) {
2699 let rcvr = &*args[0];
2700 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2702 // no need to check for bot/err -- callee does that
2703 let expr_t = structurally_resolved_type(fcx,
2705 fcx.expr_ty(&*rcvr));
2707 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2708 let fn_ty = match method::lookup(fcx,
2710 method_name.node.name,
2716 let method_ty = method.ty;
2717 let method_call = MethodCall::expr(expr.id);
2718 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2722 method::report_error(fcx, method_name.span, expr_t,
2723 method_name.node.name, Some(rcvr), error);
2724 fcx.write_error(expr.id);
2729 // Call the generic checker.
2730 let ret_ty = check_method_argument_types(fcx,
2738 write_call(fcx, expr, ret_ty);
2741 // A generic function for checking the then and else in an if
2743 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2744 cond_expr: &'tcx ast::Expr,
2745 then_blk: &'tcx ast::Block,
2746 opt_else_expr: Option<&'tcx ast::Expr>,
2749 expected: Expectation<'tcx>) {
2750 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2752 let expected = expected.adjust_for_branches(fcx);
2753 check_block_with_expected(fcx, then_blk, expected);
2754 let then_ty = fcx.node_ty(then_blk.id);
2756 let branches_ty = match opt_else_expr {
2757 Some(ref else_expr) => {
2758 check_expr_with_expectation(fcx, &**else_expr, expected);
2759 let else_ty = fcx.expr_ty(&**else_expr);
2760 infer::common_supertype(fcx.infcx(),
2761 infer::IfExpression(sp),
2767 infer::common_supertype(fcx.infcx(),
2768 infer::IfExpressionWithNoElse(sp),
2775 let cond_ty = fcx.expr_ty(cond_expr);
2776 let if_ty = if cond_ty.references_error() {
2782 fcx.write_ty(id, if_ty);
2785 // Check field access expressions
2786 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2787 expr: &'tcx ast::Expr,
2788 lvalue_pref: LvaluePreference,
2789 base: &'tcx ast::Expr,
2790 field: &ast::SpannedIdent) {
2791 let tcx = fcx.ccx.tcx;
2792 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2793 let expr_t = structurally_resolved_type(fcx, expr.span,
2795 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2796 let (_, autoderefs, field_ty) = autoderef(fcx,
2800 UnresolvedTypeAction::Error,
2804 ty::TyStruct(base_id, substs) => {
2805 debug!("struct named {:?}", base_t);
2806 let fields = tcx.lookup_struct_fields(base_id);
2807 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
2808 field.node.name, &(*substs))
2815 fcx.write_ty(expr.id, field_ty);
2816 fcx.write_autoderef_adjustment(base.id, autoderefs);
2822 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2823 fcx.type_error_message(
2826 format!("attempted to take value of method `{}` on type \
2827 `{}`", token::get_ident(field.node), actual)
2831 tcx.sess.fileline_help(field.span,
2832 "maybe a `()` to call it is missing? \
2833 If not, try an anonymous function");
2835 fcx.type_error_message(
2838 format!("attempted access of field `{}` on \
2839 type `{}`, but no field with that \
2841 token::get_ident(field.node),
2845 if let ty::TyStruct(did, _) = expr_t.sty {
2846 suggest_field_names(did, field, tcx, vec![]);
2850 fcx.write_error(expr.id);
2853 // displays hints about the closest matches in field names
2854 fn suggest_field_names<'tcx>(id : DefId,
2855 field : &ast::SpannedIdent,
2856 tcx : &ty::ctxt<'tcx>,
2858 let ident = token::get_ident(field.node);
2860 // only find fits with at least one matching letter
2861 let mut best_dist = name.len();
2862 let fields = tcx.lookup_struct_fields(id);
2863 let mut best = None;
2864 for elem in &fields {
2865 let n = elem.name.as_str();
2866 // ignore already set fields
2867 if skip.iter().any(|&x| x == n) {
2870 // ignore private fields from non-local crates
2871 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2874 let dist = lev_distance(n, name);
2875 if dist < best_dist {
2880 if let Some(n) = best {
2881 tcx.sess.span_help(field.span,
2882 &format!("did you mean `{}`?", n));
2886 // Check tuple index expressions
2887 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2888 expr: &'tcx ast::Expr,
2889 lvalue_pref: LvaluePreference,
2890 base: &'tcx ast::Expr,
2891 idx: codemap::Spanned<usize>) {
2892 let tcx = fcx.ccx.tcx;
2893 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2894 let expr_t = structurally_resolved_type(fcx, expr.span,
2896 let mut tuple_like = false;
2897 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2898 let (_, autoderefs, field_ty) = autoderef(fcx,
2902 UnresolvedTypeAction::Error,
2906 ty::TyStruct(base_id, substs) => {
2907 tuple_like = tcx.is_tuple_struct(base_id);
2909 debug!("tuple struct named {:?}", base_t);
2910 let fields = tcx.lookup_struct_fields(base_id);
2911 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
2912 idx.node, &(*substs))
2917 ty::TyTuple(ref v) => {
2919 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2926 fcx.write_ty(expr.id, field_ty);
2927 fcx.write_autoderef_adjustment(base.id, autoderefs);
2932 fcx.type_error_message(
2936 format!("attempted out-of-bounds tuple index `{}` on \
2941 format!("attempted tuple index `{}` on type `{}`, but the \
2942 type was not a tuple or tuple struct",
2949 fcx.write_error(expr.id);
2952 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2953 struct_ty: Ty<'tcx>,
2955 class_id: ast::DefId,
2956 node_id: ast::NodeId,
2957 substitutions: &'tcx subst::Substs<'tcx>,
2958 field_types: &[ty::FieldTy],
2959 ast_fields: &'tcx [ast::Field],
2960 check_completeness: bool,
2961 enum_id_opt: Option<ast::DefId>) {
2962 let tcx = fcx.ccx.tcx;
2964 let mut class_field_map = FnvHashMap();
2965 let mut fields_found = 0;
2966 for field in field_types {
2967 class_field_map.insert(field.name, (field.id, false));
2970 let mut error_happened = false;
2972 // Typecheck each field.
2973 for field in ast_fields {
2974 let mut expected_field_type = tcx.types.err;
2976 let pair = class_field_map.get(&field.ident.node.name).cloned();
2979 fcx.type_error_message(
2981 |actual| match enum_id_opt {
2983 let variant_type = tcx.enum_variant_with_id(enum_id,
2985 format!("struct variant `{}::{}` has no field named `{}`",
2986 actual, variant_type.name.as_str(),
2987 token::get_ident(field.ident.node))
2990 format!("structure `{}` has no field named `{}`",
2992 token::get_ident(field.ident.node))
2997 // prevent all specified fields from being suggested
2998 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
2999 let actual_id = match enum_id_opt {
3000 Some(_) => class_id,
3001 None => struct_ty.ty_to_def_id().unwrap()
3003 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3004 error_happened = true;
3006 Some((_, true)) => {
3007 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3008 "field `{}` specified more than once",
3009 token::get_ident(field.ident.node));
3010 error_happened = true;
3012 Some((field_id, false)) => {
3013 expected_field_type =
3014 tcx.lookup_field_type(class_id, field_id, substitutions);
3015 expected_field_type =
3016 fcx.normalize_associated_types_in(
3017 field.span, &expected_field_type);
3018 class_field_map.insert(
3019 field.ident.node.name, (field_id, true));
3024 // Make sure to give a type to the field even if there's
3025 // an error, so we can continue typechecking
3026 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3030 fcx.write_error(node_id);
3033 if check_completeness && !error_happened {
3034 // Make sure the programmer specified all the fields.
3035 assert!(fields_found <= field_types.len());
3036 if fields_found < field_types.len() {
3037 let mut missing_fields = Vec::new();
3038 for class_field in field_types {
3039 let name = class_field.name;
3040 let (_, seen) = *class_field_map.get(&name).unwrap();
3042 missing_fields.push(
3043 format!("`{}`", &token::get_name(name)))
3047 span_err!(tcx.sess, span, E0063,
3048 "missing field{}: {}",
3049 if missing_fields.len() == 1 {""} else {"s"},
3050 missing_fields.join(", "));
3054 if !error_happened {
3055 fcx.write_ty(node_id, fcx.ccx.tcx.mk_struct(class_id, substitutions));
3059 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3061 span: codemap::Span,
3062 class_id: ast::DefId,
3063 fields: &'tcx [ast::Field],
3064 base_expr: Option<&'tcx ast::Expr>) {
3065 let tcx = fcx.ccx.tcx;
3067 // Generate the struct type.
3069 ty: mut struct_type,
3070 substs: struct_substs
3071 } = fcx.instantiate_type(span, class_id);
3073 // Look up and check the fields.
3074 let class_fields = tcx.lookup_struct_fields(class_id);
3075 check_struct_or_variant_fields(fcx,
3080 fcx.ccx.tcx.mk_substs(struct_substs),
3083 base_expr.is_none(),
3085 if fcx.node_ty(id).references_error() {
3086 struct_type = tcx.types.err;
3089 // Check the base expression if necessary.
3092 Some(base_expr) => {
3093 check_expr_has_type(fcx, &*base_expr, struct_type);
3097 // Write in the resulting type.
3098 fcx.write_ty(id, struct_type);
3101 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3103 span: codemap::Span,
3104 enum_id: ast::DefId,
3105 variant_id: ast::DefId,
3106 fields: &'tcx [ast::Field]) {
3107 let tcx = fcx.ccx.tcx;
3109 // Look up the number of type parameters and the raw type, and
3110 // determine whether the enum is region-parameterized.
3113 substs: substitutions
3114 } = fcx.instantiate_type(span, enum_id);
3116 // Look up and check the enum variant fields.
3117 let variant_fields = tcx.lookup_struct_fields(variant_id);
3118 check_struct_or_variant_fields(fcx,
3123 fcx.ccx.tcx.mk_substs(substitutions),
3124 &variant_fields[..],
3128 fcx.write_ty(id, enum_type);
3131 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3133 fields: &'tcx [ast::Field],
3134 base_expr: &'tcx Option<P<ast::Expr>>) {
3135 // Make sure to still write the types
3136 // otherwise we might ICE
3137 fcx.write_error(id);
3138 for field in fields {
3139 check_expr(fcx, &*field.expr);
3142 Some(ref base) => check_expr(fcx, &**base),
3147 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3149 let tcx = fcx.ccx.tcx;
3152 ast::ExprBox(ref opt_place, ref subexpr) => {
3153 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3154 check_expr(fcx, &**subexpr);
3156 let mut checked = false;
3157 opt_place.as_ref().map(|place| match place.node {
3158 ast::ExprPath(None, ref path) => {
3159 // FIXME(pcwalton): For now we hardcode the only permissible
3160 // place: the exchange heap.
3161 let definition = lookup_full_def(tcx, path.span, place.id);
3162 let def_id = definition.def_id();
3163 let referent_ty = fcx.expr_ty(&**subexpr);
3164 if tcx.lang_items.exchange_heap() == Some(def_id) {
3165 fcx.write_ty(id, tcx.mk_box(referent_ty));
3173 span_err!(tcx.sess, expr.span, E0066,
3174 "only the exchange heap is currently supported");
3175 fcx.write_ty(id, tcx.types.err);
3179 ast::ExprLit(ref lit) => {
3180 let typ = check_lit(fcx, &**lit, expected);
3181 fcx.write_ty(id, typ);
3183 ast::ExprBinary(op, ref lhs, ref rhs) => {
3184 op::check_binop(fcx, expr, op, lhs, rhs);
3186 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3187 op::check_binop_assign(fcx, expr, op, lhs, rhs);
3189 ast::ExprUnary(unop, ref oprnd) => {
3190 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3192 ast::UnUniq => match ty.sty {
3194 Expectation::rvalue_hint(ty)
3200 ast::UnNot | ast::UnNeg => {
3208 let lvalue_pref = match unop {
3209 ast::UnDeref => lvalue_pref,
3212 check_expr_with_expectation_and_lvalue_pref(
3213 fcx, &**oprnd, expected_inner, lvalue_pref);
3214 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3216 if !oprnd_t.references_error() {
3219 oprnd_t = tcx.mk_box(oprnd_t);
3222 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3223 oprnd_t = match oprnd_t.builtin_deref(true) {
3225 None => match try_overloaded_deref(fcx, expr.span,
3226 Some(MethodCall::expr(expr.id)),
3227 Some(&**oprnd), oprnd_t, lvalue_pref) {
3230 fcx.type_error_message(expr.span, |actual| {
3231 format!("type `{}` cannot be \
3232 dereferenced", actual)
3240 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3242 if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
3243 oprnd_t = op::check_user_unop(fcx, "!", "not",
3244 tcx.lang_items.not_trait(),
3245 expr, &**oprnd, oprnd_t, unop);
3249 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3251 if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
3252 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3253 tcx.lang_items.neg_trait(),
3254 expr, &**oprnd, oprnd_t, unop);
3259 fcx.write_ty(id, oprnd_t);
3261 ast::ExprAddrOf(mutbl, ref oprnd) => {
3262 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3264 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
3265 if fcx.tcx().expr_is_lval(&**oprnd) {
3266 // Lvalues may legitimately have unsized types.
3267 // For example, dereferences of a fat pointer and
3268 // the last field of a struct can be unsized.
3269 ExpectHasType(mt.ty)
3271 Expectation::rvalue_hint(mt.ty)
3277 let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
3278 check_expr_with_expectation_and_lvalue_pref(fcx,
3283 let tm = ty::TypeAndMut { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3284 let oprnd_t = if tm.ty.references_error() {
3287 // Note: at this point, we cannot say what the best lifetime
3288 // is to use for resulting pointer. We want to use the
3289 // shortest lifetime possible so as to avoid spurious borrowck
3290 // errors. Moreover, the longest lifetime will depend on the
3291 // precise details of the value whose address is being taken
3292 // (and how long it is valid), which we don't know yet until type
3293 // inference is complete.
3295 // Therefore, here we simply generate a region variable. The
3296 // region inferencer will then select the ultimate value.
3297 // Finally, borrowck is charged with guaranteeing that the
3298 // value whose address was taken can actually be made to live
3299 // as long as it needs to live.
3300 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3301 tcx.mk_ref(tcx.mk_region(region), tm)
3303 fcx.write_ty(id, oprnd_t);
3305 ast::ExprPath(ref maybe_qself, ref path) => {
3306 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3307 fcx.to_ty(&qself.ty)
3310 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3312 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3313 // Create some fake resolution that can't possibly be a type.
3314 def::PathResolution {
3315 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3316 last_private: LastMod(AllPublic),
3317 depth: path.segments.len()
3320 tcx.sess.span_bug(expr.span,
3321 &format!("unbound path {:?}", expr))
3324 if let Some((opt_ty, segments, def)) =
3325 resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
3326 expr.span, expr.id) {
3327 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
3330 instantiate_path(fcx,
3340 // We always require that the type provided as the value for
3341 // a type parameter outlives the moment of instantiation.
3342 constrain_path_type_parameters(fcx, expr);
3344 ast::ExprInlineAsm(ref ia) => {
3345 for &(_, ref input) in &ia.inputs {
3346 check_expr(fcx, &**input);
3348 for &(_, ref out, _) in &ia.outputs {
3349 check_expr(fcx, &**out);
3353 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3354 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3355 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3356 ast::ExprRet(ref expr_opt) => {
3358 ty::FnConverging(result_type) => {
3361 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3362 result_type, fcx.tcx().mk_nil()) {
3363 span_err!(tcx.sess, expr.span, E0069,
3364 "`return;` in a function whose return type is \
3368 check_expr_coercable_to_type(fcx, &**e, result_type);
3372 ty::FnDiverging => {
3373 if let Some(ref e) = *expr_opt {
3374 check_expr(fcx, &**e);
3376 span_err!(tcx.sess, expr.span, E0166,
3377 "`return` in a function declared as diverging");
3380 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3382 ast::ExprParen(ref a) => {
3383 check_expr_with_expectation_and_lvalue_pref(fcx,
3387 fcx.write_ty(id, fcx.expr_ty(&**a));
3389 ast::ExprAssign(ref lhs, ref rhs) => {
3390 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3392 let tcx = fcx.tcx();
3393 if !tcx.expr_is_lval(&**lhs) {
3394 span_err!(tcx.sess, expr.span, E0070,
3395 "illegal left-hand side expression");
3398 let lhs_ty = fcx.expr_ty(&**lhs);
3399 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3400 let rhs_ty = fcx.expr_ty(&**rhs);
3402 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3404 if lhs_ty.references_error() || rhs_ty.references_error() {
3405 fcx.write_error(id);
3410 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3411 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3412 id, expr.span, expected);
3414 ast::ExprIfLet(..) => {
3415 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3417 ast::ExprWhile(ref cond, ref body, _) => {
3418 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3419 check_block_no_value(fcx, &**body);
3420 let cond_ty = fcx.expr_ty(&**cond);
3421 let body_ty = fcx.node_ty(body.id);
3422 if cond_ty.references_error() || body_ty.references_error() {
3423 fcx.write_error(id);
3429 ast::ExprWhileLet(..) => {
3430 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3432 ast::ExprForLoop(..) => {
3433 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3435 ast::ExprLoop(ref body, _) => {
3436 check_block_no_value(fcx, &**body);
3437 if !may_break(tcx, expr.id, &**body) {
3438 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3443 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3444 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3446 ast::ExprClosure(capture, ref decl, ref body) => {
3447 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3449 ast::ExprBlock(ref b) => {
3450 check_block_with_expected(fcx, &**b, expected);
3451 fcx.write_ty(id, fcx.node_ty(b.id));
3453 ast::ExprCall(ref callee, ref args) => {
3454 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3456 ast::ExprMethodCall(ident, ref tps, ref args) => {
3457 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3458 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3459 let args_err = arg_tys.fold(false,
3461 rest_err || a.references_error()});
3463 fcx.write_error(id);
3466 ast::ExprCast(ref e, ref t) => {
3467 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3468 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3471 // Find the type of `e`. Supply hints based on the type we are casting to,
3473 let t_cast = fcx.to_ty(t);
3474 let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
3475 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
3476 let t_expr = fcx.expr_ty(e);
3478 // Eagerly check for some obvious errors.
3479 if t_expr.references_error() {
3480 fcx.write_error(id);
3481 } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
3482 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
3484 // Write a type for the whole expression, assuming everything is going
3486 fcx.write_ty(id, t_cast);
3488 // Defer other checks until we're done type checking.
3489 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3490 let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
3491 deferred_cast_checks.push(cast_check);
3494 ast::ExprVec(ref args) => {
3495 let uty = expected.to_option(fcx).and_then(|uty| {
3497 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3502 let typ = match uty {
3505 check_expr_coercable_to_type(fcx, &**e, uty);
3510 let t: Ty = fcx.infcx().next_ty_var();
3512 check_expr_has_type(fcx, &**e, t);
3517 let typ = tcx.mk_array(typ, args.len());
3518 fcx.write_ty(id, typ);
3520 ast::ExprRepeat(ref element, ref count_expr) => {
3521 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3522 let count = fcx.tcx().eval_repeat_count(&**count_expr);
3524 let uty = match expected {
3525 ExpectHasType(uty) => {
3527 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3534 let (element_ty, t) = match uty {
3536 check_expr_coercable_to_type(fcx, &**element, uty);
3540 let t: Ty = fcx.infcx().next_ty_var();
3541 check_expr_has_type(fcx, &**element, t);
3542 (fcx.expr_ty(&**element), t)
3547 // For [foo, ..n] where n > 1, `foo` must have
3549 fcx.require_type_meets(
3556 if element_ty.references_error() {
3557 fcx.write_error(id);
3559 let t = tcx.mk_array(t, count);
3560 fcx.write_ty(id, t);
3563 ast::ExprTup(ref elts) => {
3564 let flds = expected.only_has_type(fcx).and_then(|ty| {
3566 ty::TyTuple(ref flds) => Some(&flds[..]),
3570 let mut err_field = false;
3572 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3573 let t = match flds {
3574 Some(ref fs) if i < fs.len() => {
3576 check_expr_coercable_to_type(fcx, &**e, ety);
3580 check_expr_with_expectation(fcx, &**e, NoExpectation);
3584 err_field = err_field || t.references_error();
3588 fcx.write_error(id);
3590 let typ = tcx.mk_tup(elt_ts);
3591 fcx.write_ty(id, typ);
3594 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3595 // Resolve the path.
3596 let def = lookup_full_def(tcx, path.span, id);
3597 let struct_id = match def {
3598 def::DefVariant(enum_id, variant_id, true) => {
3599 if let &Some(ref base_expr) = base_expr {
3600 span_err!(tcx.sess, base_expr.span, E0436,
3601 "functional record update syntax requires a struct");
3602 fcx.write_error(base_expr.id);
3604 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3605 variant_id, &fields[..]);
3608 def::DefTrait(def_id) => {
3609 span_err!(tcx.sess, path.span, E0159,
3610 "use of trait `{}` as a struct constructor",
3611 pprust::path_to_string(path));
3612 check_struct_fields_on_error(fcx,
3619 // Verify that this was actually a struct.
3620 let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
3622 ty::TyStruct(struct_did, _) => {
3623 check_struct_constructor(fcx,
3628 base_expr.as_ref().map(|e| &**e));
3631 span_err!(tcx.sess, path.span, E0071,
3632 "`{}` does not name a structure",
3633 pprust::path_to_string(path));
3634 check_struct_fields_on_error(fcx,
3645 // Turn the path into a type and verify that that type unifies with
3646 // the resulting structure type. This is needed to handle type
3647 // parameters correctly.
3648 let actual_structure_type = fcx.expr_ty(&*expr);
3649 if !actual_structure_type.references_error() {
3650 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3651 match fcx.mk_subty(false,
3652 infer::Misc(path.span),
3653 actual_structure_type,
3654 type_and_substs.ty) {
3656 Err(type_error) => {
3657 span_err!(fcx.tcx().sess, path.span, E0235,
3658 "structure constructor specifies a \
3659 structure of type `{}`, but this \
3660 structure has type `{}`: {}",
3662 .ty_to_string(type_and_substs.ty),
3665 actual_structure_type),
3667 tcx.note_and_explain_type_err(&type_error, path.span);
3672 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3674 ast::ExprField(ref base, ref field) => {
3675 check_field(fcx, expr, lvalue_pref, &**base, field);
3677 ast::ExprTupField(ref base, idx) => {
3678 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3680 ast::ExprIndex(ref base, ref idx) => {
3681 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3682 check_expr(fcx, &**idx);
3684 let base_t = fcx.expr_ty(&**base);
3685 let idx_t = fcx.expr_ty(&**idx);
3687 if base_t.references_error() {
3688 fcx.write_ty(id, base_t);
3689 } else if idx_t.references_error() {
3690 fcx.write_ty(id, idx_t);
3692 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3693 match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3694 Some((index_ty, element_ty)) => {
3695 let idx_expr_ty = fcx.expr_ty(idx);
3696 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3697 fcx.write_ty(id, element_ty);
3700 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3701 fcx.type_error_message(
3704 format!("cannot index a value of type `{}`",
3709 fcx.write_ty(id, fcx.tcx().types.err);
3714 ast::ExprRange(ref start, ref end) => {
3715 let t_start = start.as_ref().map(|e| {
3716 check_expr(fcx, &**e);
3719 let t_end = end.as_ref().map(|e| {
3720 check_expr(fcx, &**e);
3724 let idx_type = match (t_start, t_end) {
3725 (Some(ty), None) | (None, Some(ty)) => {
3728 (Some(t_start), Some(t_end)) if (t_start.references_error() ||
3729 t_end.references_error()) => {
3730 Some(fcx.tcx().types.err)
3732 (Some(t_start), Some(t_end)) => {
3733 Some(infer::common_supertype(fcx.infcx(),
3734 infer::RangeExpression(expr.span),
3742 // Note that we don't check the type of start/end satisfy any
3743 // bounds because right now the range structs do not have any. If we add
3744 // some bounds, then we'll need to check `t_start` against them here.
3746 let range_type = match idx_type {
3747 Some(idx_type) if idx_type.references_error() => {
3751 // Find the did from the appropriate lang item.
3752 let did = match (start, end) {
3753 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3754 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3755 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3757 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3761 if let Some(did) = did {
3762 let predicates = tcx.lookup_predicates(did);
3763 let substs = Substs::new_type(vec![idx_type], vec![]);
3764 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
3765 fcx.add_obligations_for_parameters(
3766 traits::ObligationCause::new(expr.span,
3768 traits::ItemObligation(did)),
3771 tcx.mk_struct(did, tcx.mk_substs(substs))
3773 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
3778 // Neither start nor end => RangeFull
3779 if let Some(did) = tcx.lang_items.range_full_struct() {
3780 let substs = Substs::new_type(vec![], vec![]);
3781 tcx.mk_struct(did, tcx.mk_substs(substs))
3783 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
3789 fcx.write_ty(id, range_type);
3794 debug!("type of expr({}) {} is...", expr.id,
3795 syntax::print::pprust::expr_to_string(expr));
3796 debug!("... {:?}, expected is {:?}",
3803 pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
3804 path_res: def::PathResolution,
3805 opt_self_ty: Option<Ty<'tcx>>,
3806 path: &'a ast::Path,
3808 node_id: ast::NodeId)
3809 -> Option<(Option<Ty<'tcx>>,
3810 &'a [ast::PathSegment],
3814 // Associated constants can't depend on generic types.
3815 fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3819 node_id: ast::NodeId) -> bool {
3821 def::DefAssociatedConst(..) => {
3822 if ty.has_param_types() || ty.has_self_ty() {
3823 span_err!(fcx.sess(), span, E0329,
3824 "Associated consts cannot depend \
3825 on type parameters or Self.");
3826 fcx.write_error(node_id);
3835 // If fully resolved already, we don't have to do anything.
3836 if path_res.depth == 0 {
3837 if let Some(ty) = opt_self_ty {
3838 if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
3843 Some((opt_self_ty, &path.segments, path_res.base_def))
3845 let mut def = path_res.base_def;
3846 let ty_segments = path.segments.split_last().unwrap().1;
3847 let base_ty_end = path.segments.len() - path_res.depth;
3848 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
3849 PathParamMode::Optional,
3852 &ty_segments[..base_ty_end],
3853 &ty_segments[base_ty_end..]);
3854 let item_segment = path.segments.last().unwrap();
3855 let item_name = item_segment.identifier.name;
3856 match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
3858 if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
3861 // Write back the new resolution.
3862 fcx.ccx.tcx.def_map.borrow_mut()
3863 .insert(node_id, def::PathResolution {
3865 last_private: path_res.last_private.or(lp),
3868 Some((Some(ty), slice::ref_slice(item_segment), def))
3871 method::report_error(fcx, span, ty,
3872 item_name, None, error);
3873 fcx.write_error(node_id);
3880 fn constrain_path_type_parameters(fcx: &FnCtxt,
3883 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3884 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3888 impl<'tcx> Expectation<'tcx> {
3889 /// Provide an expectation for an rvalue expression given an *optional*
3890 /// hint, which is not required for type safety (the resulting type might
3891 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3892 /// is useful in determining the concrete type.
3894 /// The primary use case is where the expected type is a fat pointer,
3895 /// like `&[isize]`. For example, consider the following statement:
3897 /// let x: &[isize] = &[1, 2, 3];
3899 /// In this case, the expected type for the `&[1, 2, 3]` expression is
3900 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3901 /// expectation `ExpectHasType([isize])`, that would be too strong --
3902 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3903 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3904 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3905 /// which still is useful, because it informs integer literals and the like.
3906 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3907 /// for examples of where this comes up,.
3908 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
3910 ty::TySlice(_) | ty::TyTrait(..) => {
3911 ExpectRvalueLikeUnsized(ty)
3913 _ => ExpectHasType(ty)
3917 // Resolves `expected` by a single level if it is a variable. If
3918 // there is no expected type or resolution is not possible (e.g.,
3919 // no constraints yet present), just returns `None`.
3920 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3925 ExpectCastableToType(t) => {
3926 ExpectCastableToType(
3927 fcx.infcx().resolve_type_vars_if_possible(&t))
3929 ExpectHasType(t) => {
3931 fcx.infcx().resolve_type_vars_if_possible(&t))
3933 ExpectRvalueLikeUnsized(t) => {
3934 ExpectRvalueLikeUnsized(
3935 fcx.infcx().resolve_type_vars_if_possible(&t))
3940 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3941 match self.resolve(fcx) {
3942 NoExpectation => None,
3943 ExpectCastableToType(ty) |
3945 ExpectRvalueLikeUnsized(ty) => Some(ty),
3949 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3950 match self.resolve(fcx) {
3951 ExpectHasType(ty) => Some(ty),
3957 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3958 local: &'tcx ast::Local,
3959 init: &'tcx ast::Expr)
3961 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
3963 let local_ty = fcx.local_ty(init.span, local.id);
3964 if let Some(m) = ref_bindings {
3965 // Somewhat subtle: if we have a `ref` binding in the pattern,
3966 // we want to avoid introducing coercions for the RHS. This is
3967 // both because it helps preserve sanity and, in the case of
3968 // ref mut, for soundness (issue #23116). In particular, in
3969 // the latter case, we need to be clear that the type of the
3970 // referent for the reference that results is *equal to* the
3971 // type of the lvalue it is referencing, and not some
3972 // supertype thereof.
3973 check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
3974 let init_ty = fcx.expr_ty(init);
3975 demand::eqtype(fcx, init.span, init_ty, local_ty);
3977 check_expr_coercable_to_type(fcx, init, local_ty)
3981 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
3982 let tcx = fcx.ccx.tcx;
3984 let t = fcx.local_ty(local.span, local.id);
3985 fcx.write_ty(local.id, t);
3987 if let Some(ref init) = local.init {
3988 check_decl_initializer(fcx, local, &**init);
3989 let init_ty = fcx.expr_ty(&**init);
3990 if init_ty.references_error() {
3991 fcx.write_ty(local.id, init_ty);
3995 let pcx = pat_ctxt {
3997 map: pat_id_map(&tcx.def_map, &*local.pat),
3999 _match::check_pat(&pcx, &*local.pat, t);
4000 let pat_ty = fcx.node_ty(local.pat.id);
4001 if pat_ty.references_error() {
4002 fcx.write_ty(local.id, pat_ty);
4006 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4008 let mut saw_bot = false;
4009 let mut saw_err = false;
4011 ast::StmtDecl(ref decl, id) => {
4014 ast::DeclLocal(ref l) => {
4015 check_decl_local(fcx, &**l);
4016 let l_t = fcx.node_ty(l.id);
4017 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4018 saw_err = saw_err || l_t.references_error();
4020 ast::DeclItem(_) => {/* ignore for now */ }
4023 ast::StmtExpr(ref expr, id) => {
4025 // Check with expected type of ()
4026 check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
4027 let expr_ty = fcx.expr_ty(&**expr);
4028 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4029 saw_err = saw_err || expr_ty.references_error();
4031 ast::StmtSemi(ref expr, id) => {
4033 check_expr(fcx, &**expr);
4034 let expr_ty = fcx.expr_ty(&**expr);
4035 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4036 saw_err |= expr_ty.references_error();
4038 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4041 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4044 fcx.write_error(node_id);
4047 fcx.write_nil(node_id)
4051 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4052 check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
4053 let blkty = fcx.node_ty(blk.id);
4054 if blkty.references_error() {
4055 fcx.write_error(blk.id);
4057 let nilty = fcx.tcx().mk_nil();
4058 demand::suptype(fcx, blk.span, nilty, blkty);
4062 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4063 blk: &'tcx ast::Block,
4064 expected: Expectation<'tcx>) {
4066 let mut fcx_ps = fcx.ps.borrow_mut();
4067 let unsafety_state = fcx_ps.recurse(blk);
4068 replace(&mut *fcx_ps, unsafety_state)
4071 let mut warned = false;
4072 let mut any_diverges = false;
4073 let mut any_err = false;
4074 for s in &blk.stmts {
4075 check_stmt(fcx, &**s);
4076 let s_id = ast_util::stmt_id(&**s);
4077 let s_ty = fcx.node_ty(s_id);
4078 if any_diverges && !warned && match s.node {
4079 ast::StmtDecl(ref decl, _) => {
4081 ast::DeclLocal(_) => true,
4085 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4091 .add_lint(lint::builtin::UNREACHABLE_CODE,
4094 "unreachable statement".to_string());
4097 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4098 any_err = any_err || s_ty.references_error();
4101 None => if any_err {
4102 fcx.write_error(blk.id);
4103 } else if any_diverges {
4104 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4106 fcx.write_nil(blk.id);
4109 if any_diverges && !warned {
4113 .add_lint(lint::builtin::UNREACHABLE_CODE,
4116 "unreachable expression".to_string());
4118 let ety = match expected {
4119 ExpectHasType(ety) => {
4120 check_expr_coercable_to_type(fcx, &**e, ety);
4124 check_expr_with_expectation(fcx, &**e, expected);
4130 fcx.write_error(blk.id);
4131 } else if any_diverges {
4132 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4134 fcx.write_ty(blk.id, ety);
4139 *fcx.ps.borrow_mut() = prev;
4142 /// Checks a constant appearing in a type. At the moment this is just the
4143 /// length expression in a fixed-length vector, but someday it might be
4144 /// extended to type-level numeric literals.
4145 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4146 expr: &'tcx ast::Expr,
4147 expected_type: Ty<'tcx>) {
4148 let tables = RefCell::new(ty::Tables::empty());
4149 let inh = static_inherited_fields(ccx, &tables);
4150 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4151 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4154 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4158 let tables = RefCell::new(ty::Tables::empty());
4159 let inh = static_inherited_fields(ccx, &tables);
4160 let rty = ccx.tcx.node_id_to_type(id);
4161 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4162 let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
4163 check_const_with_ty(&fcx, sp, e, declty);
4166 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4170 // Gather locals in statics (because of block expressions).
4171 // This is technically unnecessary because locals in static items are forbidden,
4172 // but prevents type checking from blowing up before const checking can properly
4174 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4176 check_expr_with_hint(fcx, e, declty);
4177 demand::coerce(fcx, e.span, declty, e);
4178 fcx.select_all_obligations_or_error();
4180 regionck::regionck_expr(fcx, e);
4181 writeback::resolve_type_vars_in_expr(fcx, e);
4184 /// Checks whether a type can be represented in memory. In particular, it
4185 /// identifies types that contain themselves without indirection through a
4186 /// pointer, which would mean their size is unbounded.
4187 pub fn check_representable(tcx: &ty::ctxt,
4189 item_id: ast::NodeId,
4190 designation: &str) -> bool {
4191 let rty = tcx.node_id_to_type(item_id);
4193 // Check that it is possible to represent this type. This call identifies
4194 // (1) types that contain themselves and (2) types that contain a different
4195 // recursive type. It is only necessary to throw an error on those that
4196 // contain themselves. For case 2, there must be an inner type that will be
4197 // caught by case 1.
4198 match rty.is_representable(tcx, sp) {
4199 ty::SelfRecursive => {
4200 span_err!(tcx.sess, sp, E0072,
4201 "illegal recursive {} type; \
4202 wrap the inner value in a box to make it representable",
4206 ty::Representable | ty::ContainsRecursive => (),
4211 /// Checks whether a type can be constructed at runtime without
4212 /// an existing instance of that type.
4213 pub fn check_instantiable(tcx: &ty::ctxt,
4215 item_id: ast::NodeId) {
4216 let item_ty = tcx.node_id_to_type(item_id);
4217 if !item_ty.is_instantiable(tcx) &&
4218 !tcx.sess.features.borrow().static_recursion {
4219 emit_feature_err(&tcx.sess.parse_sess.span_diagnostic,
4222 "this type cannot be instantiated at runtime \
4223 without an instance of itself");
4227 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4228 let t = tcx.node_id_to_type(id);
4229 if t.needs_subst() {
4230 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4234 ty::TyStruct(did, substs) => {
4235 let fields = tcx.lookup_struct_fields(did);
4236 if fields.is_empty() {
4237 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4240 let e = tcx.lookup_field_type(did, fields[0].id, substs);
4241 if !fields.iter().all(
4242 |f| tcx.lookup_field_type(did, f.id, substs) == e) {
4243 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4246 if !e.is_machine() {
4247 span_err!(tcx.sess, sp, E0077,
4248 "SIMD vector element type should be machine type");
4256 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4258 vs: &'tcx [P<ast::Variant>],
4261 fn disr_in_range(ccx: &CrateCtxt,
4263 disr: ty::Disr) -> bool {
4264 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4266 ast::TyU8 => disr as u8 as Disr == disr,
4267 ast::TyU16 => disr as u16 as Disr == disr,
4268 ast::TyU32 => disr as u32 as Disr == disr,
4269 ast::TyU64 => disr as u64 as Disr == disr,
4270 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4273 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4275 ast::TyI8 => disr as i8 as Disr == disr,
4276 ast::TyI16 => disr as i16 as Disr == disr,
4277 ast::TyI32 => disr as i32 as Disr == disr,
4278 ast::TyI64 => disr as i64 as Disr == disr,
4279 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4283 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4284 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4288 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4289 vs: &'tcx [P<ast::Variant>],
4291 hint: attr::ReprAttr) {
4292 #![allow(trivial_numeric_casts)]
4294 let rty = ccx.tcx.node_id_to_type(id);
4295 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4297 let tables = RefCell::new(ty::Tables::empty());
4298 let inh = static_inherited_fields(ccx, &tables);
4299 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
4301 let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint));
4303 if let Some(ref e) = v.node.disr_expr {
4304 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
4308 let def_id = local_def(id);
4310 // ty::enum_variants guards against discriminant overflows, so
4311 // we need not check for that.
4312 let variants = ccx.tcx.enum_variants(def_id);
4314 for (v, variant) in vs.iter().zip(variants.iter()) {
4315 let current_disr_val = variant.disr_val;
4317 // Check for duplicate discriminant values
4318 match disr_vals.iter().position(|&x| x == current_disr_val) {
4320 span_err!(ccx.tcx.sess, v.span, E0081,
4321 "discriminant value `{}` already exists", disr_vals[i]);
4322 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4323 "conflicting discriminant here")
4327 // Check for unrepresentable discriminant values
4329 attr::ReprAny | attr::ReprExtern => (),
4330 attr::ReprInt(sp, ity) => {
4331 if !disr_in_range(ccx, ity, current_disr_val) {
4332 span_err!(ccx.tcx.sess, v.span, E0082,
4333 "discriminant value outside specified type");
4334 span_note!(ccx.tcx.sess, sp,
4335 "discriminant type specified here");
4338 attr::ReprPacked => {
4339 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4342 disr_vals.push(current_disr_val);
4346 let hint = *ccx.tcx.lookup_repr_hints(ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4347 .get(0).unwrap_or(&attr::ReprAny);
4349 if hint != attr::ReprAny && vs.len() <= 1 {
4351 span_err!(ccx.tcx.sess, sp, E0083,
4352 "unsupported representation for univariant enum");
4354 span_err!(ccx.tcx.sess, sp, E0084,
4355 "unsupported representation for zero-variant enum");
4359 do_check(ccx, vs, id, hint);
4361 check_representable(ccx.tcx, sp, id, "enum");
4362 check_instantiable(ccx.tcx, sp, id);
4365 // Returns the type parameter count and the type for the given definition.
4366 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4369 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4371 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4372 let typ = fcx.local_ty(sp, nid);
4373 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4374 ty::GenericPredicates::empty())
4376 def::DefFn(id, _) | def::DefMethod(id, _) |
4377 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4378 def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
4379 (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
4383 def::DefAssociatedTy(..) |
4385 def::DefTyParam(..) |
4387 def::DefForeignMod(..) |
4389 def::DefRegion(..) |
4391 def::DefSelfTy(..) => {
4392 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4397 // Instantiates the given path, which must refer to an item with the given
4398 // number of type parameters and type.
4399 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4400 segments: &[ast::PathSegment],
4401 type_scheme: TypeScheme<'tcx>,
4402 type_predicates: &ty::GenericPredicates<'tcx>,
4403 opt_self_ty: Option<Ty<'tcx>>,
4406 node_id: ast::NodeId) {
4407 debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
4413 // We need to extract the type parameters supplied by the user in
4414 // the path `path`. Due to the current setup, this is a bit of a
4415 // tricky-process; the problem is that resolve only tells us the
4416 // end-point of the path resolution, and not the intermediate steps.
4417 // Luckily, we can (at least for now) deduce the intermediate steps
4418 // just from the end-point.
4420 // There are basically four cases to consider:
4422 // 1. Reference to a *type*, such as a struct or enum:
4424 // mod a { struct Foo<T> { ... } }
4426 // Because we don't allow types to be declared within one
4427 // another, a path that leads to a type will always look like
4428 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4429 // that only the final segment can have type parameters, and
4430 // they are located in the TypeSpace.
4432 // *Note:* Generally speaking, references to types don't
4433 // actually pass through this function, but rather the
4434 // `ast_ty_to_ty` function in `astconv`. However, in the case
4435 // of struct patterns (and maybe literals) we do invoke
4436 // `instantiate_path` to get the general type of an instance of
4437 // a struct. (In these cases, there are actually no type
4438 // parameters permitted at present, but perhaps we will allow
4439 // them in the future.)
4441 // 1b. Reference to a enum variant or tuple-like struct:
4443 // struct foo<T>(...)
4444 // enum E<T> { foo(...) }
4446 // In these cases, the parameters are declared in the type
4449 // 2. Reference to a *fn item*:
4453 // In this case, the path will again always have the form
4454 // `a::b::foo::<T>` where only the final segment should have
4455 // type parameters. However, in this case, those parameters are
4456 // declared on a value, and hence are in the `FnSpace`.
4458 // 3. Reference to a *method*:
4460 // impl<A> SomeStruct<A> {
4464 // Here we can have a path like
4465 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4466 // may appear in two places. The penultimate segment,
4467 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4468 // final segment, `foo::<B>` contains parameters in fn space.
4470 // 4. Reference to an *associated const*:
4472 // impl<A> AnotherStruct<A> {
4473 // const FOO: B = BAR;
4476 // The path in this case will look like
4477 // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
4478 // only will have parameters in TypeSpace.
4480 // The first step then is to categorize the segments appropriately.
4482 assert!(!segments.is_empty());
4484 let mut ufcs_method = None;
4485 let mut segment_spaces: Vec<_>;
4487 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4488 def::DefSelfTy(..) |
4489 def::DefStruct(..) |
4490 def::DefVariant(..) |
4492 def::DefAssociatedTy(..) |
4494 def::DefPrimTy(..) |
4495 def::DefTyParam(..) => {
4496 // Everything but the final segment should have no
4497 // parameters at all.
4498 segment_spaces = vec![None; segments.len() - 1];
4499 segment_spaces.push(Some(subst::TypeSpace));
4502 // Case 2. Reference to a top-level value.
4505 def::DefStatic(..) => {
4506 segment_spaces = vec![None; segments.len() - 1];
4507 segment_spaces.push(Some(subst::FnSpace));
4510 // Case 3. Reference to a method.
4511 def::DefMethod(_, provenance) => {
4513 def::FromTrait(trait_did) => {
4514 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4516 def::FromImpl(_) => {}
4519 if segments.len() >= 2 {
4520 segment_spaces = vec![None; segments.len() - 2];
4521 segment_spaces.push(Some(subst::TypeSpace));
4522 segment_spaces.push(Some(subst::FnSpace));
4524 // `<T>::method` will end up here, and so can `T::method`.
4525 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4526 segment_spaces = vec![Some(subst::FnSpace)];
4527 ufcs_method = Some((provenance, self_ty));
4531 def::DefAssociatedConst(_, provenance) => {
4533 def::FromTrait(trait_did) => {
4534 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4536 def::FromImpl(_) => {}
4539 if segments.len() >= 2 {
4540 segment_spaces = vec![None; segments.len() - 2];
4541 segment_spaces.push(Some(subst::TypeSpace));
4542 segment_spaces.push(None);
4544 segment_spaces = vec![None];
4548 // Other cases. Various nonsense that really shouldn't show up
4549 // here. If they do, an error will have been reported
4550 // elsewhere. (I hope)
4552 def::DefForeignMod(..) |
4555 def::DefRegion(..) |
4557 def::DefUpvar(..) => {
4558 segment_spaces = vec![None; segments.len()];
4561 assert_eq!(segment_spaces.len(), segments.len());
4563 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4564 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4565 // type parameters are not mandatory.
4566 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
4568 debug!("segment_spaces={:?}", segment_spaces);
4570 // Next, examine the definition, and determine how many type
4571 // parameters we expect from each space.
4572 let type_defs = &type_scheme.generics.types;
4573 let region_defs = &type_scheme.generics.regions;
4575 // Now that we have categorized what space the parameters for each
4576 // segment belong to, let's sort out the parameters that the user
4577 // provided (if any) into their appropriate spaces. We'll also report
4578 // errors if type parameters are provided in an inappropriate place.
4579 let mut substs = Substs::empty();
4580 for (opt_space, segment) in segment_spaces.iter().zip(segments) {
4583 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4584 NO_TPS | NO_REGIONS);
4588 push_explicit_parameters_from_segment_to_substs(fcx,
4598 if let Some(self_ty) = opt_self_ty {
4599 if type_defs.len(subst::SelfSpace) == 1 {
4600 substs.types.push(subst::SelfSpace, self_ty);
4604 // Now we have to compare the types that the user *actually*
4605 // provided against the types that were *expected*. If the user
4606 // did not provide any types, then we want to substitute inference
4607 // variables. If the user provided some types, we may still need
4608 // to add defaults. If the user provided *too many* types, that's
4610 for &space in &ParamSpace::all() {
4611 adjust_type_parameters(fcx, span, space, type_defs,
4612 require_type_space, &mut substs);
4613 assert_eq!(substs.types.len(space), type_defs.len(space));
4615 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4616 assert_eq!(substs.regions().len(space), region_defs.len(space));
4619 // The things we are substituting into the type should not contain
4620 // escaping late-bound regions, and nor should the base type scheme.
4621 assert!(!substs.has_regions_escaping_depth(0));
4622 assert!(!type_scheme.has_escaping_regions());
4624 // Add all the obligations that are required, substituting and
4625 // normalized appropriately.
4626 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4627 fcx.add_obligations_for_parameters(
4628 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4631 // Substitute the values for the type parameters into the type of
4632 // the referenced item.
4633 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4636 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4637 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4638 // is inherent, there is no `Self` parameter, instead, the impl needs
4639 // type parameters, which we can infer by unifying the provided `Self`
4640 // with the substituted impl type.
4641 let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
4642 assert_eq!(substs.types.len(subst::TypeSpace),
4643 impl_scheme.generics.types.len(subst::TypeSpace));
4644 assert_eq!(substs.regions().len(subst::TypeSpace),
4645 impl_scheme.generics.regions.len(subst::TypeSpace));
4647 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4648 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4649 fcx.tcx().sess.span_bug(span,
4651 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
4657 fcx.write_ty(node_id, ty_substituted);
4658 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4661 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4662 /// parameters are provided, then reports an error and clears the output vector.
4664 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4665 /// use inference variables. This seems less likely to lead to derived errors.
4667 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4668 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4669 /// here because we can easily use the precise span of the N+1'th parameter.
4670 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4671 fcx: &FnCtxt<'a, 'tcx>,
4672 space: subst::ParamSpace,
4674 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4675 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4676 segment: &ast::PathSegment,
4677 substs: &mut Substs<'tcx>)
4679 match segment.parameters {
4680 ast::AngleBracketedParameters(ref data) => {
4681 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4682 fcx, space, type_defs, region_defs, data, substs);
4685 ast::ParenthesizedParameters(ref data) => {
4686 span_err!(fcx.tcx().sess, span, E0238,
4687 "parenthesized parameters may only be used with a trait");
4688 push_explicit_parenthesized_parameters_from_segment_to_substs(
4689 fcx, space, span, type_defs, data, substs);
4694 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4695 fcx: &FnCtxt<'a, 'tcx>,
4696 space: subst::ParamSpace,
4697 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4698 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4699 data: &ast::AngleBracketedParameterData,
4700 substs: &mut Substs<'tcx>)
4703 let type_count = type_defs.len(space);
4704 assert_eq!(substs.types.len(space), 0);
4705 for (i, typ) in data.types.iter().enumerate() {
4706 let t = fcx.to_ty(&**typ);
4708 substs.types.push(space, t);
4709 } else if i == type_count {
4710 span_err!(fcx.tcx().sess, typ.span, E0087,
4711 "too many type parameters provided: \
4712 expected at most {} parameter{}, \
4713 found {} parameter{}",
4715 if type_count == 1 {""} else {"s"},
4717 if data.types.len() == 1 {""} else {"s"});
4718 substs.types.truncate(space, 0);
4724 if !data.bindings.is_empty() {
4725 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4726 "unexpected binding of associated item in expression path \
4727 (only allowed in type paths)");
4731 let region_count = region_defs.len(space);
4732 assert_eq!(substs.regions().len(space), 0);
4733 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4734 let r = ast_region_to_region(fcx.tcx(), lifetime);
4735 if i < region_count {
4736 substs.mut_regions().push(space, r);
4737 } else if i == region_count {
4738 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4739 "too many lifetime parameters provided: \
4740 expected {} parameter{}, found {} parameter{}",
4742 if region_count == 1 {""} else {"s"},
4743 data.lifetimes.len(),
4744 if data.lifetimes.len() == 1 {""} else {"s"});
4745 substs.mut_regions().truncate(space, 0);
4753 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4754 /// but intended for `Foo(A,B) -> C` form. This expands to
4755 /// roughly the same thing as `Foo<(A,B),C>`. One important
4756 /// difference has to do with the treatment of anonymous
4757 /// regions, which are translated into bound regions (NYI).
4758 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4759 fcx: &FnCtxt<'a, 'tcx>,
4760 space: subst::ParamSpace,
4762 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4763 data: &ast::ParenthesizedParameterData,
4764 substs: &mut Substs<'tcx>)
4766 let type_count = type_defs.len(space);
4768 span_err!(fcx.tcx().sess, span, E0167,
4769 "parenthesized form always supplies 2 type parameters, \
4770 but only {} parameter(s) were expected",
4774 let input_tys: Vec<Ty> =
4775 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4777 let tuple_ty = fcx.tcx().mk_tup(input_tys);
4779 if type_count >= 1 {
4780 substs.types.push(space, tuple_ty);
4783 let output_ty: Option<Ty> =
4784 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4787 output_ty.unwrap_or(fcx.tcx().mk_nil());
4789 if type_count >= 2 {
4790 substs.types.push(space, output_ty);
4794 fn adjust_type_parameters<'a, 'tcx>(
4795 fcx: &FnCtxt<'a, 'tcx>,
4798 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4799 require_type_space: bool,
4800 substs: &mut Substs<'tcx>)
4802 let provided_len = substs.types.len(space);
4803 let desired = defs.get_slice(space);
4804 let required_len = desired.iter()
4805 .take_while(|d| d.default.is_none())
4808 debug!("adjust_type_parameters(space={:?}, \
4817 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4818 assert!(provided_len <= desired.len());
4820 // Nothing specified at all: supply inference variables for
4822 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4823 substs.types.replace(space, fcx.infcx().type_vars_for_defs(span, &desired[..]));
4827 // Too few parameters specified: report an error and use Err
4829 if provided_len < required_len {
4831 if desired.len() != required_len { "at least " } else { "" };
4832 span_err!(fcx.tcx().sess, span, E0089,
4833 "too few type parameters provided: expected {}{} parameter{}, \
4834 found {} parameter{}",
4835 qualifier, required_len,
4836 if required_len == 1 {""} else {"s"},
4838 if provided_len == 1 {""} else {"s"});
4839 substs.types.replace(space, vec![fcx.tcx().types.err; desired.len()]);
4843 // Otherwise, add in any optional parameters that the user
4844 // omitted. The case of *too many* parameters is handled
4846 // push_explicit_parameters_from_segment_to_substs(). Note
4847 // that the *default* type are expressed in terms of all prior
4848 // parameters, so we have to substitute as we go with the
4849 // partial substitution that we have built up.
4850 for i in provided_len..desired.len() {
4851 let default = desired[i].default.unwrap();
4852 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4853 substs.types.push(space, default);
4855 assert_eq!(substs.types.len(space), desired.len());
4857 debug!("Final substs: {:?}", substs);
4860 fn adjust_region_parameters(
4864 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4865 substs: &mut Substs)
4867 let provided_len = substs.mut_regions().len(space);
4868 let desired = defs.get_slice(space);
4870 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4871 assert!(provided_len <= desired.len());
4873 // If nothing was provided, just use inference variables.
4874 if provided_len == 0 {
4875 substs.mut_regions().replace(
4877 fcx.infcx().region_vars_for_defs(span, desired));
4881 // If just the right number were provided, everybody is happy.
4882 if provided_len == desired.len() {
4886 // Otherwise, too few were provided. Report an error and then
4887 // use inference variables.
4888 span_err!(fcx.tcx().sess, span, E0090,
4889 "too few lifetime parameters provided: expected {} parameter{}, \
4890 found {} parameter{}",
4892 if desired.len() == 1 {""} else {"s"},
4894 if provided_len == 1 {""} else {"s"});
4896 substs.mut_regions().replace(
4898 fcx.infcx().region_vars_for_defs(span, desired));
4902 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4906 where F: Fn() -> Ty<'tcx>
4908 let mut ty = fcx.resolve_type_vars_if_possible(ty);
4911 let alternative = f();
4914 if alternative.is_ty_var() || alternative.references_error() {
4915 fcx.type_error_message(sp, |_actual| {
4916 "the type of this value must be known in this context".to_string()
4918 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4919 ty = fcx.tcx().types.err;
4921 demand::suptype(fcx, sp, alternative, ty);
4929 // Resolves `typ` by a single level if `typ` is a type variable. If no
4930 // resolution is possible, then an error is reported.
4931 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4936 structurally_resolve_type_or_else(fcx, sp, ty, || {
4941 // Returns true if b contains a break that can exit from b
4942 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4943 // First: is there an unlabeled break immediately
4945 (loop_query(&*b, |e| {
4947 ast::ExprBreak(None) => true,
4951 // Second: is there a labeled break with label
4952 // <id> nested anywhere inside the loop?
4953 (block_query(b, |e| {
4954 if let ast::ExprBreak(Some(_)) = e.node {
4955 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
4962 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4964 tps: &OwnedSlice<ast::TyParam>,
4966 debug!("check_bounds_are_used(n_tps={}, ty={:?})",
4969 // make a vector of booleans initially false, set to true when used
4970 if tps.is_empty() { return; }
4971 let mut tps_used = vec![false; tps.len()];
4973 for leaf_ty in ty.walk() {
4974 if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
4975 debug!("Found use of ty param num {}", idx);
4976 tps_used[idx as usize] = true;
4980 for (i, b) in tps_used.iter().enumerate() {
4982 span_err!(ccx.tcx.sess, span, E0091,
4983 "type parameter `{}` is unused",
4984 token::get_ident(tps[i].ident));
4989 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
4990 /// and in libcore/intrinsics.rs
4991 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4992 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
4993 let name = token::intern(&format!("P{}", n));
4994 ccx.tcx.mk_param(subst::FnSpace, n, name)
4998 let name = token::get_ident(it.ident);
4999 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5000 let split : Vec<&str> = name.split('_').collect();
5001 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5003 //We only care about the operation here
5004 let (n_tps, inputs, output) = match split[1] {
5005 "cxchg" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
5009 "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
5011 "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5014 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5015 "min" | "umax" | "umin" => {
5016 (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5019 "fence" | "singlethreadfence" => {
5020 (0, Vec::new(), tcx.mk_nil())
5023 span_err!(tcx.sess, it.span, E0092,
5024 "unrecognized atomic operation function: `{}`", op);
5028 (n_tps, inputs, ty::FnConverging(output))
5029 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5030 (0, Vec::new(), ty::FnDiverging)
5032 let (n_tps, inputs, output) = match &name[..] {
5033 "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
5035 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
5036 "size_of_val" | "min_align_of_val" => {
5038 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5041 ], ccx.tcx.types.usize)
5043 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
5044 "uninit" => (1, Vec::new(), param(ccx, 0)),
5045 "forget" => (1, vec!( param(ccx, 0) ), tcx.mk_nil()),
5046 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5047 "move_val_init" => {
5050 tcx.mk_mut_ptr(param(ccx, 0)),
5055 "drop_in_place" => {
5056 (1, vec![tcx.mk_mut_ptr(param(ccx, 0))], tcx.mk_nil())
5058 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5060 "type_name" => (1, Vec::new(), tcx.mk_static_str()),
5061 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5062 "offset" | "arith_offset" => {
5065 tcx.mk_ptr(ty::TypeAndMut {
5067 mutbl: ast::MutImmutable
5071 tcx.mk_ptr(ty::TypeAndMut {
5073 mutbl: ast::MutImmutable
5076 "copy" | "copy_nonoverlapping" => {
5079 tcx.mk_ptr(ty::TypeAndMut {
5081 mutbl: ast::MutImmutable
5083 tcx.mk_ptr(ty::TypeAndMut {
5085 mutbl: ast::MutMutable
5091 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5094 tcx.mk_ptr(ty::TypeAndMut {
5096 mutbl: ast::MutMutable
5098 tcx.mk_ptr(ty::TypeAndMut {
5100 mutbl: ast::MutImmutable
5106 "write_bytes" | "volatile_set_memory" => {
5109 tcx.mk_ptr(ty::TypeAndMut {
5111 mutbl: ast::MutMutable
5118 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5119 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5122 vec!( tcx.types.f32, tcx.types.i32 ),
5127 vec!( tcx.types.f64, tcx.types.i32 ),
5130 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5131 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5132 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5133 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5136 vec!( tcx.types.f32, tcx.types.f32 ),
5141 vec!( tcx.types.f64, tcx.types.f64 ),
5144 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5145 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5146 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5147 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5148 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5149 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5150 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5151 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5152 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5153 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5156 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5161 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5164 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5165 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5166 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5167 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5168 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5169 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5170 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5171 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5172 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5173 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5174 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5175 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5176 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5177 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5178 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5179 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5180 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5181 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5182 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5183 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5184 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5185 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5186 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5187 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5188 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5189 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5190 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5191 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5192 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5193 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5194 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5197 (1, vec!( tcx.mk_imm_ptr(param(ccx, 0)) ), param(ccx, 0)),
5199 (1, vec!( tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ), tcx.mk_nil()),
5201 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5202 (0, vec!(tcx.types.i8, tcx.types.i8),
5203 tcx.mk_tup(vec!(tcx.types.i8, tcx.types.bool))),
5205 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5206 (0, vec!(tcx.types.i16, tcx.types.i16),
5207 tcx.mk_tup(vec!(tcx.types.i16, tcx.types.bool))),
5209 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5210 (0, vec!(tcx.types.i32, tcx.types.i32),
5211 tcx.mk_tup(vec!(tcx.types.i32, tcx.types.bool))),
5213 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5214 (0, vec!(tcx.types.i64, tcx.types.i64),
5215 tcx.mk_tup(vec!(tcx.types.i64, tcx.types.bool))),
5217 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5218 (0, vec!(tcx.types.u8, tcx.types.u8),
5219 tcx.mk_tup(vec!(tcx.types.u8, tcx.types.bool))),
5221 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5222 (0, vec!(tcx.types.u16, tcx.types.u16),
5223 tcx.mk_tup(vec!(tcx.types.u16, tcx.types.bool))),
5225 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5226 (0, vec!(tcx.types.u32, tcx.types.u32),
5227 tcx.mk_tup(vec!(tcx.types.u32, tcx.types.bool))),
5229 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5230 (0, vec!(tcx.types.u64, tcx.types.u64),
5231 tcx.mk_tup(vec!(tcx.types.u64, tcx.types.bool))),
5233 "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
5234 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5236 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5237 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5239 "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
5241 "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
5243 "discriminant_value" => (1, vec![
5244 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5246 param(ccx, 0))], tcx.types.u64),
5249 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
5250 let fn_ty = ty::BareFnTy {
5251 unsafety: ast::Unsafety::Normal,
5253 sig: ty::Binder(FnSig {
5254 inputs: vec![mut_u8],
5255 output: ty::FnOutput::FnConverging(tcx.mk_nil()),
5259 let fn_ty = tcx.mk_bare_fn(fn_ty);
5260 (0, vec![tcx.mk_fn(None, fn_ty), mut_u8], mut_u8)
5264 span_err!(tcx.sess, it.span, E0093,
5265 "unrecognized intrinsic function: `{}`", *other);
5269 (n_tps, inputs, ty::FnConverging(output))
5271 let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
5272 unsafety: ast::Unsafety::Unsafe,
5273 abi: abi::RustIntrinsic,
5274 sig: ty::Binder(FnSig {
5280 let i_ty = ccx.tcx.lookup_item_type(local_def(it.id));
5281 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5282 if i_n_tps != n_tps {
5283 span_err!(tcx.sess, it.span, E0094,
5284 "intrinsic has wrong number of type \
5285 parameters: found {}, expected {}",
5288 require_same_types(tcx,
5295 format!("intrinsic has wrong type: expected `{}`",