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)
1143 ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
1144 substs: Option<&mut subst::Substs<'tcx>>,
1145 space: Option<subst::ParamSpace>,
1146 span: Span) -> Ty<'tcx> {
1147 // Grab the default doing subsitution
1148 let default = ty_param_def.and_then(|def| {
1149 def.default.map(|ty| type_variable::Default {
1150 ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
1152 def_id: def.default_def_id
1156 let ty_var = self.infcx().next_ty_var_with_default(default);
1158 // Finally we add the type variable to the substs
1161 Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
1165 fn projected_ty_from_poly_trait_ref(&self,
1167 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1168 item_name: ast::Name)
1171 let (trait_ref, _) =
1172 self.infcx().replace_late_bound_regions_with_fresh_var(
1174 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1177 self.normalize_associated_type(span, trait_ref, item_name)
1180 fn projected_ty(&self,
1182 trait_ref: ty::TraitRef<'tcx>,
1183 item_name: ast::Name)
1186 self.normalize_associated_type(span, trait_ref, item_name)
1190 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1191 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1193 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1197 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1198 &self.inh.infcx.parameter_environment
1201 pub fn sess(&self) -> &Session {
1205 pub fn err_count_since_creation(&self) -> usize {
1206 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1209 /// Resolves type variables in `ty` if possible. Unlike the infcx
1210 /// version, this version will also select obligations if it seems
1211 /// useful, in an effort to get more type information.
1212 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1213 debug!("resolve_type_vars_if_possible(ty={:?})", ty);
1215 // No TyInfer()? Nothing needs doing.
1216 if !ty.has_infer_types() {
1217 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1221 // If `ty` is a type variable, see whether we already know what it is.
1222 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1223 if !ty.has_infer_types() {
1224 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1228 // If not, try resolving any new fcx obligations that have cropped up.
1229 self.select_new_obligations();
1230 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1231 if !ty.has_infer_types() {
1232 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1236 // If not, try resolving *all* pending obligations as much as
1237 // possible. This can help substantially when there are
1238 // indirect dependencies that don't seem worth tracking
1240 self.select_obligations_where_possible();
1241 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1243 debug!("resolve_type_vars_if_possible: ty={:?}", ty);
1247 fn record_deferred_call_resolution(&self,
1248 closure_def_id: ast::DefId,
1249 r: DeferredCallResolutionHandler<'tcx>) {
1250 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1251 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1254 fn remove_deferred_call_resolutions(&self,
1255 closure_def_id: ast::DefId)
1256 -> Vec<DeferredCallResolutionHandler<'tcx>>
1258 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1259 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1262 pub fn tag(&self) -> String {
1263 let self_ptr: *const FnCtxt = self;
1264 format!("{:?}", self_ptr)
1267 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1268 match self.inh.locals.borrow().get(&nid) {
1271 self.tcx().sess.span_err(
1273 &format!("no type for local variable {}", nid));
1274 self.tcx().types.err
1280 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1281 debug!("write_ty({}, {:?}) in fcx {}",
1282 node_id, ty, self.tag());
1283 self.inh.tables.borrow_mut().node_types.insert(node_id, ty);
1286 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1287 if !substs.substs.is_noop() {
1288 debug!("write_substs({}, {:?}) in fcx {}",
1293 self.inh.tables.borrow_mut().item_substs.insert(node_id, substs);
1297 pub fn write_autoderef_adjustment(&self,
1298 node_id: ast::NodeId,
1300 self.write_adjustment(
1302 ty::AdjustDerefRef(ty::AutoDerefRef {
1310 pub fn write_adjustment(&self,
1311 node_id: ast::NodeId,
1312 adj: ty::AutoAdjustment<'tcx>) {
1313 debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
1315 if adj.is_identity() {
1319 self.inh.tables.borrow_mut().adjustments.insert(node_id, adj);
1322 /// Basically whenever we are converting from a type scheme into
1323 /// the fn body space, we always want to normalize associated
1324 /// types as well. This function combines the two.
1325 fn instantiate_type_scheme<T>(&self,
1327 substs: &Substs<'tcx>,
1330 where T : TypeFoldable<'tcx> + HasTypeFlags
1332 let value = value.subst(self.tcx(), substs);
1333 let result = self.normalize_associated_types_in(span, &value);
1334 debug!("instantiate_type_scheme(value={:?}, substs={:?}) = {:?}",
1341 /// As `instantiate_type_scheme`, but for the bounds found in a
1342 /// generic type scheme.
1343 fn instantiate_bounds(&self,
1345 substs: &Substs<'tcx>,
1346 bounds: &ty::GenericPredicates<'tcx>)
1347 -> ty::InstantiatedPredicates<'tcx>
1349 ty::InstantiatedPredicates {
1350 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1355 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1356 where T : TypeFoldable<'tcx> + HasTypeFlags
1358 self.inh.normalize_associated_types_in(span, self.body_id, value)
1361 fn normalize_associated_type(&self,
1363 trait_ref: ty::TraitRef<'tcx>,
1364 item_name: ast::Name)
1367 let cause = traits::ObligationCause::new(span,
1369 traits::ObligationCauseCode::MiscObligation);
1374 .normalize_projection_type(self.infcx(),
1376 trait_ref: trait_ref,
1377 item_name: item_name,
1382 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1383 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1384 /// Registers any trait obligations specified on `def_id` at the same time.
1386 /// Note that function is only intended to be used with types (notably, not fns). This is
1387 /// because it doesn't do any instantiation of late-bound regions.
1388 pub fn instantiate_type(&self,
1391 -> TypeAndSubsts<'tcx>
1394 self.tcx().lookup_item_type(def_id);
1395 let type_predicates =
1396 self.tcx().lookup_predicates(def_id);
1398 self.infcx().fresh_substs_for_generics(
1400 &type_scheme.generics);
1402 self.instantiate_bounds(span, &substs, &type_predicates);
1403 self.add_obligations_for_parameters(
1404 traits::ObligationCause::new(
1407 traits::ItemObligation(def_id)),
1410 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1418 /// Returns the type that this AST path refers to. If the path has no type
1419 /// parameters and the corresponding type has type parameters, fresh type
1420 /// and/or region variables are substituted.
1422 /// This is used when checking the constructor in struct literals.
1423 fn instantiate_struct_literal_ty(&self,
1426 -> TypeAndSubsts<'tcx>
1428 let tcx = self.tcx();
1430 let ty::TypeScheme { generics, ty: decl_ty } =
1431 tcx.lookup_item_type(did);
1433 let substs = astconv::ast_path_substs_for_ty(self, self,
1435 PathParamMode::Optional,
1437 path.segments.last().unwrap());
1439 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1441 TypeAndSubsts { substs: substs, ty: ty }
1444 pub fn write_nil(&self, node_id: ast::NodeId) {
1445 self.write_ty(node_id, self.tcx().mk_nil());
1447 pub fn write_error(&self, node_id: ast::NodeId) {
1448 self.write_ty(node_id, self.tcx().types.err);
1451 pub fn require_type_meets(&self,
1454 code: traits::ObligationCauseCode<'tcx>,
1455 bound: ty::BuiltinBound)
1457 self.register_builtin_bound(
1460 traits::ObligationCause::new(span, self.body_id, code));
1463 pub fn require_type_is_sized(&self,
1466 code: traits::ObligationCauseCode<'tcx>)
1468 self.require_type_meets(ty, span, code, ty::BoundSized);
1471 pub fn require_expr_have_sized_type(&self,
1473 code: traits::ObligationCauseCode<'tcx>)
1475 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1478 pub fn type_is_known_to_be_sized(&self,
1483 traits::type_known_to_meet_builtin_bound(self.infcx(),
1489 pub fn register_builtin_bound(&self,
1491 builtin_bound: ty::BuiltinBound,
1492 cause: traits::ObligationCause<'tcx>)
1494 self.inh.infcx.fulfillment_cx.borrow_mut()
1495 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1498 pub fn register_predicate(&self,
1499 obligation: traits::PredicateObligation<'tcx>)
1501 debug!("register_predicate({:?})",
1503 self.inh.infcx.fulfillment_cx
1505 .register_predicate_obligation(self.infcx(), obligation);
1508 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1509 let t = ast_ty_to_ty(self, self, ast_t);
1511 let mut bounds_checker = wf::BoundsChecker::new(self,
1514 bounds_checker.check_ty(t, ast_t.span);
1519 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1520 match self.inh.tables.borrow().node_types.get(&ex.id) {
1523 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1529 /// Apply `adjustment` to the type of `expr`
1530 pub fn adjust_expr_ty(&self,
1532 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1535 let raw_ty = self.expr_ty(expr);
1536 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1537 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1538 raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| {
1539 self.inh.tables.borrow().method_map.get(&method_call)
1540 .map(|method| resolve_ty(method.ty))
1544 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1545 match self.inh.tables.borrow().node_types.get(&id) {
1547 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1549 self.tcx().sess.bug(
1550 &format!("no type for node {}: {} in fcx {}",
1551 id, self.tcx().map.node_to_string(id),
1557 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1558 // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if
1559 // it changes when we upgrade the snapshot compiler
1560 fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
1561 -> &'a NodeMap<ty::ItemSubsts<'tcx>> {
1565 Ref::map(self.inh.tables.borrow(), project_item_susbts)
1568 pub fn opt_node_ty_substs<F>(&self,
1571 F: FnOnce(&ty::ItemSubsts<'tcx>),
1573 match self.inh.tables.borrow().item_substs.get(&id) {
1579 pub fn mk_subty(&self,
1580 a_is_expected: bool,
1581 origin: infer::TypeOrigin,
1584 -> Result<(), ty::TypeError<'tcx>> {
1585 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1588 pub fn mk_eqty(&self,
1589 a_is_expected: bool,
1590 origin: infer::TypeOrigin,
1593 -> Result<(), ty::TypeError<'tcx>> {
1594 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1597 pub fn mk_subr(&self,
1598 origin: infer::SubregionOrigin<'tcx>,
1601 infer::mk_subr(self.infcx(), origin, sub, sup)
1604 pub fn type_error_message<M>(&self,
1607 actual_ty: Ty<'tcx>,
1608 err: Option<&ty::TypeError<'tcx>>) where
1609 M: FnOnce(String) -> String,
1611 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1614 pub fn report_mismatched_types(&self,
1618 err: &ty::TypeError<'tcx>) {
1619 self.infcx().report_mismatched_types(sp, e, a, err)
1622 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1623 /// outlive the region `r`.
1624 pub fn register_region_obligation(&self,
1627 cause: traits::ObligationCause<'tcx>)
1629 let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1630 fulfillment_cx.register_region_obligation(ty, region, cause);
1633 pub fn add_default_region_param_bounds(&self,
1634 substs: &Substs<'tcx>,
1637 for &ty in &substs.types {
1638 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1639 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1640 traits::MiscObligation);
1641 self.register_region_obligation(ty, default_bound, cause);
1645 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1646 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1647 /// trait/region obligations.
1649 /// For example, if there is a function:
1652 /// fn foo<'a,T:'a>(...)
1655 /// and a reference:
1661 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1662 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1663 pub fn add_obligations_for_parameters(&self,
1664 cause: traits::ObligationCause<'tcx>,
1665 predicates: &ty::InstantiatedPredicates<'tcx>)
1667 assert!(!predicates.has_escaping_regions());
1669 debug!("add_obligations_for_parameters(predicates={:?})",
1672 for obligation in traits::predicates_for_generics(cause, predicates) {
1673 self.register_predicate(obligation);
1677 // Only for fields! Returns <none> for methods>
1678 // Indifferent to privacy flags
1679 pub fn lookup_field_ty(&self,
1681 class_id: ast::DefId,
1682 items: &[ty::FieldTy],
1683 fieldname: ast::Name,
1684 substs: &subst::Substs<'tcx>)
1687 let o_field = items.iter().find(|f| f.name == fieldname);
1688 o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
1689 .map(|t| self.normalize_associated_types_in(span, &t))
1692 pub fn lookup_tup_field_ty(&self,
1694 class_id: ast::DefId,
1695 items: &[ty::FieldTy],
1697 substs: &subst::Substs<'tcx>)
1700 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1701 o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
1702 .map(|t| self.normalize_associated_types_in(span, &t))
1705 fn check_casts(&self) {
1706 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1707 for cast in deferred_cast_checks.drain(..) {
1712 fn select_all_obligations_and_apply_defaults(&self) {
1713 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1715 // For the time being this errs on the side of being memory wasteful but provides better
1717 // let type_variables = self.infcx().type_variables.clone();
1719 // There is a possibility that this algorithm will have to run an arbitrary number of times
1720 // to terminate so we bound it by the compiler's recursion limit.
1721 for _ in (0..self.tcx().sess.recursion_limit.get()) {
1722 // First we try to solve all obligations, it is possible that the last iteration
1723 // has made it possible to make more progress.
1724 self.select_obligations_where_possible();
1726 let mut conflicts = Vec::new();
1728 // Collect all unsolved type, integral and floating point variables.
1729 let unsolved_variables = self.inh.infcx.unsolved_variables();
1731 // We must collect the defaults *before* we do any unification. Because we have
1732 // directly attached defaults to the type variables any unification that occurs
1733 // will erase defaults causing conflicting defaults to be completely ignored.
1734 let default_map: FnvHashMap<_, _> =
1737 .filter_map(|t| self.infcx().default(t).map(|d| (t, d)))
1740 let mut unbound_tyvars = HashSet::new();
1742 debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);
1744 // We loop over the unsolved variables, resolving them and if they are
1745 // and unconstrainted numberic type we add them to the set of unbound
1746 // variables. We do this so we only apply literal fallback to type
1747 // variables without defaults.
1748 for ty in &unsolved_variables {
1749 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1750 if self.infcx().type_var_diverges(resolved) {
1751 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1753 match self.infcx().type_is_unconstrained_numeric(resolved) {
1754 UnconstrainedInt | UnconstrainedFloat => {
1755 unbound_tyvars.insert(resolved);
1762 // We now remove any numeric types that also have defaults, and instead insert
1763 // the type variable with a defined fallback.
1764 for ty in &unsolved_variables {
1765 if let Some(_default) = default_map.get(ty) {
1766 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1768 debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
1771 match resolved.sty {
1772 ty::TyInfer(ty::TyVar(_)) => {
1773 unbound_tyvars.insert(ty);
1776 ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
1777 unbound_tyvars.insert(ty);
1778 if unbound_tyvars.contains(resolved) {
1779 unbound_tyvars.remove(resolved);
1788 // If there are no more fallbacks to apply at this point we have applied all possible
1789 // defaults and type inference will procede as normal.
1790 if unbound_tyvars.is_empty() {
1794 // Finally we go through each of the unbound type variables and unify them with
1795 // the proper fallback, reporting a conflicting default error if any of the
1796 // unifications fail. We know it must be a conflicting default because the
1797 // variable would only be in `unbound_tyvars` and have a concrete value if
1798 // it had been solved by previously applying a default.
1800 // We wrap this in a transaction for error reporting, if we detect a conflict
1801 // we will rollback the inference context to its prior state so we can probe
1802 // for conflicts and correctly report them.
1805 let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
1806 for ty in &unbound_tyvars {
1807 if self.infcx().type_var_diverges(ty) {
1808 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1810 match self.infcx().type_is_unconstrained_numeric(ty) {
1811 UnconstrainedInt => {
1812 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1814 UnconstrainedFloat => {
1815 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1818 if let Some(default) = default_map.get(ty) {
1819 let default = default.clone();
1820 match infer::mk_eqty(self.infcx(), false,
1821 infer::Misc(default.origin_span),
1825 conflicts.push((*ty, default));
1834 // If there are conflicts we rollback, otherwise commit
1835 if conflicts.len() > 0 {
1842 if conflicts.len() > 0 {
1843 // Loop through each conflicting default, figuring out the default that caused
1844 // a unification failure and then report an error for each.
1845 for (conflict, default) in conflicts {
1846 let conflicting_default =
1847 self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
1848 .unwrap_or(type_variable::Default {
1849 ty: self.infcx().next_ty_var(),
1850 origin_span: codemap::DUMMY_SP,
1851 def_id: local_def(0) // what do I put here?
1854 // This is to ensure that we elimnate any non-determinism from the error
1855 // reporting by fixing an order, it doesn't matter what order we choose
1856 // just that it is consistent.
1857 let (first_default, second_default) =
1858 if default.def_id < conflicting_default.def_id {
1859 (default, conflicting_default)
1861 (conflicting_default, default)
1865 self.infcx().report_conflicting_default_types(
1866 first_default.origin_span,
1873 self.select_obligations_where_possible();
1876 // For use in error handling related to default type parameter fallback. We explicitly
1877 // apply the default that caused conflict first to a local version of the type variable
1878 // table then apply defaults until we find a conflict. That default must be the one
1879 // that caused conflict earlier.
1880 fn find_conflicting_default(&self,
1881 unbound_vars: &HashSet<Ty<'tcx>>,
1882 default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
1884 -> Option<type_variable::Default<'tcx>> {
1885 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1887 // Ensure that we apply the conflicting default first
1888 let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
1889 unbound_tyvars.push(conflict);
1890 unbound_tyvars.extend(unbound_vars.iter());
1892 let mut result = None;
1893 // We run the same code as above applying defaults in order, this time when
1894 // we find the conflict we just return it for error reporting above.
1896 // We also run this inside snapshot that never commits so we can do error
1897 // reporting for more then one conflict.
1898 for ty in &unbound_tyvars {
1899 if self.infcx().type_var_diverges(ty) {
1900 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1902 match self.infcx().type_is_unconstrained_numeric(ty) {
1903 UnconstrainedInt => {
1904 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1906 UnconstrainedFloat => {
1907 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1910 if let Some(default) = default_map.get(ty) {
1911 let default = default.clone();
1912 match infer::mk_eqty(self.infcx(), false,
1913 infer::Misc(default.origin_span),
1917 result = Some(default);
1929 fn select_all_obligations_or_error(&self) {
1930 debug!("select_all_obligations_or_error");
1932 // upvar inference should have ensured that all deferred call
1933 // resolutions are handled by now.
1934 assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
1936 self.select_all_obligations_and_apply_defaults();
1937 let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1938 match fulfillment_cx.select_all_or_error(self.infcx()) {
1940 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1944 /// Select as many obligations as we can at present.
1945 fn select_obligations_where_possible(&self) {
1947 self.inh.infcx.fulfillment_cx
1949 .select_where_possible(self.infcx())
1952 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1956 /// Try to select any fcx obligation that we haven't tried yet, in an effort
1957 /// to improve inference. You could just call
1958 /// `select_obligations_where_possible` except that it leads to repeated
1960 fn select_new_obligations(&self) {
1962 self.inh.infcx.fulfillment_cx
1964 .select_new_obligations(self.infcx())
1967 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1973 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1974 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1975 Some(self.base_object_lifetime_default(span))
1978 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
1979 // RFC #599 specifies that object lifetime defaults take
1980 // precedence over other defaults. But within a fn body we
1981 // don't have a *default* region, rather we use inference to
1982 // find the *correct* region, which is strictly more general
1983 // (and anyway, within a fn body the right region may not even
1984 // be something the user can write explicitly, since it might
1985 // be some expression).
1986 self.infcx().next_region_var(infer::MiscVariable(span))
1989 fn anon_regions(&self, span: Span, count: usize)
1990 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
1991 Ok((0..count).map(|_| {
1992 self.infcx().next_region_var(infer::MiscVariable(span))
1997 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1998 pub enum LvaluePreference {
2003 impl LvaluePreference {
2004 pub fn from_mutbl(m: ast::Mutability) -> Self {
2006 ast::MutMutable => PreferMutLvalue,
2007 ast::MutImmutable => NoPreference,
2012 /// Whether `autoderef` requires types to resolve.
2013 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
2014 pub enum UnresolvedTypeAction {
2015 /// Produce an error and return `TyError` whenever a type cannot
2016 /// be resolved (i.e. it is `TyInfer`).
2018 /// Go on without emitting any errors, and return the unresolved
2019 /// type. Useful for probing, e.g. in coercions.
2023 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
2024 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
2026 /// Note: this method does not modify the adjustments table. The caller is responsible for
2027 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
2028 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2031 opt_expr: Option<&ast::Expr>,
2032 unresolved_type_action: UnresolvedTypeAction,
2033 mut lvalue_pref: LvaluePreference,
2035 -> (Ty<'tcx>, usize, Option<T>)
2036 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
2038 debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
2043 let mut t = base_ty;
2044 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
2045 let resolved_t = match unresolved_type_action {
2046 UnresolvedTypeAction::Error => {
2047 structurally_resolved_type(fcx, sp, t)
2049 UnresolvedTypeAction::Ignore => {
2050 // We can continue even when the type cannot be resolved
2051 // (i.e. it is an inference variable) because `Ty::builtin_deref`
2052 // and `try_overloaded_deref` both simply return `None`
2053 // in such a case without producing spurious errors.
2054 fcx.resolve_type_vars_if_possible(t)
2057 if resolved_t.references_error() {
2058 return (resolved_t, autoderefs, None);
2061 match should_stop(resolved_t, autoderefs) {
2062 Some(x) => return (resolved_t, autoderefs, Some(x)),
2066 // Otherwise, deref if type is derefable:
2067 let mt = match resolved_t.builtin_deref(false) {
2068 Some(mt) => Some(mt),
2071 opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
2073 // Super subtle: it might seem as though we should
2074 // pass `opt_expr` to `try_overloaded_deref`, so that
2075 // the (implicit) autoref of using an overloaded deref
2076 // would get added to the adjustment table. However we
2077 // do not do that, because it's kind of a
2078 // "meta-adjustment" -- instead, we just leave it
2079 // unrecorded and know that there "will be" an
2080 // autoref. regionck and other bits of the code base,
2081 // when they encounter an overloaded autoderef, have
2082 // to do some reconstructive surgery. This is a pretty
2083 // complex mess that is begging for a proper MIR.
2084 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2090 if mt.mutbl == ast::MutImmutable {
2091 lvalue_pref = NoPreference;
2094 None => return (resolved_t, autoderefs, None)
2098 // We've reached the recursion limit, error gracefully.
2099 span_err!(fcx.tcx().sess, sp, E0055,
2100 "reached the recursion limit while auto-dereferencing {:?}",
2102 (fcx.tcx().types.err, 0, None)
2105 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2107 method_call: Option<MethodCall>,
2108 base_expr: Option<&ast::Expr>,
2110 lvalue_pref: LvaluePreference)
2111 -> Option<ty::TypeAndMut<'tcx>>
2113 // Try DerefMut first, if preferred.
2114 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2115 (PreferMutLvalue, Some(trait_did)) => {
2116 method::lookup_in_trait(fcx, span, base_expr,
2117 token::intern("deref_mut"), trait_did,
2123 // Otherwise, fall back to Deref.
2124 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2125 (None, Some(trait_did)) => {
2126 method::lookup_in_trait(fcx, span, base_expr,
2127 token::intern("deref"), trait_did,
2130 (method, _) => method
2133 make_overloaded_lvalue_return_type(fcx, method_call, method)
2136 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2137 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2138 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2139 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2140 method_call: Option<MethodCall>,
2141 method: Option<MethodCallee<'tcx>>)
2142 -> Option<ty::TypeAndMut<'tcx>>
2146 // extract method method return type, which will be &T;
2147 // all LB regions should have been instantiated during method lookup
2148 let ret_ty = method.ty.fn_ret();
2149 let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
2151 if let Some(method_call) = method_call {
2152 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2155 // method returns &T, but the type as visible to user is T, so deref
2156 ret_ty.builtin_deref(true)
2162 fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2164 base_expr: &'tcx ast::Expr,
2167 lvalue_pref: LvaluePreference)
2168 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2170 // FIXME(#18741) -- this is almost but not quite the same as the
2171 // autoderef that normal method probing does. They could likely be
2174 let (ty, autoderefs, final_mt) = autoderef(fcx,
2178 UnresolvedTypeAction::Error,
2181 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2182 adj_ty, idx, false, lvalue_pref, idx_ty)
2185 if final_mt.is_some() {
2189 // After we have fully autoderef'd, if the resulting type is [T; n], then
2190 // do a final unsized coercion to yield [T].
2191 if let ty::TyArray(element_ty, _) = ty.sty {
2192 let adjusted_ty = fcx.tcx().mk_slice(element_ty);
2193 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2194 adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
2200 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2201 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2202 /// This loop implements one step in that search; the autoderef loop is implemented by
2203 /// `lookup_indexing`.
2204 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2205 method_call: MethodCall,
2207 base_expr: &'tcx ast::Expr,
2208 adjusted_ty: Ty<'tcx>,
2211 lvalue_pref: LvaluePreference,
2213 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2215 let tcx = fcx.tcx();
2216 debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
2217 autoderefs={}, unsize={}, index_ty={:?})",
2225 let input_ty = fcx.infcx().next_ty_var();
2227 // First, try built-in indexing.
2228 match (adjusted_ty.builtin_index(), &index_ty.sty) {
2229 (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
2230 debug!("try_index_step: success, using built-in indexing");
2231 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2233 fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
2234 return Some((tcx.types.usize, ty));
2239 // Try `IndexMut` first, if preferred.
2240 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2241 (PreferMutLvalue, Some(trait_did)) => {
2242 method::lookup_in_trait_adjusted(fcx,
2245 token::intern("index_mut"),
2250 Some(vec![input_ty]))
2255 // Otherwise, fall back to `Index`.
2256 let method = match (method, tcx.lang_items.index_trait()) {
2257 (None, Some(trait_did)) => {
2258 method::lookup_in_trait_adjusted(fcx,
2261 token::intern("index"),
2266 Some(vec![input_ty]))
2268 (method, _) => method,
2271 // If some lookup succeeds, write callee into table and extract index/element
2272 // type from the method signature.
2273 // If some lookup succeeded, install method in table
2274 method.and_then(|method| {
2275 debug!("try_index_step: success, using overloaded indexing");
2276 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2277 map(|ret| (input_ty, ret.ty))
2281 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2283 method_fn_ty: Ty<'tcx>,
2284 callee_expr: &'tcx ast::Expr,
2285 args_no_rcvr: &'tcx [P<ast::Expr>],
2286 tuple_arguments: TupleArgumentsFlag,
2287 expected: Expectation<'tcx>)
2288 -> ty::FnOutput<'tcx> {
2289 if method_fn_ty.references_error() {
2290 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2292 let err_inputs = match tuple_arguments {
2293 DontTupleArguments => err_inputs,
2294 TupleArguments => vec![fcx.tcx().mk_tup(err_inputs)],
2297 check_argument_types(fcx,
2304 ty::FnConverging(fcx.tcx().types.err)
2306 match method_fn_ty.sty {
2307 ty::TyBareFn(_, ref fty) => {
2308 // HACK(eddyb) ignore self in the definition (see above).
2309 let expected_arg_tys = expected_types_for_fn_args(fcx,
2313 &fty.sig.0.inputs[1..]);
2314 check_argument_types(fcx,
2316 &fty.sig.0.inputs[1..],
2317 &expected_arg_tys[..],
2324 fcx.tcx().sess.span_bug(callee_expr.span,
2325 "method without bare fn type");
2331 /// Generic function that factors out common logic from function calls, method calls and overloaded
2333 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2335 fn_inputs: &[Ty<'tcx>],
2336 expected_arg_tys: &[Ty<'tcx>],
2337 args: &'tcx [P<ast::Expr>],
2339 tuple_arguments: TupleArgumentsFlag) {
2340 let tcx = fcx.ccx.tcx;
2342 // Grab the argument types, supplying fresh type variables
2343 // if the wrong number of arguments were supplied
2344 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2350 let mut expected_arg_tys = expected_arg_tys;
2351 let expected_arg_count = fn_inputs.len();
2352 let formal_tys = if tuple_arguments == TupleArguments {
2353 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2354 match tuple_type.sty {
2355 ty::TyTuple(ref arg_types) => {
2356 if arg_types.len() != args.len() {
2357 span_err!(tcx.sess, sp, E0057,
2358 "this function takes {} parameter{} but {} parameter{} supplied",
2360 if arg_types.len() == 1 {""} else {"s"},
2362 if args.len() == 1 {" was"} else {"s were"});
2363 expected_arg_tys = &[];
2364 err_args(fcx.tcx(), args.len())
2366 expected_arg_tys = match expected_arg_tys.get(0) {
2367 Some(&ty) => match ty.sty {
2368 ty::TyTuple(ref tys) => &**tys,
2373 (*arg_types).clone()
2377 span_err!(tcx.sess, sp, E0059,
2378 "cannot use call notation; the first type parameter \
2379 for the function trait is neither a tuple nor unit");
2380 expected_arg_tys = &[];
2381 err_args(fcx.tcx(), args.len())
2384 } else if expected_arg_count == supplied_arg_count {
2386 } else if variadic {
2387 if supplied_arg_count >= expected_arg_count {
2390 span_err!(tcx.sess, sp, E0060,
2391 "this function takes at least {} parameter{} \
2392 but {} parameter{} supplied",
2394 if expected_arg_count == 1 {""} else {"s"},
2396 if supplied_arg_count == 1 {" was"} else {"s were"});
2397 expected_arg_tys = &[];
2398 err_args(fcx.tcx(), supplied_arg_count)
2401 span_err!(tcx.sess, sp, E0061,
2402 "this function takes {} parameter{} but {} parameter{} supplied",
2404 if expected_arg_count == 1 {""} else {"s"},
2406 if supplied_arg_count == 1 {" was"} else {"s were"});
2407 expected_arg_tys = &[];
2408 err_args(fcx.tcx(), supplied_arg_count)
2411 debug!("check_argument_types: formal_tys={:?}",
2412 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2414 // Check the arguments.
2415 // We do this in a pretty awful way: first we typecheck any arguments
2416 // that are not anonymous functions, then we typecheck the anonymous
2417 // functions. This is so that we have more information about the types
2418 // of arguments when we typecheck the functions. This isn't really the
2419 // right way to do this.
2420 let xs = [false, true];
2421 for check_blocks in &xs {
2422 let check_blocks = *check_blocks;
2423 debug!("check_blocks={}", check_blocks);
2425 // More awful hacks: before we check argument types, try to do
2426 // an "opportunistic" vtable resolution of any trait bounds on
2427 // the call. This helps coercions.
2429 fcx.select_new_obligations();
2432 // For variadic functions, we don't have a declared type for all of
2433 // the arguments hence we only do our usual type checking with
2434 // the arguments who's types we do know.
2435 let t = if variadic {
2437 } else if tuple_arguments == TupleArguments {
2442 for (i, arg) in args.iter().take(t).enumerate() {
2443 let is_block = match arg.node {
2444 ast::ExprClosure(..) => true,
2448 if is_block == check_blocks {
2449 debug!("checking the argument");
2450 let formal_ty = formal_tys[i];
2452 // The special-cased logic below has three functions:
2453 // 1. Provide as good of an expected type as possible.
2454 let expected = expected_arg_tys.get(i).map(|&ty| {
2455 Expectation::rvalue_hint(ty)
2458 check_expr_with_unifier(fcx, &**arg,
2459 expected.unwrap_or(ExpectHasType(formal_ty)),
2461 // 2. Coerce to the most detailed type that could be coerced
2462 // to, which is `expected_ty` if `rvalue_hint` returns an
2463 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2464 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2465 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2467 // 3. Relate the expected type and the formal one,
2468 // if the expected type was used for the coercion.
2469 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2475 // We also need to make sure we at least write the ty of the other
2476 // arguments which we skipped above.
2478 for arg in args.iter().skip(expected_arg_count) {
2479 check_expr(fcx, &**arg);
2481 // There are a few types which get autopromoted when passed via varargs
2482 // in C but we just error out instead and require explicit casts.
2483 let arg_ty = structurally_resolved_type(fcx, arg.span,
2484 fcx.expr_ty(&**arg));
2486 ty::TyFloat(ast::TyF32) => {
2487 fcx.type_error_message(arg.span,
2489 format!("can't pass an {} to variadic \
2490 function, cast to c_double", t)
2493 ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
2494 fcx.type_error_message(arg.span, |t| {
2495 format!("can't pass {} to variadic \
2496 function, cast to c_int",
2500 ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
2501 fcx.type_error_message(arg.span, |t| {
2502 format!("can't pass {} to variadic \
2503 function, cast to c_uint",
2513 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2514 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2515 (0..len).map(|_| tcx.types.err).collect()
2518 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2519 call_expr: &ast::Expr,
2520 output: ty::FnOutput<'tcx>) {
2521 fcx.write_ty(call_expr.id, match output {
2522 ty::FnConverging(output_ty) => output_ty,
2523 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2527 // AST fragment checking
2528 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2530 expected: Expectation<'tcx>)
2533 let tcx = fcx.ccx.tcx;
2536 ast::LitStr(..) => tcx.mk_static_str(),
2537 ast::LitBinary(ref v) => {
2538 tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
2539 tcx.mk_array(tcx.types.u8, v.len()))
2541 ast::LitByte(_) => tcx.types.u8,
2542 ast::LitChar(_) => tcx.types.char,
2543 ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
2544 ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
2545 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2546 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2548 ty::TyInt(_) | ty::TyUint(_) => Some(ty),
2549 ty::TyChar => Some(tcx.types.u8),
2550 ty::TyRawPtr(..) => Some(tcx.types.usize),
2551 ty::TyBareFn(..) => Some(tcx.types.usize),
2555 opt_ty.unwrap_or_else(
2556 || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
2558 ast::LitFloat(_, t) => tcx.mk_mach_float(t),
2559 ast::LitFloatUnsuffixed(_) => {
2560 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2562 ty::TyFloat(_) => Some(ty),
2566 opt_ty.unwrap_or_else(
2567 || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
2569 ast::LitBool(_) => tcx.types.bool
2573 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2574 expr: &'tcx ast::Expr,
2575 expected: Ty<'tcx>) {
2576 check_expr_with_unifier(
2577 fcx, expr, ExpectHasType(expected), NoPreference,
2578 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2581 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2582 expr: &'tcx ast::Expr,
2583 expected: Ty<'tcx>) {
2584 check_expr_with_unifier(
2585 fcx, expr, ExpectHasType(expected), NoPreference,
2586 || demand::coerce(fcx, expr.span, expected, expr));
2589 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2590 expected: Ty<'tcx>) {
2591 check_expr_with_unifier(
2592 fcx, expr, ExpectHasType(expected), NoPreference,
2596 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2597 expr: &'tcx ast::Expr,
2598 expected: Expectation<'tcx>) {
2599 check_expr_with_unifier(
2600 fcx, expr, expected, NoPreference,
2604 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2605 expr: &'tcx ast::Expr,
2606 expected: Expectation<'tcx>,
2607 lvalue_pref: LvaluePreference)
2609 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2612 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2613 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2616 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2617 lvalue_pref: LvaluePreference) {
2618 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2621 // determine the `self` type, using fresh variables for all variables
2622 // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
2623 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2625 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2626 span: Span, // (potential) receiver for this impl
2628 -> TypeAndSubsts<'tcx> {
2629 let tcx = fcx.tcx();
2631 let ity = tcx.lookup_item_type(did);
2632 let (tps, rps, raw_ty) =
2633 (ity.generics.types.get_slice(subst::TypeSpace),
2634 ity.generics.regions.get_slice(subst::TypeSpace),
2637 debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
2639 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2640 let mut substs = subst::Substs::new(
2641 VecPerParamSpace::empty(),
2642 VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
2643 fcx.inh.infcx.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
2644 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2646 TypeAndSubsts { substs: substs, ty: substd_ty }
2649 /// Controls whether the arguments are tupled. This is used for the call
2652 /// Tupling means that all call-side arguments are packed into a tuple and
2653 /// passed as a single parameter. For example, if tupling is enabled, this
2656 /// fn f(x: (isize, isize))
2658 /// Can be called as:
2665 #[derive(Clone, Eq, PartialEq)]
2666 enum TupleArgumentsFlag {
2671 /// Unifies the return type with the expected type early, for more coercions
2672 /// and forward type information on the argument expressions.
2673 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2675 expected_ret: Expectation<'tcx>,
2676 formal_ret: ty::FnOutput<'tcx>,
2677 formal_args: &[Ty<'tcx>])
2679 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2680 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2681 fcx.infcx().commit_regions_if_ok(|| {
2682 // Attempt to apply a subtyping relationship between the formal
2683 // return type (likely containing type variables if the function
2684 // is polymorphic) and the expected return type.
2685 // No argument expectations are produced if unification fails.
2686 let origin = infer::Misc(call_span);
2687 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2688 // FIXME(#15760) can't use try! here, FromError doesn't default
2689 // to identity so the resulting type is not constrained.
2690 if let Err(e) = ures {
2694 // Record all the argument types, with the substitutions
2695 // produced from the above subtyping unification.
2696 Ok(formal_args.iter().map(|ty| {
2697 fcx.infcx().resolve_type_vars_if_possible(ty)
2703 }).unwrap_or(vec![]);
2704 debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
2705 formal_args, formal_ret,
2706 expected_args, expected_ret);
2711 /// If an expression has any sub-expressions that result in a type error,
2712 /// inspecting that expression's type with `ty.references_error()` will return
2713 /// true. Likewise, if an expression is known to diverge, inspecting its
2714 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2715 /// strict, _|_ can appear in the type of an expression that does not,
2716 /// itself, diverge: for example, fn() -> _|_.)
2717 /// Note that inspecting a type's structure *directly* may expose the fact
2718 /// that there are actually multiple representations for `TyError`, so avoid
2719 /// that when err needs to be handled differently.
2720 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2721 expr: &'tcx ast::Expr,
2722 expected: Expectation<'tcx>,
2723 lvalue_pref: LvaluePreference,
2727 debug!(">> typechecking: expr={:?} expected={:?}",
2730 // Checks a method call.
2731 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2732 expr: &'tcx ast::Expr,
2733 method_name: ast::SpannedIdent,
2734 args: &'tcx [P<ast::Expr>],
2736 expected: Expectation<'tcx>,
2737 lvalue_pref: LvaluePreference) {
2738 let rcvr = &*args[0];
2739 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2741 // no need to check for bot/err -- callee does that
2742 let expr_t = structurally_resolved_type(fcx,
2744 fcx.expr_ty(&*rcvr));
2746 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2747 let fn_ty = match method::lookup(fcx,
2749 method_name.node.name,
2755 let method_ty = method.ty;
2756 let method_call = MethodCall::expr(expr.id);
2757 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2761 method::report_error(fcx, method_name.span, expr_t,
2762 method_name.node.name, Some(rcvr), error);
2763 fcx.write_error(expr.id);
2768 // Call the generic checker.
2769 let ret_ty = check_method_argument_types(fcx,
2777 write_call(fcx, expr, ret_ty);
2780 // A generic function for checking the then and else in an if
2782 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2783 cond_expr: &'tcx ast::Expr,
2784 then_blk: &'tcx ast::Block,
2785 opt_else_expr: Option<&'tcx ast::Expr>,
2788 expected: Expectation<'tcx>) {
2789 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2791 let expected = expected.adjust_for_branches(fcx);
2792 check_block_with_expected(fcx, then_blk, expected);
2793 let then_ty = fcx.node_ty(then_blk.id);
2795 let branches_ty = match opt_else_expr {
2796 Some(ref else_expr) => {
2797 check_expr_with_expectation(fcx, &**else_expr, expected);
2798 let else_ty = fcx.expr_ty(&**else_expr);
2799 infer::common_supertype(fcx.infcx(),
2800 infer::IfExpression(sp),
2806 infer::common_supertype(fcx.infcx(),
2807 infer::IfExpressionWithNoElse(sp),
2814 let cond_ty = fcx.expr_ty(cond_expr);
2815 let if_ty = if cond_ty.references_error() {
2821 fcx.write_ty(id, if_ty);
2824 // Check field access expressions
2825 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2826 expr: &'tcx ast::Expr,
2827 lvalue_pref: LvaluePreference,
2828 base: &'tcx ast::Expr,
2829 field: &ast::SpannedIdent) {
2830 let tcx = fcx.ccx.tcx;
2831 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2832 let expr_t = structurally_resolved_type(fcx, expr.span,
2834 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2835 let (_, autoderefs, field_ty) = autoderef(fcx,
2839 UnresolvedTypeAction::Error,
2843 ty::TyStruct(base_id, substs) => {
2844 debug!("struct named {:?}", base_t);
2845 let fields = tcx.lookup_struct_fields(base_id);
2846 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
2847 field.node.name, &(*substs))
2854 fcx.write_ty(expr.id, field_ty);
2855 fcx.write_autoderef_adjustment(base.id, autoderefs);
2861 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2862 fcx.type_error_message(
2865 format!("attempted to take value of method `{}` on type \
2866 `{}`", token::get_ident(field.node), actual)
2870 tcx.sess.fileline_help(field.span,
2871 "maybe a `()` to call it is missing? \
2872 If not, try an anonymous function");
2874 fcx.type_error_message(
2877 format!("attempted access of field `{}` on \
2878 type `{}`, but no field with that \
2880 token::get_ident(field.node),
2884 if let ty::TyStruct(did, _) = expr_t.sty {
2885 suggest_field_names(did, field, tcx, vec![]);
2889 fcx.write_error(expr.id);
2892 // displays hints about the closest matches in field names
2893 fn suggest_field_names<'tcx>(id : DefId,
2894 field : &ast::SpannedIdent,
2895 tcx : &ty::ctxt<'tcx>,
2897 let ident = token::get_ident(field.node);
2899 // only find fits with at least one matching letter
2900 let mut best_dist = name.len();
2901 let fields = tcx.lookup_struct_fields(id);
2902 let mut best = None;
2903 for elem in &fields {
2904 let n = elem.name.as_str();
2905 // ignore already set fields
2906 if skip.iter().any(|&x| x == n) {
2909 // ignore private fields from non-local crates
2910 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2913 let dist = lev_distance(n, name);
2914 if dist < best_dist {
2919 if let Some(n) = best {
2920 tcx.sess.span_help(field.span,
2921 &format!("did you mean `{}`?", n));
2925 // Check tuple index expressions
2926 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2927 expr: &'tcx ast::Expr,
2928 lvalue_pref: LvaluePreference,
2929 base: &'tcx ast::Expr,
2930 idx: codemap::Spanned<usize>) {
2931 let tcx = fcx.ccx.tcx;
2932 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2933 let expr_t = structurally_resolved_type(fcx, expr.span,
2935 let mut tuple_like = false;
2936 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2937 let (_, autoderefs, field_ty) = autoderef(fcx,
2941 UnresolvedTypeAction::Error,
2945 ty::TyStruct(base_id, substs) => {
2946 tuple_like = tcx.is_tuple_struct(base_id);
2948 debug!("tuple struct named {:?}", base_t);
2949 let fields = tcx.lookup_struct_fields(base_id);
2950 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
2951 idx.node, &(*substs))
2956 ty::TyTuple(ref v) => {
2958 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2965 fcx.write_ty(expr.id, field_ty);
2966 fcx.write_autoderef_adjustment(base.id, autoderefs);
2971 fcx.type_error_message(
2975 format!("attempted out-of-bounds tuple index `{}` on \
2980 format!("attempted tuple index `{}` on type `{}`, but the \
2981 type was not a tuple or tuple struct",
2988 fcx.write_error(expr.id);
2991 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2992 struct_ty: Ty<'tcx>,
2994 class_id: ast::DefId,
2995 node_id: ast::NodeId,
2996 substitutions: &'tcx subst::Substs<'tcx>,
2997 field_types: &[ty::FieldTy],
2998 ast_fields: &'tcx [ast::Field],
2999 check_completeness: bool,
3000 enum_id_opt: Option<ast::DefId>) {
3001 let tcx = fcx.ccx.tcx;
3003 let mut class_field_map = FnvHashMap();
3004 let mut fields_found = 0;
3005 for field in field_types {
3006 class_field_map.insert(field.name, (field.id, false));
3009 let mut error_happened = false;
3011 // Typecheck each field.
3012 for field in ast_fields {
3013 let mut expected_field_type = tcx.types.err;
3015 let pair = class_field_map.get(&field.ident.node.name).cloned();
3018 fcx.type_error_message(
3020 |actual| match enum_id_opt {
3022 let variant_type = tcx.enum_variant_with_id(enum_id,
3024 format!("struct variant `{}::{}` has no field named `{}`",
3025 actual, variant_type.name.as_str(),
3026 token::get_ident(field.ident.node))
3029 format!("structure `{}` has no field named `{}`",
3031 token::get_ident(field.ident.node))
3036 // prevent all specified fields from being suggested
3037 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
3038 let actual_id = match enum_id_opt {
3039 Some(_) => class_id,
3040 None => struct_ty.ty_to_def_id().unwrap()
3042 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3043 error_happened = true;
3045 Some((_, true)) => {
3046 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3047 "field `{}` specified more than once",
3048 token::get_ident(field.ident.node));
3049 error_happened = true;
3051 Some((field_id, false)) => {
3052 expected_field_type =
3053 tcx.lookup_field_type(class_id, field_id, substitutions);
3054 expected_field_type =
3055 fcx.normalize_associated_types_in(
3056 field.span, &expected_field_type);
3057 class_field_map.insert(
3058 field.ident.node.name, (field_id, true));
3063 // Make sure to give a type to the field even if there's
3064 // an error, so we can continue typechecking
3065 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3069 fcx.write_error(node_id);
3072 if check_completeness && !error_happened {
3073 // Make sure the programmer specified all the fields.
3074 assert!(fields_found <= field_types.len());
3075 if fields_found < field_types.len() {
3076 let mut missing_fields = Vec::new();
3077 for class_field in field_types {
3078 let name = class_field.name;
3079 let (_, seen) = *class_field_map.get(&name).unwrap();
3081 missing_fields.push(
3082 format!("`{}`", &token::get_name(name)))
3086 span_err!(tcx.sess, span, E0063,
3087 "missing field{}: {}",
3088 if missing_fields.len() == 1 {""} else {"s"},
3089 missing_fields.join(", "));
3093 if !error_happened {
3094 fcx.write_ty(node_id, fcx.ccx.tcx.mk_struct(class_id, substitutions));
3098 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3100 span: codemap::Span,
3101 class_id: ast::DefId,
3102 fields: &'tcx [ast::Field],
3103 base_expr: Option<&'tcx ast::Expr>) {
3104 let tcx = fcx.ccx.tcx;
3106 // Generate the struct type.
3108 ty: mut struct_type,
3109 substs: struct_substs
3110 } = fcx.instantiate_type(span, class_id);
3112 // Look up and check the fields.
3113 let class_fields = tcx.lookup_struct_fields(class_id);
3114 check_struct_or_variant_fields(fcx,
3119 fcx.ccx.tcx.mk_substs(struct_substs),
3122 base_expr.is_none(),
3124 if fcx.node_ty(id).references_error() {
3125 struct_type = tcx.types.err;
3128 // Check the base expression if necessary.
3131 Some(base_expr) => {
3132 check_expr_has_type(fcx, &*base_expr, struct_type);
3136 // Write in the resulting type.
3137 fcx.write_ty(id, struct_type);
3140 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3142 span: codemap::Span,
3143 enum_id: ast::DefId,
3144 variant_id: ast::DefId,
3145 fields: &'tcx [ast::Field]) {
3146 let tcx = fcx.ccx.tcx;
3148 // Look up the number of type parameters and the raw type, and
3149 // determine whether the enum is region-parameterized.
3152 substs: substitutions
3153 } = fcx.instantiate_type(span, enum_id);
3155 // Look up and check the enum variant fields.
3156 let variant_fields = tcx.lookup_struct_fields(variant_id);
3157 check_struct_or_variant_fields(fcx,
3162 fcx.ccx.tcx.mk_substs(substitutions),
3163 &variant_fields[..],
3167 fcx.write_ty(id, enum_type);
3170 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3172 fields: &'tcx [ast::Field],
3173 base_expr: &'tcx Option<P<ast::Expr>>) {
3174 // Make sure to still write the types
3175 // otherwise we might ICE
3176 fcx.write_error(id);
3177 for field in fields {
3178 check_expr(fcx, &*field.expr);
3181 Some(ref base) => check_expr(fcx, &**base),
3186 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3188 let tcx = fcx.ccx.tcx;
3191 ast::ExprBox(ref opt_place, ref subexpr) => {
3192 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3193 check_expr(fcx, &**subexpr);
3195 let mut checked = false;
3196 opt_place.as_ref().map(|place| match place.node {
3197 ast::ExprPath(None, ref path) => {
3198 // FIXME(pcwalton): For now we hardcode the only permissible
3199 // place: the exchange heap.
3200 let definition = lookup_full_def(tcx, path.span, place.id);
3201 let def_id = definition.def_id();
3202 let referent_ty = fcx.expr_ty(&**subexpr);
3203 if tcx.lang_items.exchange_heap() == Some(def_id) {
3204 fcx.write_ty(id, tcx.mk_box(referent_ty));
3212 span_err!(tcx.sess, expr.span, E0066,
3213 "only the exchange heap is currently supported");
3214 fcx.write_ty(id, tcx.types.err);
3218 ast::ExprLit(ref lit) => {
3219 let typ = check_lit(fcx, &**lit, expected);
3220 fcx.write_ty(id, typ);
3222 ast::ExprBinary(op, ref lhs, ref rhs) => {
3223 op::check_binop(fcx, expr, op, lhs, rhs);
3225 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3226 op::check_binop_assign(fcx, expr, op, lhs, rhs);
3228 ast::ExprUnary(unop, ref oprnd) => {
3229 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3231 ast::UnUniq => match ty.sty {
3233 Expectation::rvalue_hint(ty)
3239 ast::UnNot | ast::UnNeg => {
3247 let lvalue_pref = match unop {
3248 ast::UnDeref => lvalue_pref,
3251 check_expr_with_expectation_and_lvalue_pref(
3252 fcx, &**oprnd, expected_inner, lvalue_pref);
3253 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3255 if !oprnd_t.references_error() {
3258 oprnd_t = tcx.mk_box(oprnd_t);
3261 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3262 oprnd_t = match oprnd_t.builtin_deref(true) {
3264 None => match try_overloaded_deref(fcx, expr.span,
3265 Some(MethodCall::expr(expr.id)),
3266 Some(&**oprnd), oprnd_t, lvalue_pref) {
3269 fcx.type_error_message(expr.span, |actual| {
3270 format!("type `{}` cannot be \
3271 dereferenced", actual)
3279 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3281 if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
3282 oprnd_t = op::check_user_unop(fcx, "!", "not",
3283 tcx.lang_items.not_trait(),
3284 expr, &**oprnd, oprnd_t, unop);
3288 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3290 if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
3291 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3292 tcx.lang_items.neg_trait(),
3293 expr, &**oprnd, oprnd_t, unop);
3298 fcx.write_ty(id, oprnd_t);
3300 ast::ExprAddrOf(mutbl, ref oprnd) => {
3301 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3303 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
3304 if fcx.tcx().expr_is_lval(&**oprnd) {
3305 // Lvalues may legitimately have unsized types.
3306 // For example, dereferences of a fat pointer and
3307 // the last field of a struct can be unsized.
3308 ExpectHasType(mt.ty)
3310 Expectation::rvalue_hint(mt.ty)
3316 let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
3317 check_expr_with_expectation_and_lvalue_pref(fcx,
3322 let tm = ty::TypeAndMut { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3323 let oprnd_t = if tm.ty.references_error() {
3326 // Note: at this point, we cannot say what the best lifetime
3327 // is to use for resulting pointer. We want to use the
3328 // shortest lifetime possible so as to avoid spurious borrowck
3329 // errors. Moreover, the longest lifetime will depend on the
3330 // precise details of the value whose address is being taken
3331 // (and how long it is valid), which we don't know yet until type
3332 // inference is complete.
3334 // Therefore, here we simply generate a region variable. The
3335 // region inferencer will then select the ultimate value.
3336 // Finally, borrowck is charged with guaranteeing that the
3337 // value whose address was taken can actually be made to live
3338 // as long as it needs to live.
3339 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3340 tcx.mk_ref(tcx.mk_region(region), tm)
3342 fcx.write_ty(id, oprnd_t);
3344 ast::ExprPath(ref maybe_qself, ref path) => {
3345 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3346 fcx.to_ty(&qself.ty)
3349 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3351 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3352 // Create some fake resolution that can't possibly be a type.
3353 def::PathResolution {
3354 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3355 last_private: LastMod(AllPublic),
3356 depth: path.segments.len()
3359 tcx.sess.span_bug(expr.span,
3360 &format!("unbound path {:?}", expr))
3363 if let Some((opt_ty, segments, def)) =
3364 resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
3365 expr.span, expr.id) {
3366 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
3369 instantiate_path(fcx,
3379 // We always require that the type provided as the value for
3380 // a type parameter outlives the moment of instantiation.
3381 constrain_path_type_parameters(fcx, expr);
3383 ast::ExprInlineAsm(ref ia) => {
3384 for &(_, ref input) in &ia.inputs {
3385 check_expr(fcx, &**input);
3387 for &(_, ref out, _) in &ia.outputs {
3388 check_expr(fcx, &**out);
3392 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3393 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3394 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3395 ast::ExprRet(ref expr_opt) => {
3397 ty::FnConverging(result_type) => {
3400 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3401 result_type, fcx.tcx().mk_nil()) {
3402 span_err!(tcx.sess, expr.span, E0069,
3403 "`return;` in a function whose return type is \
3407 check_expr_coercable_to_type(fcx, &**e, result_type);
3411 ty::FnDiverging => {
3412 if let Some(ref e) = *expr_opt {
3413 check_expr(fcx, &**e);
3415 span_err!(tcx.sess, expr.span, E0166,
3416 "`return` in a function declared as diverging");
3419 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3421 ast::ExprParen(ref a) => {
3422 check_expr_with_expectation_and_lvalue_pref(fcx,
3426 fcx.write_ty(id, fcx.expr_ty(&**a));
3428 ast::ExprAssign(ref lhs, ref rhs) => {
3429 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3431 let tcx = fcx.tcx();
3432 if !tcx.expr_is_lval(&**lhs) {
3433 span_err!(tcx.sess, expr.span, E0070,
3434 "illegal left-hand side expression");
3437 let lhs_ty = fcx.expr_ty(&**lhs);
3438 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3439 let rhs_ty = fcx.expr_ty(&**rhs);
3441 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3443 if lhs_ty.references_error() || rhs_ty.references_error() {
3444 fcx.write_error(id);
3449 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3450 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3451 id, expr.span, expected);
3453 ast::ExprIfLet(..) => {
3454 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3456 ast::ExprWhile(ref cond, ref body, _) => {
3457 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3458 check_block_no_value(fcx, &**body);
3459 let cond_ty = fcx.expr_ty(&**cond);
3460 let body_ty = fcx.node_ty(body.id);
3461 if cond_ty.references_error() || body_ty.references_error() {
3462 fcx.write_error(id);
3468 ast::ExprWhileLet(..) => {
3469 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3471 ast::ExprForLoop(..) => {
3472 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3474 ast::ExprLoop(ref body, _) => {
3475 check_block_no_value(fcx, &**body);
3476 if !may_break(tcx, expr.id, &**body) {
3477 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3482 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3483 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3485 ast::ExprClosure(capture, ref decl, ref body) => {
3486 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3488 ast::ExprBlock(ref b) => {
3489 check_block_with_expected(fcx, &**b, expected);
3490 fcx.write_ty(id, fcx.node_ty(b.id));
3492 ast::ExprCall(ref callee, ref args) => {
3493 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3495 ast::ExprMethodCall(ident, ref tps, ref args) => {
3496 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3497 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3498 let args_err = arg_tys.fold(false,
3500 rest_err || a.references_error()});
3502 fcx.write_error(id);
3505 ast::ExprCast(ref e, ref t) => {
3506 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3507 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3510 // Find the type of `e`. Supply hints based on the type we are casting to,
3512 let t_cast = fcx.to_ty(t);
3513 let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
3514 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
3515 let t_expr = fcx.expr_ty(e);
3517 // Eagerly check for some obvious errors.
3518 if t_expr.references_error() {
3519 fcx.write_error(id);
3520 } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
3521 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
3523 // Write a type for the whole expression, assuming everything is going
3525 fcx.write_ty(id, t_cast);
3527 // Defer other checks until we're done type checking.
3528 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3529 let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
3530 deferred_cast_checks.push(cast_check);
3533 ast::ExprVec(ref args) => {
3534 let uty = expected.to_option(fcx).and_then(|uty| {
3536 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3541 let typ = match uty {
3544 check_expr_coercable_to_type(fcx, &**e, uty);
3549 let t: Ty = fcx.infcx().next_ty_var();
3551 check_expr_has_type(fcx, &**e, t);
3556 let typ = tcx.mk_array(typ, args.len());
3557 fcx.write_ty(id, typ);
3559 ast::ExprRepeat(ref element, ref count_expr) => {
3560 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3561 let count = fcx.tcx().eval_repeat_count(&**count_expr);
3563 let uty = match expected {
3564 ExpectHasType(uty) => {
3566 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3573 let (element_ty, t) = match uty {
3575 check_expr_coercable_to_type(fcx, &**element, uty);
3579 let t: Ty = fcx.infcx().next_ty_var();
3580 check_expr_has_type(fcx, &**element, t);
3581 (fcx.expr_ty(&**element), t)
3586 // For [foo, ..n] where n > 1, `foo` must have
3588 fcx.require_type_meets(
3595 if element_ty.references_error() {
3596 fcx.write_error(id);
3598 let t = tcx.mk_array(t, count);
3599 fcx.write_ty(id, t);
3602 ast::ExprTup(ref elts) => {
3603 let flds = expected.only_has_type(fcx).and_then(|ty| {
3605 ty::TyTuple(ref flds) => Some(&flds[..]),
3609 let mut err_field = false;
3611 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3612 let t = match flds {
3613 Some(ref fs) if i < fs.len() => {
3615 check_expr_coercable_to_type(fcx, &**e, ety);
3619 check_expr_with_expectation(fcx, &**e, NoExpectation);
3623 err_field = err_field || t.references_error();
3627 fcx.write_error(id);
3629 let typ = tcx.mk_tup(elt_ts);
3630 fcx.write_ty(id, typ);
3633 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3634 // Resolve the path.
3635 let def = lookup_full_def(tcx, path.span, id);
3636 let struct_id = match def {
3637 def::DefVariant(enum_id, variant_id, true) => {
3638 if let &Some(ref base_expr) = base_expr {
3639 span_err!(tcx.sess, base_expr.span, E0436,
3640 "functional record update syntax requires a struct");
3641 fcx.write_error(base_expr.id);
3643 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3644 variant_id, &fields[..]);
3647 def::DefTrait(def_id) => {
3648 span_err!(tcx.sess, path.span, E0159,
3649 "use of trait `{}` as a struct constructor",
3650 pprust::path_to_string(path));
3651 check_struct_fields_on_error(fcx,
3658 // Verify that this was actually a struct.
3659 let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
3661 ty::TyStruct(struct_did, _) => {
3662 check_struct_constructor(fcx,
3667 base_expr.as_ref().map(|e| &**e));
3670 span_err!(tcx.sess, path.span, E0071,
3671 "`{}` does not name a structure",
3672 pprust::path_to_string(path));
3673 check_struct_fields_on_error(fcx,
3684 // Turn the path into a type and verify that that type unifies with
3685 // the resulting structure type. This is needed to handle type
3686 // parameters correctly.
3687 let actual_structure_type = fcx.expr_ty(&*expr);
3688 if !actual_structure_type.references_error() {
3689 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3690 match fcx.mk_subty(false,
3691 infer::Misc(path.span),
3692 actual_structure_type,
3693 type_and_substs.ty) {
3695 Err(type_error) => {
3696 span_err!(fcx.tcx().sess, path.span, E0235,
3697 "structure constructor specifies a \
3698 structure of type `{}`, but this \
3699 structure has type `{}`: {}",
3701 .ty_to_string(type_and_substs.ty),
3704 actual_structure_type),
3706 tcx.note_and_explain_type_err(&type_error, path.span);
3711 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3713 ast::ExprField(ref base, ref field) => {
3714 check_field(fcx, expr, lvalue_pref, &**base, field);
3716 ast::ExprTupField(ref base, idx) => {
3717 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3719 ast::ExprIndex(ref base, ref idx) => {
3720 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3721 check_expr(fcx, &**idx);
3723 let base_t = fcx.expr_ty(&**base);
3724 let idx_t = fcx.expr_ty(&**idx);
3726 if base_t.references_error() {
3727 fcx.write_ty(id, base_t);
3728 } else if idx_t.references_error() {
3729 fcx.write_ty(id, idx_t);
3731 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3732 match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3733 Some((index_ty, element_ty)) => {
3734 let idx_expr_ty = fcx.expr_ty(idx);
3735 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3736 fcx.write_ty(id, element_ty);
3739 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3740 fcx.type_error_message(
3743 format!("cannot index a value of type `{}`",
3748 fcx.write_ty(id, fcx.tcx().types.err);
3753 ast::ExprRange(ref start, ref end) => {
3754 let t_start = start.as_ref().map(|e| {
3755 check_expr(fcx, &**e);
3758 let t_end = end.as_ref().map(|e| {
3759 check_expr(fcx, &**e);
3763 let idx_type = match (t_start, t_end) {
3764 (Some(ty), None) | (None, Some(ty)) => {
3767 (Some(t_start), Some(t_end)) if (t_start.references_error() ||
3768 t_end.references_error()) => {
3769 Some(fcx.tcx().types.err)
3771 (Some(t_start), Some(t_end)) => {
3772 Some(infer::common_supertype(fcx.infcx(),
3773 infer::RangeExpression(expr.span),
3781 // Note that we don't check the type of start/end satisfy any
3782 // bounds because right now the range structs do not have any. If we add
3783 // some bounds, then we'll need to check `t_start` against them here.
3785 let range_type = match idx_type {
3786 Some(idx_type) if idx_type.references_error() => {
3790 // Find the did from the appropriate lang item.
3791 let did = match (start, end) {
3792 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3793 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3794 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3796 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3800 if let Some(did) = did {
3801 let predicates = tcx.lookup_predicates(did);
3802 let substs = Substs::new_type(vec![idx_type], vec![]);
3803 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
3804 fcx.add_obligations_for_parameters(
3805 traits::ObligationCause::new(expr.span,
3807 traits::ItemObligation(did)),
3810 tcx.mk_struct(did, tcx.mk_substs(substs))
3812 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
3817 // Neither start nor end => RangeFull
3818 if let Some(did) = tcx.lang_items.range_full_struct() {
3819 let substs = Substs::new_type(vec![], vec![]);
3820 tcx.mk_struct(did, tcx.mk_substs(substs))
3822 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
3828 fcx.write_ty(id, range_type);
3833 debug!("type of expr({}) {} is...", expr.id,
3834 syntax::print::pprust::expr_to_string(expr));
3835 debug!("... {:?}, expected is {:?}",
3842 pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
3843 path_res: def::PathResolution,
3844 opt_self_ty: Option<Ty<'tcx>>,
3845 path: &'a ast::Path,
3847 node_id: ast::NodeId)
3848 -> Option<(Option<Ty<'tcx>>,
3849 &'a [ast::PathSegment],
3853 // Associated constants can't depend on generic types.
3854 fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3858 node_id: ast::NodeId) -> bool {
3860 def::DefAssociatedConst(..) => {
3861 if ty.has_param_types() || ty.has_self_ty() {
3862 span_err!(fcx.sess(), span, E0329,
3863 "Associated consts cannot depend \
3864 on type parameters or Self.");
3865 fcx.write_error(node_id);
3874 // If fully resolved already, we don't have to do anything.
3875 if path_res.depth == 0 {
3876 if let Some(ty) = opt_self_ty {
3877 if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
3882 Some((opt_self_ty, &path.segments, path_res.base_def))
3884 let mut def = path_res.base_def;
3885 let ty_segments = path.segments.split_last().unwrap().1;
3886 let base_ty_end = path.segments.len() - path_res.depth;
3887 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
3888 PathParamMode::Optional,
3891 &ty_segments[..base_ty_end],
3892 &ty_segments[base_ty_end..]);
3893 let item_segment = path.segments.last().unwrap();
3894 let item_name = item_segment.identifier.name;
3895 match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
3897 if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
3900 // Write back the new resolution.
3901 fcx.ccx.tcx.def_map.borrow_mut()
3902 .insert(node_id, def::PathResolution {
3904 last_private: path_res.last_private.or(lp),
3907 Some((Some(ty), slice::ref_slice(item_segment), def))
3910 method::report_error(fcx, span, ty,
3911 item_name, None, error);
3912 fcx.write_error(node_id);
3919 fn constrain_path_type_parameters(fcx: &FnCtxt,
3922 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3923 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3927 impl<'tcx> Expectation<'tcx> {
3928 /// Provide an expectation for an rvalue expression given an *optional*
3929 /// hint, which is not required for type safety (the resulting type might
3930 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3931 /// is useful in determining the concrete type.
3933 /// The primary use case is where the expected type is a fat pointer,
3934 /// like `&[isize]`. For example, consider the following statement:
3936 /// let x: &[isize] = &[1, 2, 3];
3938 /// In this case, the expected type for the `&[1, 2, 3]` expression is
3939 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3940 /// expectation `ExpectHasType([isize])`, that would be too strong --
3941 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3942 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3943 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3944 /// which still is useful, because it informs integer literals and the like.
3945 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3946 /// for examples of where this comes up,.
3947 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
3949 ty::TySlice(_) | ty::TyTrait(..) => {
3950 ExpectRvalueLikeUnsized(ty)
3952 _ => ExpectHasType(ty)
3956 // Resolves `expected` by a single level if it is a variable. If
3957 // there is no expected type or resolution is not possible (e.g.,
3958 // no constraints yet present), just returns `None`.
3959 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3964 ExpectCastableToType(t) => {
3965 ExpectCastableToType(
3966 fcx.infcx().resolve_type_vars_if_possible(&t))
3968 ExpectHasType(t) => {
3970 fcx.infcx().resolve_type_vars_if_possible(&t))
3972 ExpectRvalueLikeUnsized(t) => {
3973 ExpectRvalueLikeUnsized(
3974 fcx.infcx().resolve_type_vars_if_possible(&t))
3979 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3980 match self.resolve(fcx) {
3981 NoExpectation => None,
3982 ExpectCastableToType(ty) |
3984 ExpectRvalueLikeUnsized(ty) => Some(ty),
3988 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3989 match self.resolve(fcx) {
3990 ExpectHasType(ty) => Some(ty),
3996 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3997 local: &'tcx ast::Local,
3998 init: &'tcx ast::Expr)
4000 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
4002 let local_ty = fcx.local_ty(init.span, local.id);
4003 if let Some(m) = ref_bindings {
4004 // Somewhat subtle: if we have a `ref` binding in the pattern,
4005 // we want to avoid introducing coercions for the RHS. This is
4006 // both because it helps preserve sanity and, in the case of
4007 // ref mut, for soundness (issue #23116). In particular, in
4008 // the latter case, we need to be clear that the type of the
4009 // referent for the reference that results is *equal to* the
4010 // type of the lvalue it is referencing, and not some
4011 // supertype thereof.
4012 check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
4013 let init_ty = fcx.expr_ty(init);
4014 demand::eqtype(fcx, init.span, init_ty, local_ty);
4016 check_expr_coercable_to_type(fcx, init, local_ty)
4020 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
4021 let tcx = fcx.ccx.tcx;
4023 let t = fcx.local_ty(local.span, local.id);
4024 fcx.write_ty(local.id, t);
4026 if let Some(ref init) = local.init {
4027 check_decl_initializer(fcx, local, &**init);
4028 let init_ty = fcx.expr_ty(&**init);
4029 if init_ty.references_error() {
4030 fcx.write_ty(local.id, init_ty);
4034 let pcx = pat_ctxt {
4036 map: pat_id_map(&tcx.def_map, &*local.pat),
4038 _match::check_pat(&pcx, &*local.pat, t);
4039 let pat_ty = fcx.node_ty(local.pat.id);
4040 if pat_ty.references_error() {
4041 fcx.write_ty(local.id, pat_ty);
4045 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4047 let mut saw_bot = false;
4048 let mut saw_err = false;
4050 ast::StmtDecl(ref decl, id) => {
4053 ast::DeclLocal(ref l) => {
4054 check_decl_local(fcx, &**l);
4055 let l_t = fcx.node_ty(l.id);
4056 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4057 saw_err = saw_err || l_t.references_error();
4059 ast::DeclItem(_) => {/* ignore for now */ }
4062 ast::StmtExpr(ref expr, id) => {
4064 // Check with expected type of ()
4065 check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
4066 let expr_ty = fcx.expr_ty(&**expr);
4067 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4068 saw_err = saw_err || expr_ty.references_error();
4070 ast::StmtSemi(ref expr, id) => {
4072 check_expr(fcx, &**expr);
4073 let expr_ty = fcx.expr_ty(&**expr);
4074 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4075 saw_err |= expr_ty.references_error();
4077 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4080 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4083 fcx.write_error(node_id);
4086 fcx.write_nil(node_id)
4090 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4091 check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
4092 let blkty = fcx.node_ty(blk.id);
4093 if blkty.references_error() {
4094 fcx.write_error(blk.id);
4096 let nilty = fcx.tcx().mk_nil();
4097 demand::suptype(fcx, blk.span, nilty, blkty);
4101 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4102 blk: &'tcx ast::Block,
4103 expected: Expectation<'tcx>) {
4105 let mut fcx_ps = fcx.ps.borrow_mut();
4106 let unsafety_state = fcx_ps.recurse(blk);
4107 replace(&mut *fcx_ps, unsafety_state)
4110 let mut warned = false;
4111 let mut any_diverges = false;
4112 let mut any_err = false;
4113 for s in &blk.stmts {
4114 check_stmt(fcx, &**s);
4115 let s_id = ast_util::stmt_id(&**s);
4116 let s_ty = fcx.node_ty(s_id);
4117 if any_diverges && !warned && match s.node {
4118 ast::StmtDecl(ref decl, _) => {
4120 ast::DeclLocal(_) => true,
4124 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4130 .add_lint(lint::builtin::UNREACHABLE_CODE,
4133 "unreachable statement".to_string());
4136 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4137 any_err = any_err || s_ty.references_error();
4140 None => if any_err {
4141 fcx.write_error(blk.id);
4142 } else if any_diverges {
4143 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4145 fcx.write_nil(blk.id);
4148 if any_diverges && !warned {
4152 .add_lint(lint::builtin::UNREACHABLE_CODE,
4155 "unreachable expression".to_string());
4157 let ety = match expected {
4158 ExpectHasType(ety) => {
4159 check_expr_coercable_to_type(fcx, &**e, ety);
4163 check_expr_with_expectation(fcx, &**e, expected);
4169 fcx.write_error(blk.id);
4170 } else if any_diverges {
4171 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4173 fcx.write_ty(blk.id, ety);
4178 *fcx.ps.borrow_mut() = prev;
4181 /// Checks a constant appearing in a type. At the moment this is just the
4182 /// length expression in a fixed-length vector, but someday it might be
4183 /// extended to type-level numeric literals.
4184 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4185 expr: &'tcx ast::Expr,
4186 expected_type: Ty<'tcx>) {
4187 let tables = RefCell::new(ty::Tables::empty());
4188 let inh = static_inherited_fields(ccx, &tables);
4189 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4190 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4193 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4197 let tables = RefCell::new(ty::Tables::empty());
4198 let inh = static_inherited_fields(ccx, &tables);
4199 let rty = ccx.tcx.node_id_to_type(id);
4200 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4201 let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
4202 check_const_with_ty(&fcx, sp, e, declty);
4205 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4209 // Gather locals in statics (because of block expressions).
4210 // This is technically unnecessary because locals in static items are forbidden,
4211 // but prevents type checking from blowing up before const checking can properly
4213 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4215 check_expr_with_hint(fcx, e, declty);
4216 demand::coerce(fcx, e.span, declty, e);
4217 fcx.select_all_obligations_or_error();
4219 regionck::regionck_expr(fcx, e);
4220 writeback::resolve_type_vars_in_expr(fcx, e);
4223 /// Checks whether a type can be represented in memory. In particular, it
4224 /// identifies types that contain themselves without indirection through a
4225 /// pointer, which would mean their size is unbounded.
4226 pub fn check_representable(tcx: &ty::ctxt,
4228 item_id: ast::NodeId,
4229 designation: &str) -> bool {
4230 let rty = tcx.node_id_to_type(item_id);
4232 // Check that it is possible to represent this type. This call identifies
4233 // (1) types that contain themselves and (2) types that contain a different
4234 // recursive type. It is only necessary to throw an error on those that
4235 // contain themselves. For case 2, there must be an inner type that will be
4236 // caught by case 1.
4237 match rty.is_representable(tcx, sp) {
4238 ty::SelfRecursive => {
4239 span_err!(tcx.sess, sp, E0072,
4240 "illegal recursive {} type; \
4241 wrap the inner value in a box to make it representable",
4245 ty::Representable | ty::ContainsRecursive => (),
4250 /// Checks whether a type can be constructed at runtime without
4251 /// an existing instance of that type.
4252 pub fn check_instantiable(tcx: &ty::ctxt,
4254 item_id: ast::NodeId) {
4255 let item_ty = tcx.node_id_to_type(item_id);
4256 if !item_ty.is_instantiable(tcx) &&
4257 !tcx.sess.features.borrow().static_recursion {
4258 emit_feature_err(&tcx.sess.parse_sess.span_diagnostic,
4261 "this type cannot be instantiated at runtime \
4262 without an instance of itself");
4266 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4267 let t = tcx.node_id_to_type(id);
4268 if t.needs_subst() {
4269 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4273 ty::TyStruct(did, substs) => {
4274 let fields = tcx.lookup_struct_fields(did);
4275 if fields.is_empty() {
4276 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4279 let e = tcx.lookup_field_type(did, fields[0].id, substs);
4280 if !fields.iter().all(
4281 |f| tcx.lookup_field_type(did, f.id, substs) == e) {
4282 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4285 if !e.is_machine() {
4286 span_err!(tcx.sess, sp, E0077,
4287 "SIMD vector element type should be machine type");
4295 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4297 vs: &'tcx [P<ast::Variant>],
4300 fn disr_in_range(ccx: &CrateCtxt,
4302 disr: ty::Disr) -> bool {
4303 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4305 ast::TyU8 => disr as u8 as Disr == disr,
4306 ast::TyU16 => disr as u16 as Disr == disr,
4307 ast::TyU32 => disr as u32 as Disr == disr,
4308 ast::TyU64 => disr as u64 as Disr == disr,
4309 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4312 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4314 ast::TyI8 => disr as i8 as Disr == disr,
4315 ast::TyI16 => disr as i16 as Disr == disr,
4316 ast::TyI32 => disr as i32 as Disr == disr,
4317 ast::TyI64 => disr as i64 as Disr == disr,
4318 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4322 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4323 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4327 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4328 vs: &'tcx [P<ast::Variant>],
4330 hint: attr::ReprAttr) {
4331 #![allow(trivial_numeric_casts)]
4333 let rty = ccx.tcx.node_id_to_type(id);
4334 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4336 let tables = RefCell::new(ty::Tables::empty());
4337 let inh = static_inherited_fields(ccx, &tables);
4338 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
4340 let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint));
4342 if let Some(ref e) = v.node.disr_expr {
4343 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
4347 let def_id = local_def(id);
4349 // ty::enum_variants guards against discriminant overflows, so
4350 // we need not check for that.
4351 let variants = ccx.tcx.enum_variants(def_id);
4353 for (v, variant) in vs.iter().zip(variants.iter()) {
4354 let current_disr_val = variant.disr_val;
4356 // Check for duplicate discriminant values
4357 match disr_vals.iter().position(|&x| x == current_disr_val) {
4359 span_err!(ccx.tcx.sess, v.span, E0081,
4360 "discriminant value `{}` already exists", disr_vals[i]);
4361 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4362 "conflicting discriminant here")
4366 // Check for unrepresentable discriminant values
4368 attr::ReprAny | attr::ReprExtern => (),
4369 attr::ReprInt(sp, ity) => {
4370 if !disr_in_range(ccx, ity, current_disr_val) {
4371 span_err!(ccx.tcx.sess, v.span, E0082,
4372 "discriminant value outside specified type");
4373 span_note!(ccx.tcx.sess, sp,
4374 "discriminant type specified here");
4377 attr::ReprPacked => {
4378 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4381 disr_vals.push(current_disr_val);
4385 let hint = *ccx.tcx.lookup_repr_hints(ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4386 .get(0).unwrap_or(&attr::ReprAny);
4388 if hint != attr::ReprAny && vs.len() <= 1 {
4390 span_err!(ccx.tcx.sess, sp, E0083,
4391 "unsupported representation for univariant enum");
4393 span_err!(ccx.tcx.sess, sp, E0084,
4394 "unsupported representation for zero-variant enum");
4398 do_check(ccx, vs, id, hint);
4400 check_representable(ccx.tcx, sp, id, "enum");
4401 check_instantiable(ccx.tcx, sp, id);
4404 // Returns the type parameter count and the type for the given definition.
4405 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4408 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4410 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4411 let typ = fcx.local_ty(sp, nid);
4412 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4413 ty::GenericPredicates::empty())
4415 def::DefFn(id, _) | def::DefMethod(id, _) |
4416 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4417 def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
4418 (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
4422 def::DefAssociatedTy(..) |
4424 def::DefTyParam(..) |
4426 def::DefForeignMod(..) |
4428 def::DefRegion(..) |
4430 def::DefSelfTy(..) => {
4431 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4436 // Instantiates the given path, which must refer to an item with the given
4437 // number of type parameters and type.
4438 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4439 segments: &[ast::PathSegment],
4440 type_scheme: TypeScheme<'tcx>,
4441 type_predicates: &ty::GenericPredicates<'tcx>,
4442 opt_self_ty: Option<Ty<'tcx>>,
4445 node_id: ast::NodeId) {
4446 debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
4452 // We need to extract the type parameters supplied by the user in
4453 // the path `path`. Due to the current setup, this is a bit of a
4454 // tricky-process; the problem is that resolve only tells us the
4455 // end-point of the path resolution, and not the intermediate steps.
4456 // Luckily, we can (at least for now) deduce the intermediate steps
4457 // just from the end-point.
4459 // There are basically four cases to consider:
4461 // 1. Reference to a *type*, such as a struct or enum:
4463 // mod a { struct Foo<T> { ... } }
4465 // Because we don't allow types to be declared within one
4466 // another, a path that leads to a type will always look like
4467 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4468 // that only the final segment can have type parameters, and
4469 // they are located in the TypeSpace.
4471 // *Note:* Generally speaking, references to types don't
4472 // actually pass through this function, but rather the
4473 // `ast_ty_to_ty` function in `astconv`. However, in the case
4474 // of struct patterns (and maybe literals) we do invoke
4475 // `instantiate_path` to get the general type of an instance of
4476 // a struct. (In these cases, there are actually no type
4477 // parameters permitted at present, but perhaps we will allow
4478 // them in the future.)
4480 // 1b. Reference to a enum variant or tuple-like struct:
4482 // struct foo<T>(...)
4483 // enum E<T> { foo(...) }
4485 // In these cases, the parameters are declared in the type
4488 // 2. Reference to a *fn item*:
4492 // In this case, the path will again always have the form
4493 // `a::b::foo::<T>` where only the final segment should have
4494 // type parameters. However, in this case, those parameters are
4495 // declared on a value, and hence are in the `FnSpace`.
4497 // 3. Reference to a *method*:
4499 // impl<A> SomeStruct<A> {
4503 // Here we can have a path like
4504 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4505 // may appear in two places. The penultimate segment,
4506 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4507 // final segment, `foo::<B>` contains parameters in fn space.
4509 // 4. Reference to an *associated const*:
4511 // impl<A> AnotherStruct<A> {
4512 // const FOO: B = BAR;
4515 // The path in this case will look like
4516 // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
4517 // only will have parameters in TypeSpace.
4519 // The first step then is to categorize the segments appropriately.
4521 assert!(!segments.is_empty());
4523 let mut ufcs_method = None;
4524 let mut segment_spaces: Vec<_>;
4526 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4527 def::DefSelfTy(..) |
4528 def::DefStruct(..) |
4529 def::DefVariant(..) |
4531 def::DefAssociatedTy(..) |
4533 def::DefPrimTy(..) |
4534 def::DefTyParam(..) => {
4535 // Everything but the final segment should have no
4536 // parameters at all.
4537 segment_spaces = vec![None; segments.len() - 1];
4538 segment_spaces.push(Some(subst::TypeSpace));
4541 // Case 2. Reference to a top-level value.
4544 def::DefStatic(..) => {
4545 segment_spaces = vec![None; segments.len() - 1];
4546 segment_spaces.push(Some(subst::FnSpace));
4549 // Case 3. Reference to a method.
4550 def::DefMethod(_, provenance) => {
4552 def::FromTrait(trait_did) => {
4553 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4555 def::FromImpl(_) => {}
4558 if segments.len() >= 2 {
4559 segment_spaces = vec![None; segments.len() - 2];
4560 segment_spaces.push(Some(subst::TypeSpace));
4561 segment_spaces.push(Some(subst::FnSpace));
4563 // `<T>::method` will end up here, and so can `T::method`.
4564 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4565 segment_spaces = vec![Some(subst::FnSpace)];
4566 ufcs_method = Some((provenance, self_ty));
4570 def::DefAssociatedConst(_, provenance) => {
4572 def::FromTrait(trait_did) => {
4573 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4575 def::FromImpl(_) => {}
4578 if segments.len() >= 2 {
4579 segment_spaces = vec![None; segments.len() - 2];
4580 segment_spaces.push(Some(subst::TypeSpace));
4581 segment_spaces.push(None);
4583 segment_spaces = vec![None];
4587 // Other cases. Various nonsense that really shouldn't show up
4588 // here. If they do, an error will have been reported
4589 // elsewhere. (I hope)
4591 def::DefForeignMod(..) |
4594 def::DefRegion(..) |
4596 def::DefUpvar(..) => {
4597 segment_spaces = vec![None; segments.len()];
4600 assert_eq!(segment_spaces.len(), segments.len());
4602 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4603 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4604 // type parameters are not mandatory.
4605 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
4607 debug!("segment_spaces={:?}", segment_spaces);
4609 // Next, examine the definition, and determine how many type
4610 // parameters we expect from each space.
4611 let type_defs = &type_scheme.generics.types;
4612 let region_defs = &type_scheme.generics.regions;
4614 // Now that we have categorized what space the parameters for each
4615 // segment belong to, let's sort out the parameters that the user
4616 // provided (if any) into their appropriate spaces. We'll also report
4617 // errors if type parameters are provided in an inappropriate place.
4618 let mut substs = Substs::empty();
4619 for (opt_space, segment) in segment_spaces.iter().zip(segments) {
4622 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4623 NO_TPS | NO_REGIONS);
4627 push_explicit_parameters_from_segment_to_substs(fcx,
4637 if let Some(self_ty) = opt_self_ty {
4638 if type_defs.len(subst::SelfSpace) == 1 {
4639 substs.types.push(subst::SelfSpace, self_ty);
4643 // Now we have to compare the types that the user *actually*
4644 // provided against the types that were *expected*. If the user
4645 // did not provide any types, then we want to substitute inference
4646 // variables. If the user provided some types, we may still need
4647 // to add defaults. If the user provided *too many* types, that's
4649 for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
4650 adjust_type_parameters(fcx, span, space, type_defs,
4651 require_type_space, &mut substs);
4652 assert_eq!(substs.types.len(space), type_defs.len(space));
4654 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4655 assert_eq!(substs.regions().len(space), region_defs.len(space));
4658 // The things we are substituting into the type should not contain
4659 // escaping late-bound regions, and nor should the base type scheme.
4660 assert!(!substs.has_regions_escaping_depth(0));
4661 assert!(!type_scheme.has_escaping_regions());
4663 // Add all the obligations that are required, substituting and
4664 // normalized appropriately.
4665 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4666 fcx.add_obligations_for_parameters(
4667 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4670 // Substitute the values for the type parameters into the type of
4671 // the referenced item.
4672 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4675 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4676 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4677 // is inherent, there is no `Self` parameter, instead, the impl needs
4678 // type parameters, which we can infer by unifying the provided `Self`
4679 // with the substituted impl type.
4680 let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
4681 assert_eq!(substs.types.len(subst::TypeSpace),
4682 impl_scheme.generics.types.len(subst::TypeSpace));
4683 assert_eq!(substs.regions().len(subst::TypeSpace),
4684 impl_scheme.generics.regions.len(subst::TypeSpace));
4686 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4687 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4688 fcx.tcx().sess.span_bug(span,
4690 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
4696 fcx.write_ty(node_id, ty_substituted);
4697 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4700 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4701 /// parameters are provided, then reports an error and clears the output vector.
4703 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4704 /// use inference variables. This seems less likely to lead to derived errors.
4706 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4707 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4708 /// here because we can easily use the precise span of the N+1'th parameter.
4709 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4710 fcx: &FnCtxt<'a, 'tcx>,
4711 space: subst::ParamSpace,
4713 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4714 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4715 segment: &ast::PathSegment,
4716 substs: &mut Substs<'tcx>)
4718 match segment.parameters {
4719 ast::AngleBracketedParameters(ref data) => {
4720 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4721 fcx, space, type_defs, region_defs, data, substs);
4724 ast::ParenthesizedParameters(ref data) => {
4725 span_err!(fcx.tcx().sess, span, E0238,
4726 "parenthesized parameters may only be used with a trait");
4727 push_explicit_parenthesized_parameters_from_segment_to_substs(
4728 fcx, space, span, type_defs, data, substs);
4733 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4734 fcx: &FnCtxt<'a, 'tcx>,
4735 space: subst::ParamSpace,
4736 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4737 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4738 data: &ast::AngleBracketedParameterData,
4739 substs: &mut Substs<'tcx>)
4742 let type_count = type_defs.len(space);
4743 assert_eq!(substs.types.len(space), 0);
4744 for (i, typ) in data.types.iter().enumerate() {
4745 let t = fcx.to_ty(&**typ);
4747 substs.types.push(space, t);
4748 } else if i == type_count {
4749 span_err!(fcx.tcx().sess, typ.span, E0087,
4750 "too many type parameters provided: \
4751 expected at most {} parameter{}, \
4752 found {} parameter{}",
4754 if type_count == 1 {""} else {"s"},
4756 if data.types.len() == 1 {""} else {"s"});
4757 substs.types.truncate(space, 0);
4763 if !data.bindings.is_empty() {
4764 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4765 "unexpected binding of associated item in expression path \
4766 (only allowed in type paths)");
4770 let region_count = region_defs.len(space);
4771 assert_eq!(substs.regions().len(space), 0);
4772 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4773 let r = ast_region_to_region(fcx.tcx(), lifetime);
4774 if i < region_count {
4775 substs.mut_regions().push(space, r);
4776 } else if i == region_count {
4777 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4778 "too many lifetime parameters provided: \
4779 expected {} parameter{}, found {} parameter{}",
4781 if region_count == 1 {""} else {"s"},
4782 data.lifetimes.len(),
4783 if data.lifetimes.len() == 1 {""} else {"s"});
4784 substs.mut_regions().truncate(space, 0);
4792 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4793 /// but intended for `Foo(A,B) -> C` form. This expands to
4794 /// roughly the same thing as `Foo<(A,B),C>`. One important
4795 /// difference has to do with the treatment of anonymous
4796 /// regions, which are translated into bound regions (NYI).
4797 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4798 fcx: &FnCtxt<'a, 'tcx>,
4799 space: subst::ParamSpace,
4801 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4802 data: &ast::ParenthesizedParameterData,
4803 substs: &mut Substs<'tcx>)
4805 let type_count = type_defs.len(space);
4807 span_err!(fcx.tcx().sess, span, E0167,
4808 "parenthesized form always supplies 2 type parameters, \
4809 but only {} parameter(s) were expected",
4813 let input_tys: Vec<Ty> =
4814 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4816 let tuple_ty = fcx.tcx().mk_tup(input_tys);
4818 if type_count >= 1 {
4819 substs.types.push(space, tuple_ty);
4822 let output_ty: Option<Ty> =
4823 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4826 output_ty.unwrap_or(fcx.tcx().mk_nil());
4828 if type_count >= 2 {
4829 substs.types.push(space, output_ty);
4833 fn adjust_type_parameters<'a, 'tcx>(
4834 fcx: &FnCtxt<'a, 'tcx>,
4837 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4838 require_type_space: bool,
4839 substs: &mut Substs<'tcx>)
4841 let provided_len = substs.types.len(space);
4842 let desired = defs.get_slice(space);
4843 let required_len = desired.iter()
4844 .take_while(|d| d.default.is_none())
4847 debug!("adjust_type_parameters(space={:?}, \
4856 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4857 assert!(provided_len <= desired.len());
4859 // Nothing specified at all: supply inference variables for
4861 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4862 substs.types.replace(space, Vec::new());
4863 fcx.infcx().type_vars_for_defs(span, space, substs, &desired[..]);
4867 // Too few parameters specified: report an error and use Err
4869 if provided_len < required_len {
4871 if desired.len() != required_len { "at least " } else { "" };
4872 span_err!(fcx.tcx().sess, span, E0089,
4873 "too few type parameters provided: expected {}{} parameter{}, \
4874 found {} parameter{}",
4875 qualifier, required_len,
4876 if required_len == 1 {""} else {"s"},
4878 if provided_len == 1 {""} else {"s"});
4879 substs.types.replace(space, vec![fcx.tcx().types.err; desired.len()]);
4883 // Otherwise, add in any optional parameters that the user
4884 // omitted. The case of *too many* parameters is handled
4886 // push_explicit_parameters_from_segment_to_substs(). Note
4887 // that the *default* type are expressed in terms of all prior
4888 // parameters, so we have to substitute as we go with the
4889 // partial substitution that we have built up.
4890 for i in provided_len..desired.len() {
4891 let default = desired[i].default.unwrap();
4892 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4893 substs.types.push(space, default);
4895 assert_eq!(substs.types.len(space), desired.len());
4897 debug!("Final substs: {:?}", substs);
4900 fn adjust_region_parameters(
4904 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4905 substs: &mut Substs)
4907 let provided_len = substs.mut_regions().len(space);
4908 let desired = defs.get_slice(space);
4910 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4911 assert!(provided_len <= desired.len());
4913 // If nothing was provided, just use inference variables.
4914 if provided_len == 0 {
4915 substs.mut_regions().replace(
4917 fcx.infcx().region_vars_for_defs(span, desired));
4921 // If just the right number were provided, everybody is happy.
4922 if provided_len == desired.len() {
4926 // Otherwise, too few were provided. Report an error and then
4927 // use inference variables.
4928 span_err!(fcx.tcx().sess, span, E0090,
4929 "too few lifetime parameters provided: expected {} parameter{}, \
4930 found {} parameter{}",
4932 if desired.len() == 1 {""} else {"s"},
4934 if provided_len == 1 {""} else {"s"});
4936 substs.mut_regions().replace(
4938 fcx.infcx().region_vars_for_defs(span, desired));
4942 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4946 where F: Fn() -> Ty<'tcx>
4948 let mut ty = fcx.resolve_type_vars_if_possible(ty);
4951 let alternative = f();
4954 if alternative.is_ty_var() || alternative.references_error() {
4955 fcx.type_error_message(sp, |_actual| {
4956 "the type of this value must be known in this context".to_string()
4958 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4959 ty = fcx.tcx().types.err;
4961 demand::suptype(fcx, sp, alternative, ty);
4969 // Resolves `typ` by a single level if `typ` is a type variable. If no
4970 // resolution is possible, then an error is reported.
4971 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4976 structurally_resolve_type_or_else(fcx, sp, ty, || {
4981 // Returns true if b contains a break that can exit from b
4982 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4983 // First: is there an unlabeled break immediately
4985 (loop_query(&*b, |e| {
4987 ast::ExprBreak(None) => true,
4991 // Second: is there a labeled break with label
4992 // <id> nested anywhere inside the loop?
4993 (block_query(b, |e| {
4994 if let ast::ExprBreak(Some(_)) = e.node {
4995 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
5002 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5004 tps: &OwnedSlice<ast::TyParam>,
5006 debug!("check_bounds_are_used(n_tps={}, ty={:?})",
5009 // make a vector of booleans initially false, set to true when used
5010 if tps.is_empty() { return; }
5011 let mut tps_used = vec![false; tps.len()];
5013 for leaf_ty in ty.walk() {
5014 if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
5015 debug!("Found use of ty param num {}", idx);
5016 tps_used[idx as usize] = true;
5020 for (i, b) in tps_used.iter().enumerate() {
5022 span_err!(ccx.tcx.sess, span, E0091,
5023 "type parameter `{}` is unused",
5024 token::get_ident(tps[i].ident));
5029 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
5030 /// and in libcore/intrinsics.rs
5031 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5032 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5033 let name = token::intern(&format!("P{}", n));
5034 ccx.tcx.mk_param(subst::FnSpace, n, name)
5038 let name = token::get_ident(it.ident);
5039 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5040 let split : Vec<&str> = name.split('_').collect();
5041 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5043 //We only care about the operation here
5044 let (n_tps, inputs, output) = match split[1] {
5045 "cxchg" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
5049 "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
5051 "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5054 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5055 "min" | "umax" | "umin" => {
5056 (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5059 "fence" | "singlethreadfence" => {
5060 (0, Vec::new(), tcx.mk_nil())
5063 span_err!(tcx.sess, it.span, E0092,
5064 "unrecognized atomic operation function: `{}`", op);
5068 (n_tps, inputs, ty::FnConverging(output))
5069 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5070 (0, Vec::new(), ty::FnDiverging)
5072 let (n_tps, inputs, output) = match &name[..] {
5073 "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
5075 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
5076 "size_of_val" | "min_align_of_val" => {
5078 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5081 ], ccx.tcx.types.usize)
5083 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
5084 "uninit" => (1, Vec::new(), param(ccx, 0)),
5085 "forget" => (1, vec!( param(ccx, 0) ), tcx.mk_nil()),
5086 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5087 "move_val_init" => {
5090 tcx.mk_mut_ptr(param(ccx, 0)),
5095 "drop_in_place" => {
5096 (1, vec![tcx.mk_mut_ptr(param(ccx, 0))], tcx.mk_nil())
5098 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5100 "type_name" => (1, Vec::new(), tcx.mk_static_str()),
5101 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5102 "offset" | "arith_offset" => {
5105 tcx.mk_ptr(ty::TypeAndMut {
5107 mutbl: ast::MutImmutable
5111 tcx.mk_ptr(ty::TypeAndMut {
5113 mutbl: ast::MutImmutable
5116 "copy" | "copy_nonoverlapping" => {
5119 tcx.mk_ptr(ty::TypeAndMut {
5121 mutbl: ast::MutImmutable
5123 tcx.mk_ptr(ty::TypeAndMut {
5125 mutbl: ast::MutMutable
5131 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5134 tcx.mk_ptr(ty::TypeAndMut {
5136 mutbl: ast::MutMutable
5138 tcx.mk_ptr(ty::TypeAndMut {
5140 mutbl: ast::MutImmutable
5146 "write_bytes" | "volatile_set_memory" => {
5149 tcx.mk_ptr(ty::TypeAndMut {
5151 mutbl: ast::MutMutable
5158 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5159 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5162 vec!( tcx.types.f32, tcx.types.i32 ),
5167 vec!( tcx.types.f64, tcx.types.i32 ),
5170 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5171 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5172 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5173 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5176 vec!( tcx.types.f32, tcx.types.f32 ),
5181 vec!( tcx.types.f64, tcx.types.f64 ),
5184 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5185 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5186 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5187 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5188 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5189 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5190 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5191 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5192 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5193 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5196 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5201 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5204 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5205 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5206 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5207 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5208 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5209 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5210 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5211 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5212 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5213 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5214 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5215 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5216 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5217 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5218 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5219 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5220 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5221 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5222 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5223 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5224 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5225 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5226 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5227 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5228 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5229 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5230 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5231 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5232 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5233 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5234 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5237 (1, vec!( tcx.mk_imm_ptr(param(ccx, 0)) ), param(ccx, 0)),
5239 (1, vec!( tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ), tcx.mk_nil()),
5241 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5242 (0, vec!(tcx.types.i8, tcx.types.i8),
5243 tcx.mk_tup(vec!(tcx.types.i8, tcx.types.bool))),
5245 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5246 (0, vec!(tcx.types.i16, tcx.types.i16),
5247 tcx.mk_tup(vec!(tcx.types.i16, tcx.types.bool))),
5249 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5250 (0, vec!(tcx.types.i32, tcx.types.i32),
5251 tcx.mk_tup(vec!(tcx.types.i32, tcx.types.bool))),
5253 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5254 (0, vec!(tcx.types.i64, tcx.types.i64),
5255 tcx.mk_tup(vec!(tcx.types.i64, tcx.types.bool))),
5257 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5258 (0, vec!(tcx.types.u8, tcx.types.u8),
5259 tcx.mk_tup(vec!(tcx.types.u8, tcx.types.bool))),
5261 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5262 (0, vec!(tcx.types.u16, tcx.types.u16),
5263 tcx.mk_tup(vec!(tcx.types.u16, tcx.types.bool))),
5265 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5266 (0, vec!(tcx.types.u32, tcx.types.u32),
5267 tcx.mk_tup(vec!(tcx.types.u32, tcx.types.bool))),
5269 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5270 (0, vec!(tcx.types.u64, tcx.types.u64),
5271 tcx.mk_tup(vec!(tcx.types.u64, tcx.types.bool))),
5273 "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
5274 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5276 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5277 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5279 "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
5281 "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
5283 "discriminant_value" => (1, vec![
5284 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5286 param(ccx, 0))], tcx.types.u64),
5289 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
5290 let fn_ty = ty::BareFnTy {
5291 unsafety: ast::Unsafety::Normal,
5293 sig: ty::Binder(FnSig {
5294 inputs: vec![mut_u8],
5295 output: ty::FnOutput::FnConverging(tcx.mk_nil()),
5299 let fn_ty = tcx.mk_bare_fn(fn_ty);
5300 (0, vec![tcx.mk_fn(None, fn_ty), mut_u8], mut_u8)
5304 span_err!(tcx.sess, it.span, E0093,
5305 "unrecognized intrinsic function: `{}`", *other);
5309 (n_tps, inputs, ty::FnConverging(output))
5311 let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
5312 unsafety: ast::Unsafety::Unsafe,
5313 abi: abi::RustIntrinsic,
5314 sig: ty::Binder(FnSig {
5320 let i_ty = ccx.tcx.lookup_item_type(local_def(it.id));
5321 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5322 if i_n_tps != n_tps {
5323 span_err!(tcx.sess, it.span, E0094,
5324 "intrinsic has wrong number of type \
5325 parameters: found {}, expected {}",
5328 require_same_types(tcx,
5335 format!("intrinsic has wrong type: expected `{}`",