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::{self, InternedString};
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 {:?}",
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 {}", 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 {}", 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| {
803 span_err!(ccx.tcx.sess, attr.span, E0230,
804 "there is no type parameter \
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 `{:?}`",
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 `{:?}`",
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 `{:?}`",
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 `{:?}`",
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(|name| name.to_string())
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: `{}`",
1022 invalidated_items.iter()
1023 .map(|name| name.to_string())
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 // FIXME(arielb1): use this instead of field.ty everywhere
1678 pub fn field_ty(&self,
1680 field: ty::FieldDef<'tcx>,
1681 substs: &Substs<'tcx>)
1684 self.normalize_associated_types_in(span,
1685 &field.ty(self.tcx(), substs))
1688 // Only for fields! Returns <none> for methods>
1689 // Indifferent to privacy flags
1690 fn check_casts(&self) {
1691 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1692 for cast in deferred_cast_checks.drain(..) {
1697 /// Apply "fallbacks" to some types
1698 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1699 fn default_type_parameters(&self) {
1700 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1701 for ty in &self.infcx().unsolved_variables() {
1702 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1703 if self.infcx().type_var_diverges(resolved) {
1704 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1706 match self.infcx().type_is_unconstrained_numeric(resolved) {
1707 UnconstrainedInt => {
1708 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1710 UnconstrainedFloat => {
1711 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1719 fn select_all_obligations_and_apply_defaults(&self) {
1720 if self.tcx().sess.features.borrow().default_type_parameter_fallback {
1721 self.new_select_all_obligations_and_apply_defaults();
1723 self.old_select_all_obligations_and_apply_defaults();
1727 // Implements old type inference fallback algorithm
1728 fn old_select_all_obligations_and_apply_defaults(&self) {
1729 self.select_obligations_where_possible();
1730 self.default_type_parameters();
1731 self.select_obligations_where_possible();
1734 fn new_select_all_obligations_and_apply_defaults(&self) {
1735 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1737 // For the time being this errs on the side of being memory wasteful but provides better
1739 // let type_variables = self.infcx().type_variables.clone();
1741 // There is a possibility that this algorithm will have to run an arbitrary number of times
1742 // to terminate so we bound it by the compiler's recursion limit.
1743 for _ in (0..self.tcx().sess.recursion_limit.get()) {
1744 // First we try to solve all obligations, it is possible that the last iteration
1745 // has made it possible to make more progress.
1746 self.select_obligations_where_possible();
1748 let mut conflicts = Vec::new();
1750 // Collect all unsolved type, integral and floating point variables.
1751 let unsolved_variables = self.inh.infcx.unsolved_variables();
1753 // We must collect the defaults *before* we do any unification. Because we have
1754 // directly attached defaults to the type variables any unification that occurs
1755 // will erase defaults causing conflicting defaults to be completely ignored.
1756 let default_map: FnvHashMap<_, _> =
1759 .filter_map(|t| self.infcx().default(t).map(|d| (t, d)))
1762 let mut unbound_tyvars = HashSet::new();
1764 debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);
1766 // We loop over the unsolved variables, resolving them and if they are
1767 // and unconstrainted numberic type we add them to the set of unbound
1768 // variables. We do this so we only apply literal fallback to type
1769 // variables without defaults.
1770 for ty in &unsolved_variables {
1771 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1772 if self.infcx().type_var_diverges(resolved) {
1773 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1775 match self.infcx().type_is_unconstrained_numeric(resolved) {
1776 UnconstrainedInt | UnconstrainedFloat => {
1777 unbound_tyvars.insert(resolved);
1784 // We now remove any numeric types that also have defaults, and instead insert
1785 // the type variable with a defined fallback.
1786 for ty in &unsolved_variables {
1787 if let Some(_default) = default_map.get(ty) {
1788 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1790 debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
1793 match resolved.sty {
1794 ty::TyInfer(ty::TyVar(_)) => {
1795 unbound_tyvars.insert(ty);
1798 ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
1799 unbound_tyvars.insert(ty);
1800 if unbound_tyvars.contains(resolved) {
1801 unbound_tyvars.remove(resolved);
1810 // If there are no more fallbacks to apply at this point we have applied all possible
1811 // defaults and type inference will procede as normal.
1812 if unbound_tyvars.is_empty() {
1816 // Finally we go through each of the unbound type variables and unify them with
1817 // the proper fallback, reporting a conflicting default error if any of the
1818 // unifications fail. We know it must be a conflicting default because the
1819 // variable would only be in `unbound_tyvars` and have a concrete value if
1820 // it had been solved by previously applying a default.
1822 // We wrap this in a transaction for error reporting, if we detect a conflict
1823 // we will rollback the inference context to its prior state so we can probe
1824 // for conflicts and correctly report them.
1827 let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
1828 for ty in &unbound_tyvars {
1829 if self.infcx().type_var_diverges(ty) {
1830 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1832 match self.infcx().type_is_unconstrained_numeric(ty) {
1833 UnconstrainedInt => {
1834 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1836 UnconstrainedFloat => {
1837 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1840 if let Some(default) = default_map.get(ty) {
1841 let default = default.clone();
1842 match infer::mk_eqty(self.infcx(), false,
1843 infer::Misc(default.origin_span),
1847 conflicts.push((*ty, default));
1856 // If there are conflicts we rollback, otherwise commit
1857 if conflicts.len() > 0 {
1864 if conflicts.len() > 0 {
1865 // Loop through each conflicting default, figuring out the default that caused
1866 // a unification failure and then report an error for each.
1867 for (conflict, default) in conflicts {
1868 let conflicting_default =
1869 self.find_conflicting_default(&unbound_tyvars, &default_map, conflict)
1870 .unwrap_or(type_variable::Default {
1871 ty: self.infcx().next_ty_var(),
1872 origin_span: codemap::DUMMY_SP,
1873 def_id: local_def(0) // what do I put here?
1876 // This is to ensure that we elimnate any non-determinism from the error
1877 // reporting by fixing an order, it doesn't matter what order we choose
1878 // just that it is consistent.
1879 let (first_default, second_default) =
1880 if default.def_id < conflicting_default.def_id {
1881 (default, conflicting_default)
1883 (conflicting_default, default)
1887 self.infcx().report_conflicting_default_types(
1888 first_default.origin_span,
1895 self.select_obligations_where_possible();
1898 // For use in error handling related to default type parameter fallback. We explicitly
1899 // apply the default that caused conflict first to a local version of the type variable
1900 // table then apply defaults until we find a conflict. That default must be the one
1901 // that caused conflict earlier.
1902 fn find_conflicting_default(&self,
1903 unbound_vars: &HashSet<Ty<'tcx>>,
1904 default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>,
1906 -> Option<type_variable::Default<'tcx>> {
1907 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1909 // Ensure that we apply the conflicting default first
1910 let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1);
1911 unbound_tyvars.push(conflict);
1912 unbound_tyvars.extend(unbound_vars.iter());
1914 let mut result = None;
1915 // We run the same code as above applying defaults in order, this time when
1916 // we find the conflict we just return it for error reporting above.
1918 // We also run this inside snapshot that never commits so we can do error
1919 // reporting for more then one conflict.
1920 for ty in &unbound_tyvars {
1921 if self.infcx().type_var_diverges(ty) {
1922 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
1924 match self.infcx().type_is_unconstrained_numeric(ty) {
1925 UnconstrainedInt => {
1926 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1928 UnconstrainedFloat => {
1929 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1932 if let Some(default) = default_map.get(ty) {
1933 let default = default.clone();
1934 match infer::mk_eqty(self.infcx(), false,
1935 infer::Misc(default.origin_span),
1939 result = Some(default);
1951 fn select_all_obligations_or_error(&self) {
1952 debug!("select_all_obligations_or_error");
1954 // upvar inference should have ensured that all deferred call
1955 // resolutions are handled by now.
1956 assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
1958 self.select_all_obligations_and_apply_defaults();
1960 let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
1961 match fulfillment_cx.select_all_or_error(self.infcx()) {
1963 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1967 /// Select as many obligations as we can at present.
1968 fn select_obligations_where_possible(&self) {
1970 self.inh.infcx.fulfillment_cx
1972 .select_where_possible(self.infcx())
1975 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1979 /// Try to select any fcx obligation that we haven't tried yet, in an effort
1980 /// to improve inference. You could just call
1981 /// `select_obligations_where_possible` except that it leads to repeated
1983 fn select_new_obligations(&self) {
1985 self.inh.infcx.fulfillment_cx
1987 .select_new_obligations(self.infcx())
1990 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1996 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1997 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1998 Some(self.base_object_lifetime_default(span))
2001 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
2002 // RFC #599 specifies that object lifetime defaults take
2003 // precedence over other defaults. But within a fn body we
2004 // don't have a *default* region, rather we use inference to
2005 // find the *correct* region, which is strictly more general
2006 // (and anyway, within a fn body the right region may not even
2007 // be something the user can write explicitly, since it might
2008 // be some expression).
2009 self.infcx().next_region_var(infer::MiscVariable(span))
2012 fn anon_regions(&self, span: Span, count: usize)
2013 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
2014 Ok((0..count).map(|_| {
2015 self.infcx().next_region_var(infer::MiscVariable(span))
2020 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
2021 pub enum LvaluePreference {
2026 impl LvaluePreference {
2027 pub fn from_mutbl(m: ast::Mutability) -> Self {
2029 ast::MutMutable => PreferMutLvalue,
2030 ast::MutImmutable => NoPreference,
2035 /// Whether `autoderef` requires types to resolve.
2036 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
2037 pub enum UnresolvedTypeAction {
2038 /// Produce an error and return `TyError` whenever a type cannot
2039 /// be resolved (i.e. it is `TyInfer`).
2041 /// Go on without emitting any errors, and return the unresolved
2042 /// type. Useful for probing, e.g. in coercions.
2046 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
2047 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
2049 /// Note: this method does not modify the adjustments table. The caller is responsible for
2050 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
2051 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2054 opt_expr: Option<&ast::Expr>,
2055 unresolved_type_action: UnresolvedTypeAction,
2056 mut lvalue_pref: LvaluePreference,
2058 -> (Ty<'tcx>, usize, Option<T>)
2059 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
2061 debug!("autoderef(base_ty={:?}, opt_expr={:?}, lvalue_pref={:?})",
2066 let mut t = base_ty;
2067 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
2068 let resolved_t = match unresolved_type_action {
2069 UnresolvedTypeAction::Error => {
2070 structurally_resolved_type(fcx, sp, t)
2072 UnresolvedTypeAction::Ignore => {
2073 // We can continue even when the type cannot be resolved
2074 // (i.e. it is an inference variable) because `Ty::builtin_deref`
2075 // and `try_overloaded_deref` both simply return `None`
2076 // in such a case without producing spurious errors.
2077 fcx.resolve_type_vars_if_possible(t)
2080 if resolved_t.references_error() {
2081 return (resolved_t, autoderefs, None);
2084 match should_stop(resolved_t, autoderefs) {
2085 Some(x) => return (resolved_t, autoderefs, Some(x)),
2089 // Otherwise, deref if type is derefable:
2090 let mt = match resolved_t.builtin_deref(false) {
2091 Some(mt) => Some(mt),
2094 opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
2096 // Super subtle: it might seem as though we should
2097 // pass `opt_expr` to `try_overloaded_deref`, so that
2098 // the (implicit) autoref of using an overloaded deref
2099 // would get added to the adjustment table. However we
2100 // do not do that, because it's kind of a
2101 // "meta-adjustment" -- instead, we just leave it
2102 // unrecorded and know that there "will be" an
2103 // autoref. regionck and other bits of the code base,
2104 // when they encounter an overloaded autoderef, have
2105 // to do some reconstructive surgery. This is a pretty
2106 // complex mess that is begging for a proper MIR.
2107 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2113 if mt.mutbl == ast::MutImmutable {
2114 lvalue_pref = NoPreference;
2117 None => return (resolved_t, autoderefs, None)
2121 // We've reached the recursion limit, error gracefully.
2122 span_err!(fcx.tcx().sess, sp, E0055,
2123 "reached the recursion limit while auto-dereferencing {:?}",
2125 (fcx.tcx().types.err, 0, None)
2128 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2130 method_call: Option<MethodCall>,
2131 base_expr: Option<&ast::Expr>,
2133 lvalue_pref: LvaluePreference)
2134 -> Option<ty::TypeAndMut<'tcx>>
2136 // Try DerefMut first, if preferred.
2137 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2138 (PreferMutLvalue, Some(trait_did)) => {
2139 method::lookup_in_trait(fcx, span, base_expr,
2140 token::intern("deref_mut"), trait_did,
2146 // Otherwise, fall back to Deref.
2147 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2148 (None, Some(trait_did)) => {
2149 method::lookup_in_trait(fcx, span, base_expr,
2150 token::intern("deref"), trait_did,
2153 (method, _) => method
2156 make_overloaded_lvalue_return_type(fcx, method_call, method)
2159 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2160 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2161 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2162 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2163 method_call: Option<MethodCall>,
2164 method: Option<MethodCallee<'tcx>>)
2165 -> Option<ty::TypeAndMut<'tcx>>
2169 // extract method method return type, which will be &T;
2170 // all LB regions should have been instantiated during method lookup
2171 let ret_ty = method.ty.fn_ret();
2172 let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
2174 if let Some(method_call) = method_call {
2175 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2178 // method returns &T, but the type as visible to user is T, so deref
2179 ret_ty.builtin_deref(true)
2185 fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2187 base_expr: &'tcx ast::Expr,
2190 lvalue_pref: LvaluePreference)
2191 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2193 // FIXME(#18741) -- this is almost but not quite the same as the
2194 // autoderef that normal method probing does. They could likely be
2197 let (ty, autoderefs, final_mt) = autoderef(fcx,
2201 UnresolvedTypeAction::Error,
2204 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2205 adj_ty, idx, false, lvalue_pref, idx_ty)
2208 if final_mt.is_some() {
2212 // After we have fully autoderef'd, if the resulting type is [T; n], then
2213 // do a final unsized coercion to yield [T].
2214 if let ty::TyArray(element_ty, _) = ty.sty {
2215 let adjusted_ty = fcx.tcx().mk_slice(element_ty);
2216 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2217 adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
2223 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2224 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2225 /// This loop implements one step in that search; the autoderef loop is implemented by
2226 /// `lookup_indexing`.
2227 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2228 method_call: MethodCall,
2230 base_expr: &'tcx ast::Expr,
2231 adjusted_ty: Ty<'tcx>,
2234 lvalue_pref: LvaluePreference,
2236 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2238 let tcx = fcx.tcx();
2239 debug!("try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
2240 autoderefs={}, unsize={}, index_ty={:?})",
2248 let input_ty = fcx.infcx().next_ty_var();
2250 // First, try built-in indexing.
2251 match (adjusted_ty.builtin_index(), &index_ty.sty) {
2252 (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
2253 debug!("try_index_step: success, using built-in indexing");
2254 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2256 fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
2257 return Some((tcx.types.usize, ty));
2262 // Try `IndexMut` first, if preferred.
2263 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2264 (PreferMutLvalue, Some(trait_did)) => {
2265 method::lookup_in_trait_adjusted(fcx,
2268 token::intern("index_mut"),
2273 Some(vec![input_ty]))
2278 // Otherwise, fall back to `Index`.
2279 let method = match (method, tcx.lang_items.index_trait()) {
2280 (None, Some(trait_did)) => {
2281 method::lookup_in_trait_adjusted(fcx,
2284 token::intern("index"),
2289 Some(vec![input_ty]))
2291 (method, _) => method,
2294 // If some lookup succeeds, write callee into table and extract index/element
2295 // type from the method signature.
2296 // If some lookup succeeded, install method in table
2297 method.and_then(|method| {
2298 debug!("try_index_step: success, using overloaded indexing");
2299 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2300 map(|ret| (input_ty, ret.ty))
2304 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2306 method_fn_ty: Ty<'tcx>,
2307 callee_expr: &'tcx ast::Expr,
2308 args_no_rcvr: &'tcx [P<ast::Expr>],
2309 tuple_arguments: TupleArgumentsFlag,
2310 expected: Expectation<'tcx>)
2311 -> ty::FnOutput<'tcx> {
2312 if method_fn_ty.references_error() {
2313 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2315 let err_inputs = match tuple_arguments {
2316 DontTupleArguments => err_inputs,
2317 TupleArguments => vec![fcx.tcx().mk_tup(err_inputs)],
2320 check_argument_types(fcx,
2327 ty::FnConverging(fcx.tcx().types.err)
2329 match method_fn_ty.sty {
2330 ty::TyBareFn(_, ref fty) => {
2331 // HACK(eddyb) ignore self in the definition (see above).
2332 let expected_arg_tys = expected_types_for_fn_args(fcx,
2336 &fty.sig.0.inputs[1..]);
2337 check_argument_types(fcx,
2339 &fty.sig.0.inputs[1..],
2340 &expected_arg_tys[..],
2347 fcx.tcx().sess.span_bug(callee_expr.span,
2348 "method without bare fn type");
2354 /// Generic function that factors out common logic from function calls, method calls and overloaded
2356 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2358 fn_inputs: &[Ty<'tcx>],
2359 expected_arg_tys: &[Ty<'tcx>],
2360 args: &'tcx [P<ast::Expr>],
2362 tuple_arguments: TupleArgumentsFlag) {
2363 let tcx = fcx.ccx.tcx;
2365 // Grab the argument types, supplying fresh type variables
2366 // if the wrong number of arguments were supplied
2367 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2373 let mut expected_arg_tys = expected_arg_tys;
2374 let expected_arg_count = fn_inputs.len();
2375 let formal_tys = if tuple_arguments == TupleArguments {
2376 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2377 match tuple_type.sty {
2378 ty::TyTuple(ref arg_types) => {
2379 if arg_types.len() != args.len() {
2380 span_err!(tcx.sess, sp, E0057,
2381 "this function takes {} parameter{} but {} parameter{} supplied",
2383 if arg_types.len() == 1 {""} else {"s"},
2385 if args.len() == 1 {" was"} else {"s were"});
2386 expected_arg_tys = &[];
2387 err_args(fcx.tcx(), args.len())
2389 expected_arg_tys = match expected_arg_tys.get(0) {
2390 Some(&ty) => match ty.sty {
2391 ty::TyTuple(ref tys) => &**tys,
2396 (*arg_types).clone()
2400 span_err!(tcx.sess, sp, E0059,
2401 "cannot use call notation; the first type parameter \
2402 for the function trait is neither a tuple nor unit");
2403 expected_arg_tys = &[];
2404 err_args(fcx.tcx(), args.len())
2407 } else if expected_arg_count == supplied_arg_count {
2409 } else if variadic {
2410 if supplied_arg_count >= expected_arg_count {
2413 span_err!(tcx.sess, sp, E0060,
2414 "this function takes at least {} parameter{} \
2415 but {} parameter{} supplied",
2417 if expected_arg_count == 1 {""} else {"s"},
2419 if supplied_arg_count == 1 {" was"} else {"s were"});
2420 expected_arg_tys = &[];
2421 err_args(fcx.tcx(), supplied_arg_count)
2424 span_err!(tcx.sess, sp, E0061,
2425 "this function takes {} parameter{} but {} parameter{} supplied",
2427 if expected_arg_count == 1 {""} else {"s"},
2429 if supplied_arg_count == 1 {" was"} else {"s were"});
2430 expected_arg_tys = &[];
2431 err_args(fcx.tcx(), supplied_arg_count)
2434 debug!("check_argument_types: formal_tys={:?}",
2435 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2437 // Check the arguments.
2438 // We do this in a pretty awful way: first we typecheck any arguments
2439 // that are not anonymous functions, then we typecheck the anonymous
2440 // functions. This is so that we have more information about the types
2441 // of arguments when we typecheck the functions. This isn't really the
2442 // right way to do this.
2443 let xs = [false, true];
2444 for check_blocks in &xs {
2445 let check_blocks = *check_blocks;
2446 debug!("check_blocks={}", check_blocks);
2448 // More awful hacks: before we check argument types, try to do
2449 // an "opportunistic" vtable resolution of any trait bounds on
2450 // the call. This helps coercions.
2452 fcx.select_new_obligations();
2455 // For variadic functions, we don't have a declared type for all of
2456 // the arguments hence we only do our usual type checking with
2457 // the arguments who's types we do know.
2458 let t = if variadic {
2460 } else if tuple_arguments == TupleArguments {
2465 for (i, arg) in args.iter().take(t).enumerate() {
2466 let is_block = match arg.node {
2467 ast::ExprClosure(..) => true,
2471 if is_block == check_blocks {
2472 debug!("checking the argument");
2473 let formal_ty = formal_tys[i];
2475 // The special-cased logic below has three functions:
2476 // 1. Provide as good of an expected type as possible.
2477 let expected = expected_arg_tys.get(i).map(|&ty| {
2478 Expectation::rvalue_hint(fcx.tcx(), ty)
2481 check_expr_with_unifier(fcx, &**arg,
2482 expected.unwrap_or(ExpectHasType(formal_ty)),
2484 // 2. Coerce to the most detailed type that could be coerced
2485 // to, which is `expected_ty` if `rvalue_hint` returns an
2486 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2487 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2488 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2490 // 3. Relate the expected type and the formal one,
2491 // if the expected type was used for the coercion.
2492 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2498 // We also need to make sure we at least write the ty of the other
2499 // arguments which we skipped above.
2501 for arg in args.iter().skip(expected_arg_count) {
2502 check_expr(fcx, &**arg);
2504 // There are a few types which get autopromoted when passed via varargs
2505 // in C but we just error out instead and require explicit casts.
2506 let arg_ty = structurally_resolved_type(fcx, arg.span,
2507 fcx.expr_ty(&**arg));
2509 ty::TyFloat(ast::TyF32) => {
2510 fcx.type_error_message(arg.span,
2512 format!("can't pass an {} to variadic \
2513 function, cast to c_double", t)
2516 ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
2517 fcx.type_error_message(arg.span, |t| {
2518 format!("can't pass {} to variadic \
2519 function, cast to c_int",
2523 ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
2524 fcx.type_error_message(arg.span, |t| {
2525 format!("can't pass {} to variadic \
2526 function, cast to c_uint",
2536 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2537 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2538 (0..len).map(|_| tcx.types.err).collect()
2541 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2542 call_expr: &ast::Expr,
2543 output: ty::FnOutput<'tcx>) {
2544 fcx.write_ty(call_expr.id, match output {
2545 ty::FnConverging(output_ty) => output_ty,
2546 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2550 // AST fragment checking
2551 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2553 expected: Expectation<'tcx>)
2556 let tcx = fcx.ccx.tcx;
2559 ast::LitStr(..) => tcx.mk_static_str(),
2560 ast::LitBinary(ref v) => {
2561 tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
2562 tcx.mk_array(tcx.types.u8, v.len()))
2564 ast::LitByte(_) => tcx.types.u8,
2565 ast::LitChar(_) => tcx.types.char,
2566 ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
2567 ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
2568 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2569 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2571 ty::TyInt(_) | ty::TyUint(_) => Some(ty),
2572 ty::TyChar => Some(tcx.types.u8),
2573 ty::TyRawPtr(..) => Some(tcx.types.usize),
2574 ty::TyBareFn(..) => Some(tcx.types.usize),
2578 opt_ty.unwrap_or_else(
2579 || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
2581 ast::LitFloat(_, t) => tcx.mk_mach_float(t),
2582 ast::LitFloatUnsuffixed(_) => {
2583 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2585 ty::TyFloat(_) => Some(ty),
2589 opt_ty.unwrap_or_else(
2590 || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
2592 ast::LitBool(_) => tcx.types.bool
2596 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2597 expr: &'tcx ast::Expr,
2598 expected: Ty<'tcx>) {
2599 check_expr_with_unifier(
2600 fcx, expr, ExpectHasType(expected), NoPreference,
2601 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2604 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2605 expr: &'tcx ast::Expr,
2606 expected: Ty<'tcx>) {
2607 check_expr_with_unifier(
2608 fcx, expr, ExpectHasType(expected), NoPreference,
2609 || demand::coerce(fcx, expr.span, expected, expr));
2612 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2613 expected: Ty<'tcx>) {
2614 check_expr_with_unifier(
2615 fcx, expr, ExpectHasType(expected), NoPreference,
2619 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2620 expr: &'tcx ast::Expr,
2621 expected: Expectation<'tcx>) {
2622 check_expr_with_unifier(
2623 fcx, expr, expected, NoPreference,
2627 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2628 expr: &'tcx ast::Expr,
2629 expected: Expectation<'tcx>,
2630 lvalue_pref: LvaluePreference)
2632 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2635 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2636 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2639 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2640 lvalue_pref: LvaluePreference) {
2641 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2644 // determine the `self` type, using fresh variables for all variables
2645 // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
2646 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2648 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2649 span: Span, // (potential) receiver for this impl
2651 -> TypeAndSubsts<'tcx> {
2652 let tcx = fcx.tcx();
2654 let ity = tcx.lookup_item_type(did);
2655 let (tps, rps, raw_ty) =
2656 (ity.generics.types.get_slice(subst::TypeSpace),
2657 ity.generics.regions.get_slice(subst::TypeSpace),
2660 debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
2662 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2663 let mut substs = subst::Substs::new(
2664 VecPerParamSpace::empty(),
2665 VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
2666 fcx.inh.infcx.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
2667 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2669 TypeAndSubsts { substs: substs, ty: substd_ty }
2672 /// Controls whether the arguments are tupled. This is used for the call
2675 /// Tupling means that all call-side arguments are packed into a tuple and
2676 /// passed as a single parameter. For example, if tupling is enabled, this
2679 /// fn f(x: (isize, isize))
2681 /// Can be called as:
2688 #[derive(Clone, Eq, PartialEq)]
2689 enum TupleArgumentsFlag {
2694 /// Unifies the return type with the expected type early, for more coercions
2695 /// and forward type information on the argument expressions.
2696 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2698 expected_ret: Expectation<'tcx>,
2699 formal_ret: ty::FnOutput<'tcx>,
2700 formal_args: &[Ty<'tcx>])
2702 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2703 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2704 fcx.infcx().commit_regions_if_ok(|| {
2705 // Attempt to apply a subtyping relationship between the formal
2706 // return type (likely containing type variables if the function
2707 // is polymorphic) and the expected return type.
2708 // No argument expectations are produced if unification fails.
2709 let origin = infer::Misc(call_span);
2710 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2711 // FIXME(#15760) can't use try! here, FromError doesn't default
2712 // to identity so the resulting type is not constrained.
2713 if let Err(e) = ures {
2717 // Record all the argument types, with the substitutions
2718 // produced from the above subtyping unification.
2719 Ok(formal_args.iter().map(|ty| {
2720 fcx.infcx().resolve_type_vars_if_possible(ty)
2726 }).unwrap_or(vec![]);
2727 debug!("expected_types_for_fn_args(formal={:?} -> {:?}, expected={:?} -> {:?})",
2728 formal_args, formal_ret,
2729 expected_args, expected_ret);
2734 /// If an expression has any sub-expressions that result in a type error,
2735 /// inspecting that expression's type with `ty.references_error()` will return
2736 /// true. Likewise, if an expression is known to diverge, inspecting its
2737 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2738 /// strict, _|_ can appear in the type of an expression that does not,
2739 /// itself, diverge: for example, fn() -> _|_.)
2740 /// Note that inspecting a type's structure *directly* may expose the fact
2741 /// that there are actually multiple representations for `TyError`, so avoid
2742 /// that when err needs to be handled differently.
2743 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2744 expr: &'tcx ast::Expr,
2745 expected: Expectation<'tcx>,
2746 lvalue_pref: LvaluePreference,
2750 debug!(">> typechecking: expr={:?} expected={:?}",
2753 // Checks a method call.
2754 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2755 expr: &'tcx ast::Expr,
2756 method_name: ast::SpannedIdent,
2757 args: &'tcx [P<ast::Expr>],
2759 expected: Expectation<'tcx>,
2760 lvalue_pref: LvaluePreference) {
2761 let rcvr = &*args[0];
2762 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2764 // no need to check for bot/err -- callee does that
2765 let expr_t = structurally_resolved_type(fcx,
2767 fcx.expr_ty(&*rcvr));
2769 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2770 let fn_ty = match method::lookup(fcx,
2772 method_name.node.name,
2778 let method_ty = method.ty;
2779 let method_call = MethodCall::expr(expr.id);
2780 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
2784 method::report_error(fcx, method_name.span, expr_t,
2785 method_name.node.name, Some(rcvr), error);
2786 fcx.write_error(expr.id);
2791 // Call the generic checker.
2792 let ret_ty = check_method_argument_types(fcx,
2800 write_call(fcx, expr, ret_ty);
2803 // A generic function for checking the then and else in an if
2805 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2806 cond_expr: &'tcx ast::Expr,
2807 then_blk: &'tcx ast::Block,
2808 opt_else_expr: Option<&'tcx ast::Expr>,
2811 expected: Expectation<'tcx>) {
2812 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2814 let expected = expected.adjust_for_branches(fcx);
2815 check_block_with_expected(fcx, then_blk, expected);
2816 let then_ty = fcx.node_ty(then_blk.id);
2818 let branches_ty = match opt_else_expr {
2819 Some(ref else_expr) => {
2820 check_expr_with_expectation(fcx, &**else_expr, expected);
2821 let else_ty = fcx.expr_ty(&**else_expr);
2822 infer::common_supertype(fcx.infcx(),
2823 infer::IfExpression(sp),
2829 infer::common_supertype(fcx.infcx(),
2830 infer::IfExpressionWithNoElse(sp),
2837 let cond_ty = fcx.expr_ty(cond_expr);
2838 let if_ty = if cond_ty.references_error() {
2844 fcx.write_ty(id, if_ty);
2847 // Check field access expressions
2848 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2849 expr: &'tcx ast::Expr,
2850 lvalue_pref: LvaluePreference,
2851 base: &'tcx ast::Expr,
2852 field: &ast::SpannedIdent) {
2853 let tcx = fcx.ccx.tcx;
2854 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2855 let expr_t = structurally_resolved_type(fcx, expr.span,
2857 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2858 let (_, autoderefs, field_ty) = autoderef(fcx,
2862 UnresolvedTypeAction::Error,
2866 ty::TyStruct(base_def, substs) => {
2867 debug!("struct named {:?}", base_t);
2868 base_def.struct_variant()
2869 .find_field_named(field.node.name)
2870 .map(|f| fcx.field_ty(expr.span, f, substs))
2877 fcx.write_ty(expr.id, field_ty);
2878 fcx.write_autoderef_adjustment(base.id, autoderefs);
2884 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2885 fcx.type_error_message(
2888 format!("attempted to take value of method `{}` on type \
2889 `{}`", field.node, actual)
2893 tcx.sess.fileline_help(field.span,
2894 "maybe a `()` to call it is missing? \
2895 If not, try an anonymous function");
2897 fcx.type_error_message(
2900 format!("attempted access of field `{}` on \
2901 type `{}`, but no field with that \
2907 if let ty::TyStruct(def, _) = expr_t.sty {
2908 suggest_field_names(def.struct_variant(), field, tcx, vec![]);
2912 fcx.write_error(expr.id);
2915 // displays hints about the closest matches in field names
2916 fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
2917 field: &ast::SpannedIdent,
2918 tcx: &ty::ctxt<'tcx>,
2919 skip : Vec<InternedString>) {
2920 let name = field.node.name.as_str();
2921 // only find fits with at least one matching letter
2922 let mut best_dist = name.len();
2923 let mut best = None;
2924 for elem in &variant.fields {
2925 let n = elem.name.as_str();
2926 // ignore already set fields
2927 if skip.iter().any(|x| *x == n) {
2930 // ignore private fields from non-local crates
2931 if variant.did.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2934 let dist = lev_distance(&n, &name);
2935 if dist < best_dist {
2940 if let Some(n) = best {
2941 tcx.sess.span_help(field.span,
2942 &format!("did you mean `{}`?", n));
2946 // Check tuple index expressions
2947 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2948 expr: &'tcx ast::Expr,
2949 lvalue_pref: LvaluePreference,
2950 base: &'tcx ast::Expr,
2951 idx: codemap::Spanned<usize>) {
2952 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2953 let expr_t = structurally_resolved_type(fcx, expr.span,
2955 let mut tuple_like = false;
2956 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2957 let (_, autoderefs, field_ty) = autoderef(fcx,
2961 UnresolvedTypeAction::Error,
2965 ty::TyStruct(base_def, substs) => {
2966 tuple_like = base_def.struct_variant().is_tuple_struct();
2968 debug!("tuple struct named {:?}", base_t);
2969 base_def.struct_variant()
2972 .map(|f| fcx.field_ty(expr.span, f, substs))
2977 ty::TyTuple(ref v) => {
2979 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2986 fcx.write_ty(expr.id, field_ty);
2987 fcx.write_autoderef_adjustment(base.id, autoderefs);
2992 fcx.type_error_message(
2996 format!("attempted out-of-bounds tuple index `{}` on \
3001 format!("attempted tuple index `{}` on type `{}`, but the \
3002 type was not a tuple or tuple struct",
3009 fcx.write_error(expr.id);
3012 fn report_unknown_field<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3014 variant: ty::VariantDef<'tcx>,
3016 skip_fields: &[ast::Field]) {
3017 fcx.type_error_message(
3019 |actual| if let ty::TyEnum(..) = ty.sty {
3020 format!("struct variant `{}::{}` has no field named `{}`",
3021 actual, variant.name.as_str(), field.ident.node)
3023 format!("structure `{}` has no field named `{}`",
3024 actual, field.ident.node)
3028 // prevent all specified fields from being suggested
3029 let skip_fields = skip_fields.iter().map(|ref x| x.ident.node.name.as_str());
3030 suggest_field_names(variant, &field.ident, fcx.tcx(), skip_fields.collect());
3034 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3037 variant_id: ast::DefId,
3038 ast_fields: &'tcx [ast::Field],
3039 check_completeness: bool) -> Result<(),()> {
3040 let tcx = fcx.ccx.tcx;
3041 let (adt_def, substs) = match adt_ty.sty {
3042 ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => (def, substs),
3043 _ => tcx.sess.span_bug(span, "non-ADT passed to check_struct_or_variant_fields")
3045 let variant = adt_def.variant_with_id(variant_id);
3047 let mut remaining_fields = FnvHashMap();
3048 for field in &variant.fields {
3049 remaining_fields.insert(field.name, field);
3052 let mut error_happened = false;
3054 // Typecheck each field.
3055 for field in ast_fields {
3056 let expected_field_type;
3058 if let Some(v_field) = remaining_fields.remove(&field.ident.node.name) {
3059 expected_field_type = fcx.field_ty(field.span, v_field, substs);
3061 error_happened = true;
3062 expected_field_type = tcx.types.err;
3063 if let Some(_) = variant.find_field_named(field.ident.node.name) {
3064 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3065 "field `{}` specified more than once",
3068 report_unknown_field(fcx, adt_ty, variant, field, ast_fields);
3072 // Make sure to give a type to the field even if there's
3073 // an error, so we can continue typechecking
3074 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3077 // Make sure the programmer specified all the fields.
3078 if check_completeness &&
3080 !remaining_fields.is_empty()
3082 error_happened = true;
3083 span_err!(tcx.sess, span, E0063,
3084 "missing field{}: {}",
3085 if remaining_fields.len() == 1 {""} else {"s"},
3086 remaining_fields.keys()
3087 .map(|n| format!("`{}`", n))
3088 .collect::<Vec<_>>()
3092 if error_happened { Err(()) } else { Ok(()) }
3095 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3097 span: codemap::Span,
3098 struct_def: ty::AdtDef<'tcx>,
3099 fields: &'tcx [ast::Field],
3100 base_expr: Option<&'tcx ast::Expr>) {
3101 let tcx = fcx.ccx.tcx;
3103 // Generate the struct type.
3105 ty: mut struct_type,
3107 } = fcx.instantiate_type(span, struct_def.did);
3109 // Look up and check the fields.
3110 let res = check_struct_or_variant_fields(fcx,
3115 base_expr.is_none());
3117 struct_type = tcx.types.err;
3120 // Check the base expression if necessary.
3123 Some(base_expr) => {
3124 check_expr_has_type(fcx, &*base_expr, struct_type);
3128 // Write in the resulting type.
3129 fcx.write_ty(id, struct_type);
3132 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3134 span: codemap::Span,
3135 enum_id: ast::DefId,
3136 variant_id: ast::DefId,
3137 fields: &'tcx [ast::Field]) {
3138 // Look up the number of type parameters and the raw type, and
3139 // determine whether the enum is region-parameterized.
3143 } = fcx.instantiate_type(span, enum_id);
3145 // Look up and check the enum variant fields.
3146 let _ = check_struct_or_variant_fields(fcx,
3152 fcx.write_ty(id, enum_type);
3155 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3157 fields: &'tcx [ast::Field],
3158 base_expr: &'tcx Option<P<ast::Expr>>) {
3159 // Make sure to still write the types
3160 // otherwise we might ICE
3161 fcx.write_error(id);
3162 for field in fields {
3163 check_expr(fcx, &*field.expr);
3166 Some(ref base) => check_expr(fcx, &**base),
3171 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3173 let tcx = fcx.ccx.tcx;
3176 ast::ExprBox(ref opt_place, ref subexpr) => {
3177 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3178 check_expr(fcx, &**subexpr);
3180 let mut checked = false;
3181 opt_place.as_ref().map(|place| match place.node {
3182 ast::ExprPath(None, ref path) => {
3183 // FIXME(pcwalton): For now we hardcode the only permissible
3184 // place: the exchange heap.
3185 let definition = lookup_full_def(tcx, path.span, place.id);
3186 let def_id = definition.def_id();
3187 let referent_ty = fcx.expr_ty(&**subexpr);
3188 if tcx.lang_items.exchange_heap() == Some(def_id) {
3189 fcx.write_ty(id, tcx.mk_box(referent_ty));
3197 span_err!(tcx.sess, expr.span, E0066,
3198 "only the exchange heap is currently supported");
3199 fcx.write_ty(id, tcx.types.err);
3203 ast::ExprLit(ref lit) => {
3204 let typ = check_lit(fcx, &**lit, expected);
3205 fcx.write_ty(id, typ);
3207 ast::ExprBinary(op, ref lhs, ref rhs) => {
3208 op::check_binop(fcx, expr, op, lhs, rhs);
3210 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3211 op::check_binop_assign(fcx, expr, op, lhs, rhs);
3213 ast::ExprUnary(unop, ref oprnd) => {
3214 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3216 ast::UnUniq => match ty.sty {
3218 Expectation::rvalue_hint(tcx, ty)
3224 ast::UnNot | ast::UnNeg => {
3232 let lvalue_pref = match unop {
3233 ast::UnDeref => lvalue_pref,
3236 check_expr_with_expectation_and_lvalue_pref(
3237 fcx, &**oprnd, expected_inner, lvalue_pref);
3238 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3240 if !oprnd_t.references_error() {
3243 oprnd_t = tcx.mk_box(oprnd_t);
3246 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3247 oprnd_t = match oprnd_t.builtin_deref(true) {
3249 None => match try_overloaded_deref(fcx, expr.span,
3250 Some(MethodCall::expr(expr.id)),
3251 Some(&**oprnd), oprnd_t, lvalue_pref) {
3254 fcx.type_error_message(expr.span, |actual| {
3255 format!("type `{}` cannot be \
3256 dereferenced", actual)
3264 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3266 if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
3267 oprnd_t = op::check_user_unop(fcx, "!", "not",
3268 tcx.lang_items.not_trait(),
3269 expr, &**oprnd, oprnd_t, unop);
3273 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3275 if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
3276 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3277 tcx.lang_items.neg_trait(),
3278 expr, &**oprnd, oprnd_t, unop);
3283 fcx.write_ty(id, oprnd_t);
3285 ast::ExprAddrOf(mutbl, ref oprnd) => {
3286 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3288 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
3289 if fcx.tcx().expr_is_lval(&**oprnd) {
3290 // Lvalues may legitimately have unsized types.
3291 // For example, dereferences of a fat pointer and
3292 // the last field of a struct can be unsized.
3293 ExpectHasType(mt.ty)
3295 Expectation::rvalue_hint(tcx, mt.ty)
3301 let lvalue_pref = LvaluePreference::from_mutbl(mutbl);
3302 check_expr_with_expectation_and_lvalue_pref(fcx,
3307 let tm = ty::TypeAndMut { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3308 let oprnd_t = if tm.ty.references_error() {
3311 // Note: at this point, we cannot say what the best lifetime
3312 // is to use for resulting pointer. We want to use the
3313 // shortest lifetime possible so as to avoid spurious borrowck
3314 // errors. Moreover, the longest lifetime will depend on the
3315 // precise details of the value whose address is being taken
3316 // (and how long it is valid), which we don't know yet until type
3317 // inference is complete.
3319 // Therefore, here we simply generate a region variable. The
3320 // region inferencer will then select the ultimate value.
3321 // Finally, borrowck is charged with guaranteeing that the
3322 // value whose address was taken can actually be made to live
3323 // as long as it needs to live.
3324 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3325 tcx.mk_ref(tcx.mk_region(region), tm)
3327 fcx.write_ty(id, oprnd_t);
3329 ast::ExprPath(ref maybe_qself, ref path) => {
3330 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3331 fcx.to_ty(&qself.ty)
3334 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3336 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3337 // Create some fake resolution that can't possibly be a type.
3338 def::PathResolution {
3339 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3340 last_private: LastMod(AllPublic),
3341 depth: path.segments.len()
3344 tcx.sess.span_bug(expr.span,
3345 &format!("unbound path {:?}", expr))
3348 if let Some((opt_ty, segments, def)) =
3349 resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
3350 expr.span, expr.id) {
3351 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
3354 instantiate_path(fcx,
3364 // We always require that the type provided as the value for
3365 // a type parameter outlives the moment of instantiation.
3366 constrain_path_type_parameters(fcx, expr);
3368 ast::ExprInlineAsm(ref ia) => {
3369 for &(_, ref input) in &ia.inputs {
3370 check_expr(fcx, &**input);
3372 for &(_, ref out, _) in &ia.outputs {
3373 check_expr(fcx, &**out);
3377 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3378 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3379 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3380 ast::ExprRet(ref expr_opt) => {
3382 ty::FnConverging(result_type) => {
3385 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3386 result_type, fcx.tcx().mk_nil()) {
3387 span_err!(tcx.sess, expr.span, E0069,
3388 "`return;` in a function whose return type is \
3392 check_expr_coercable_to_type(fcx, &**e, result_type);
3396 ty::FnDiverging => {
3397 if let Some(ref e) = *expr_opt {
3398 check_expr(fcx, &**e);
3400 span_err!(tcx.sess, expr.span, E0166,
3401 "`return` in a function declared as diverging");
3404 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3406 ast::ExprParen(ref a) => {
3407 check_expr_with_expectation_and_lvalue_pref(fcx,
3411 fcx.write_ty(id, fcx.expr_ty(&**a));
3413 ast::ExprAssign(ref lhs, ref rhs) => {
3414 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3416 let tcx = fcx.tcx();
3417 if !tcx.expr_is_lval(&**lhs) {
3418 span_err!(tcx.sess, expr.span, E0070,
3419 "invalid left-hand side expression");
3422 let lhs_ty = fcx.expr_ty(&**lhs);
3423 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3424 let rhs_ty = fcx.expr_ty(&**rhs);
3426 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3428 if lhs_ty.references_error() || rhs_ty.references_error() {
3429 fcx.write_error(id);
3434 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3435 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3436 id, expr.span, expected);
3438 ast::ExprIfLet(..) => {
3439 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3441 ast::ExprWhile(ref cond, ref body, _) => {
3442 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3443 check_block_no_value(fcx, &**body);
3444 let cond_ty = fcx.expr_ty(&**cond);
3445 let body_ty = fcx.node_ty(body.id);
3446 if cond_ty.references_error() || body_ty.references_error() {
3447 fcx.write_error(id);
3453 ast::ExprWhileLet(..) => {
3454 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3456 ast::ExprForLoop(..) => {
3457 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3459 ast::ExprLoop(ref body, _) => {
3460 check_block_no_value(fcx, &**body);
3461 if !may_break(tcx, expr.id, &**body) {
3462 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3467 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3468 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3470 ast::ExprClosure(capture, ref decl, ref body) => {
3471 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3473 ast::ExprBlock(ref b) => {
3474 check_block_with_expected(fcx, &**b, expected);
3475 fcx.write_ty(id, fcx.node_ty(b.id));
3477 ast::ExprCall(ref callee, ref args) => {
3478 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3480 ast::ExprMethodCall(ident, ref tps, ref args) => {
3481 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3482 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3483 let args_err = arg_tys.fold(false,
3485 rest_err || a.references_error()});
3487 fcx.write_error(id);
3490 ast::ExprCast(ref e, ref t) => {
3491 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3492 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3495 // Find the type of `e`. Supply hints based on the type we are casting to,
3497 let t_cast = fcx.to_ty(t);
3498 let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
3499 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
3500 let t_expr = fcx.expr_ty(e);
3502 // Eagerly check for some obvious errors.
3503 if t_expr.references_error() {
3504 fcx.write_error(id);
3505 } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
3506 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
3508 // Write a type for the whole expression, assuming everything is going
3510 fcx.write_ty(id, t_cast);
3512 // Defer other checks until we're done type checking.
3513 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3514 let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
3515 deferred_cast_checks.push(cast_check);
3518 ast::ExprVec(ref args) => {
3519 let uty = expected.to_option(fcx).and_then(|uty| {
3521 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3526 let typ = match uty {
3529 check_expr_coercable_to_type(fcx, &**e, uty);
3534 let t: Ty = fcx.infcx().next_ty_var();
3536 check_expr_has_type(fcx, &**e, t);
3541 let typ = tcx.mk_array(typ, args.len());
3542 fcx.write_ty(id, typ);
3544 ast::ExprRepeat(ref element, ref count_expr) => {
3545 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3546 let count = fcx.tcx().eval_repeat_count(&**count_expr);
3548 let uty = match expected {
3549 ExpectHasType(uty) => {
3551 ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
3558 let (element_ty, t) = match uty {
3560 check_expr_coercable_to_type(fcx, &**element, uty);
3564 let t: Ty = fcx.infcx().next_ty_var();
3565 check_expr_has_type(fcx, &**element, t);
3566 (fcx.expr_ty(&**element), t)
3571 // For [foo, ..n] where n > 1, `foo` must have
3573 fcx.require_type_meets(
3580 if element_ty.references_error() {
3581 fcx.write_error(id);
3583 let t = tcx.mk_array(t, count);
3584 fcx.write_ty(id, t);
3587 ast::ExprTup(ref elts) => {
3588 let flds = expected.only_has_type(fcx).and_then(|ty| {
3590 ty::TyTuple(ref flds) => Some(&flds[..]),
3594 let mut err_field = false;
3596 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3597 let t = match flds {
3598 Some(ref fs) if i < fs.len() => {
3600 check_expr_coercable_to_type(fcx, &**e, ety);
3604 check_expr_with_expectation(fcx, &**e, NoExpectation);
3608 err_field = err_field || t.references_error();
3612 fcx.write_error(id);
3614 let typ = tcx.mk_tup(elt_ts);
3615 fcx.write_ty(id, typ);
3618 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3619 // Resolve the path.
3620 let def = lookup_full_def(tcx, path.span, id);
3621 let struct_id = match def {
3622 def::DefVariant(enum_id, variant_id, true) => {
3623 if let &Some(ref base_expr) = base_expr {
3624 span_err!(tcx.sess, base_expr.span, E0436,
3625 "functional record update syntax requires a struct");
3626 fcx.write_error(base_expr.id);
3628 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3629 variant_id, &fields[..]);
3632 def::DefTrait(def_id) => {
3633 span_err!(tcx.sess, path.span, E0159,
3634 "use of trait `{}` as a struct constructor",
3635 pprust::path_to_string(path));
3636 check_struct_fields_on_error(fcx,
3643 // Verify that this was actually a struct.
3644 let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
3646 ty::TyStruct(struct_def, _) => {
3647 check_struct_constructor(fcx,
3652 base_expr.as_ref().map(|e| &**e));
3655 span_err!(tcx.sess, path.span, E0071,
3656 "`{}` does not name a structure",
3657 pprust::path_to_string(path));
3658 check_struct_fields_on_error(fcx,
3669 // Turn the path into a type and verify that that type unifies with
3670 // the resulting structure type. This is needed to handle type
3671 // parameters correctly.
3672 let actual_structure_type = fcx.expr_ty(&*expr);
3673 if !actual_structure_type.references_error() {
3674 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3675 match fcx.mk_subty(false,
3676 infer::Misc(path.span),
3677 actual_structure_type,
3678 type_and_substs.ty) {
3680 Err(type_error) => {
3681 span_err!(fcx.tcx().sess, path.span, E0235,
3682 "structure constructor specifies a \
3683 structure of type `{}`, but this \
3684 structure has type `{}`: {}",
3686 .ty_to_string(type_and_substs.ty),
3689 actual_structure_type),
3691 tcx.note_and_explain_type_err(&type_error, path.span);
3696 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3698 ast::ExprField(ref base, ref field) => {
3699 check_field(fcx, expr, lvalue_pref, &**base, field);
3701 ast::ExprTupField(ref base, idx) => {
3702 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3704 ast::ExprIndex(ref base, ref idx) => {
3705 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3706 check_expr(fcx, &**idx);
3708 let base_t = fcx.expr_ty(&**base);
3709 let idx_t = fcx.expr_ty(&**idx);
3711 if base_t.references_error() {
3712 fcx.write_ty(id, base_t);
3713 } else if idx_t.references_error() {
3714 fcx.write_ty(id, idx_t);
3716 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3717 match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3718 Some((index_ty, element_ty)) => {
3719 let idx_expr_ty = fcx.expr_ty(idx);
3720 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3721 fcx.write_ty(id, element_ty);
3724 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3725 fcx.type_error_message(
3728 format!("cannot index a value of type `{}`",
3733 fcx.write_ty(id, fcx.tcx().types.err);
3738 ast::ExprRange(ref start, ref end) => {
3739 let t_start = start.as_ref().map(|e| {
3740 check_expr(fcx, &**e);
3743 let t_end = end.as_ref().map(|e| {
3744 check_expr(fcx, &**e);
3748 let idx_type = match (t_start, t_end) {
3749 (Some(ty), None) | (None, Some(ty)) => {
3752 (Some(t_start), Some(t_end)) if (t_start.references_error() ||
3753 t_end.references_error()) => {
3754 Some(fcx.tcx().types.err)
3756 (Some(t_start), Some(t_end)) => {
3757 Some(infer::common_supertype(fcx.infcx(),
3758 infer::RangeExpression(expr.span),
3766 // Note that we don't check the type of start/end satisfy any
3767 // bounds because right now the range structs do not have any. If we add
3768 // some bounds, then we'll need to check `t_start` against them here.
3770 let range_type = match idx_type {
3771 Some(idx_type) if idx_type.references_error() => {
3775 // Find the did from the appropriate lang item.
3776 let did = match (start, end) {
3777 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3778 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3779 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3781 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3785 if let Some(did) = did {
3786 let def = tcx.lookup_adt_def(did);
3787 let predicates = tcx.lookup_predicates(did);
3788 let substs = Substs::new_type(vec![idx_type], vec![]);
3789 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
3790 fcx.add_obligations_for_parameters(
3791 traits::ObligationCause::new(expr.span,
3793 traits::ItemObligation(did)),
3796 tcx.mk_struct(def, tcx.mk_substs(substs))
3798 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
3803 // Neither start nor end => RangeFull
3804 if let Some(did) = tcx.lang_items.range_full_struct() {
3806 tcx.lookup_adt_def(did),
3807 tcx.mk_substs(Substs::empty())
3810 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
3816 fcx.write_ty(id, range_type);
3821 debug!("type of expr({}) {} is...", expr.id,
3822 syntax::print::pprust::expr_to_string(expr));
3823 debug!("... {:?}, expected is {:?}",
3830 pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
3831 path_res: def::PathResolution,
3832 opt_self_ty: Option<Ty<'tcx>>,
3833 path: &'a ast::Path,
3835 node_id: ast::NodeId)
3836 -> Option<(Option<Ty<'tcx>>,
3837 &'a [ast::PathSegment],
3841 // Associated constants can't depend on generic types.
3842 fn have_disallowed_generic_consts<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3846 node_id: ast::NodeId) -> bool {
3848 def::DefAssociatedConst(..) => {
3849 if ty.has_param_types() || ty.has_self_ty() {
3850 span_err!(fcx.sess(), span, E0329,
3851 "Associated consts cannot depend \
3852 on type parameters or Self.");
3853 fcx.write_error(node_id);
3862 // If fully resolved already, we don't have to do anything.
3863 if path_res.depth == 0 {
3864 if let Some(ty) = opt_self_ty {
3865 if have_disallowed_generic_consts(fcx, path_res.full_def(), ty,
3870 Some((opt_self_ty, &path.segments, path_res.base_def))
3872 let mut def = path_res.base_def;
3873 let ty_segments = path.segments.split_last().unwrap().1;
3874 let base_ty_end = path.segments.len() - path_res.depth;
3875 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
3876 PathParamMode::Optional,
3879 &ty_segments[..base_ty_end],
3880 &ty_segments[base_ty_end..]);
3881 let item_segment = path.segments.last().unwrap();
3882 let item_name = item_segment.identifier.name;
3883 match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
3885 if have_disallowed_generic_consts(fcx, def, ty, span, node_id) {
3888 // Write back the new resolution.
3889 fcx.ccx.tcx.def_map.borrow_mut()
3890 .insert(node_id, def::PathResolution {
3892 last_private: path_res.last_private.or(lp),
3895 Some((Some(ty), slice::ref_slice(item_segment), def))
3898 method::report_error(fcx, span, ty,
3899 item_name, None, error);
3900 fcx.write_error(node_id);
3907 fn constrain_path_type_parameters(fcx: &FnCtxt,
3910 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3911 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3915 impl<'tcx> Expectation<'tcx> {
3916 /// Provide an expectation for an rvalue expression given an *optional*
3917 /// hint, which is not required for type safety (the resulting type might
3918 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3919 /// is useful in determining the concrete type.
3921 /// The primary use case is where the expected type is a fat pointer,
3922 /// like `&[isize]`. For example, consider the following statement:
3924 /// let x: &[isize] = &[1, 2, 3];
3926 /// In this case, the expected type for the `&[1, 2, 3]` expression is
3927 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3928 /// expectation `ExpectHasType([isize])`, that would be too strong --
3929 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3930 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3931 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3932 /// which still is useful, because it informs integer literals and the like.
3933 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3934 /// for examples of where this comes up,.
3935 fn rvalue_hint(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
3936 match tcx.struct_tail(ty).sty {
3937 ty::TySlice(_) | ty::TyTrait(..) => {
3938 ExpectRvalueLikeUnsized(ty)
3940 _ => ExpectHasType(ty)
3944 // Resolves `expected` by a single level if it is a variable. If
3945 // there is no expected type or resolution is not possible (e.g.,
3946 // no constraints yet present), just returns `None`.
3947 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3952 ExpectCastableToType(t) => {
3953 ExpectCastableToType(
3954 fcx.infcx().resolve_type_vars_if_possible(&t))
3956 ExpectHasType(t) => {
3958 fcx.infcx().resolve_type_vars_if_possible(&t))
3960 ExpectRvalueLikeUnsized(t) => {
3961 ExpectRvalueLikeUnsized(
3962 fcx.infcx().resolve_type_vars_if_possible(&t))
3967 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3968 match self.resolve(fcx) {
3969 NoExpectation => None,
3970 ExpectCastableToType(ty) |
3972 ExpectRvalueLikeUnsized(ty) => Some(ty),
3976 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3977 match self.resolve(fcx) {
3978 ExpectHasType(ty) => Some(ty),
3984 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3985 local: &'tcx ast::Local,
3986 init: &'tcx ast::Expr)
3988 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
3990 let local_ty = fcx.local_ty(init.span, local.id);
3991 if let Some(m) = ref_bindings {
3992 // Somewhat subtle: if we have a `ref` binding in the pattern,
3993 // we want to avoid introducing coercions for the RHS. This is
3994 // both because it helps preserve sanity and, in the case of
3995 // ref mut, for soundness (issue #23116). In particular, in
3996 // the latter case, we need to be clear that the type of the
3997 // referent for the reference that results is *equal to* the
3998 // type of the lvalue it is referencing, and not some
3999 // supertype thereof.
4000 check_expr_with_lvalue_pref(fcx, init, LvaluePreference::from_mutbl(m));
4001 let init_ty = fcx.expr_ty(init);
4002 demand::eqtype(fcx, init.span, init_ty, local_ty);
4004 check_expr_coercable_to_type(fcx, init, local_ty)
4008 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
4009 let tcx = fcx.ccx.tcx;
4011 let t = fcx.local_ty(local.span, local.id);
4012 fcx.write_ty(local.id, t);
4014 if let Some(ref init) = local.init {
4015 check_decl_initializer(fcx, local, &**init);
4016 let init_ty = fcx.expr_ty(&**init);
4017 if init_ty.references_error() {
4018 fcx.write_ty(local.id, init_ty);
4022 let pcx = pat_ctxt {
4024 map: pat_id_map(&tcx.def_map, &*local.pat),
4026 _match::check_pat(&pcx, &*local.pat, t);
4027 let pat_ty = fcx.node_ty(local.pat.id);
4028 if pat_ty.references_error() {
4029 fcx.write_ty(local.id, pat_ty);
4033 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4035 let mut saw_bot = false;
4036 let mut saw_err = false;
4038 ast::StmtDecl(ref decl, id) => {
4041 ast::DeclLocal(ref l) => {
4042 check_decl_local(fcx, &**l);
4043 let l_t = fcx.node_ty(l.id);
4044 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4045 saw_err = saw_err || l_t.references_error();
4047 ast::DeclItem(_) => {/* ignore for now */ }
4050 ast::StmtExpr(ref expr, id) => {
4052 // Check with expected type of ()
4053 check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
4054 let expr_ty = fcx.expr_ty(&**expr);
4055 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4056 saw_err = saw_err || expr_ty.references_error();
4058 ast::StmtSemi(ref expr, id) => {
4060 check_expr(fcx, &**expr);
4061 let expr_ty = fcx.expr_ty(&**expr);
4062 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4063 saw_err |= expr_ty.references_error();
4065 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4068 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4071 fcx.write_error(node_id);
4074 fcx.write_nil(node_id)
4078 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4079 check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
4080 let blkty = fcx.node_ty(blk.id);
4081 if blkty.references_error() {
4082 fcx.write_error(blk.id);
4084 let nilty = fcx.tcx().mk_nil();
4085 demand::suptype(fcx, blk.span, nilty, blkty);
4089 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4090 blk: &'tcx ast::Block,
4091 expected: Expectation<'tcx>) {
4093 let mut fcx_ps = fcx.ps.borrow_mut();
4094 let unsafety_state = fcx_ps.recurse(blk);
4095 replace(&mut *fcx_ps, unsafety_state)
4098 let mut warned = false;
4099 let mut any_diverges = false;
4100 let mut any_err = false;
4101 for s in &blk.stmts {
4102 check_stmt(fcx, &**s);
4103 let s_id = ast_util::stmt_id(&**s);
4104 let s_ty = fcx.node_ty(s_id);
4105 if any_diverges && !warned && match s.node {
4106 ast::StmtDecl(ref decl, _) => {
4108 ast::DeclLocal(_) => true,
4112 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4118 .add_lint(lint::builtin::UNREACHABLE_CODE,
4121 "unreachable statement".to_string());
4124 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4125 any_err = any_err || s_ty.references_error();
4128 None => if any_err {
4129 fcx.write_error(blk.id);
4130 } else if any_diverges {
4131 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4133 fcx.write_nil(blk.id);
4136 if any_diverges && !warned {
4140 .add_lint(lint::builtin::UNREACHABLE_CODE,
4143 "unreachable expression".to_string());
4145 let ety = match expected {
4146 ExpectHasType(ety) => {
4147 check_expr_coercable_to_type(fcx, &**e, ety);
4151 check_expr_with_expectation(fcx, &**e, expected);
4157 fcx.write_error(blk.id);
4158 } else if any_diverges {
4159 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4161 fcx.write_ty(blk.id, ety);
4166 *fcx.ps.borrow_mut() = prev;
4169 /// Checks a constant appearing in a type. At the moment this is just the
4170 /// length expression in a fixed-length vector, but someday it might be
4171 /// extended to type-level numeric literals.
4172 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4173 expr: &'tcx ast::Expr,
4174 expected_type: Ty<'tcx>) {
4175 let tables = RefCell::new(ty::Tables::empty());
4176 let inh = static_inherited_fields(ccx, &tables);
4177 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4178 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4181 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4185 let tables = RefCell::new(ty::Tables::empty());
4186 let inh = static_inherited_fields(ccx, &tables);
4187 let rty = ccx.tcx.node_id_to_type(id);
4188 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4189 let declty = fcx.ccx.tcx.lookup_item_type(local_def(id)).ty;
4190 check_const_with_ty(&fcx, sp, e, declty);
4193 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4197 // Gather locals in statics (because of block expressions).
4198 // This is technically unnecessary because locals in static items are forbidden,
4199 // but prevents type checking from blowing up before const checking can properly
4201 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4203 check_expr_with_hint(fcx, e, declty);
4204 demand::coerce(fcx, e.span, declty, e);
4205 fcx.select_all_obligations_or_error();
4207 regionck::regionck_expr(fcx, e);
4208 writeback::resolve_type_vars_in_expr(fcx, e);
4211 /// Checks whether a type can be represented in memory. In particular, it
4212 /// identifies types that contain themselves without indirection through a
4213 /// pointer, which would mean their size is unbounded.
4214 pub fn check_representable(tcx: &ty::ctxt,
4216 item_id: ast::NodeId,
4217 designation: &str) -> bool {
4218 let rty = tcx.node_id_to_type(item_id);
4220 // Check that it is possible to represent this type. This call identifies
4221 // (1) types that contain themselves and (2) types that contain a different
4222 // recursive type. It is only necessary to throw an error on those that
4223 // contain themselves. For case 2, there must be an inner type that will be
4224 // caught by case 1.
4225 match rty.is_representable(tcx, sp) {
4226 ty::SelfRecursive => {
4227 span_err!(tcx.sess, sp, E0072, "invalid recursive {} type", designation);
4228 tcx.sess.fileline_help(sp, "wrap the inner value in a box to make it representable");
4231 ty::Representable | ty::ContainsRecursive => (),
4236 /// Checks whether a type can be constructed at runtime without
4237 /// an existing instance of that type.
4238 pub fn check_instantiable(tcx: &ty::ctxt,
4240 item_id: ast::NodeId) {
4241 let item_ty = tcx.node_id_to_type(item_id);
4242 if !item_ty.is_instantiable(tcx) &&
4243 !tcx.sess.features.borrow().static_recursion {
4244 emit_feature_err(&tcx.sess.parse_sess.span_diagnostic,
4247 "this type cannot be instantiated at runtime \
4248 without an instance of itself");
4252 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4253 let t = tcx.node_id_to_type(id);
4254 if t.needs_subst() {
4255 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4259 ty::TyStruct(def, substs) => {
4260 let fields = &def.struct_variant().fields;
4261 if fields.is_empty() {
4262 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4265 let e = fields[0].ty(tcx, substs);
4266 if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
4267 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4270 if !e.is_machine() {
4271 span_err!(tcx.sess, sp, E0077,
4272 "SIMD vector element type should be machine type");
4280 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4282 vs: &'tcx [P<ast::Variant>],
4285 fn disr_in_range(ccx: &CrateCtxt,
4287 disr: ty::Disr) -> bool {
4288 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4290 ast::TyU8 => disr as u8 as Disr == disr,
4291 ast::TyU16 => disr as u16 as Disr == disr,
4292 ast::TyU32 => disr as u32 as Disr == disr,
4293 ast::TyU64 => disr as u64 as Disr == disr,
4294 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4297 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4299 ast::TyI8 => disr as i8 as Disr == disr,
4300 ast::TyI16 => disr as i16 as Disr == disr,
4301 ast::TyI32 => disr as i32 as Disr == disr,
4302 ast::TyI64 => disr as i64 as Disr == disr,
4303 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4307 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4308 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4312 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4313 vs: &'tcx [P<ast::Variant>],
4315 hint: attr::ReprAttr) {
4316 #![allow(trivial_numeric_casts)]
4318 let rty = ccx.tcx.node_id_to_type(id);
4319 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4321 let tables = RefCell::new(ty::Tables::empty());
4322 let inh = static_inherited_fields(ccx, &tables);
4323 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
4325 let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint));
4327 if let Some(ref e) = v.node.disr_expr {
4328 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
4332 let def_id = local_def(id);
4334 let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
4335 for (v, variant) in vs.iter().zip(variants.iter()) {
4336 let current_disr_val = variant.disr_val;
4338 // Check for duplicate discriminant values
4339 match disr_vals.iter().position(|&x| x == current_disr_val) {
4341 span_err!(ccx.tcx.sess, v.span, E0081,
4342 "discriminant value `{}` already exists", disr_vals[i]);
4343 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].did.node),
4344 "conflicting discriminant here")
4348 // Check for unrepresentable discriminant values
4350 attr::ReprAny | attr::ReprExtern => (),
4351 attr::ReprInt(sp, ity) => {
4352 if !disr_in_range(ccx, ity, current_disr_val) {
4353 span_err!(ccx.tcx.sess, v.span, E0082,
4354 "discriminant value outside specified type");
4355 span_note!(ccx.tcx.sess, sp,
4356 "discriminant type specified here");
4359 attr::ReprPacked => {
4360 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4363 disr_vals.push(current_disr_val);
4367 let hint = *ccx.tcx.lookup_repr_hints(ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4368 .get(0).unwrap_or(&attr::ReprAny);
4370 if hint != attr::ReprAny && vs.len() <= 1 {
4372 span_err!(ccx.tcx.sess, sp, E0083,
4373 "unsupported representation for univariant enum");
4375 span_err!(ccx.tcx.sess, sp, E0084,
4376 "unsupported representation for zero-variant enum");
4380 do_check(ccx, vs, id, hint);
4382 check_representable(ccx.tcx, sp, id, "enum");
4383 check_instantiable(ccx.tcx, sp, id);
4386 // Returns the type parameter count and the type for the given definition.
4387 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4390 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4392 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4393 let typ = fcx.local_ty(sp, nid);
4394 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4395 ty::GenericPredicates::empty())
4397 def::DefFn(id, _) | def::DefMethod(id) |
4398 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4399 def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id) => {
4400 (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
4404 def::DefAssociatedTy(..) |
4406 def::DefTyParam(..) |
4408 def::DefForeignMod(..) |
4410 def::DefRegion(..) |
4412 def::DefSelfTy(..) => {
4413 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4418 // Instantiates the given path, which must refer to an item with the given
4419 // number of type parameters and type.
4420 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4421 segments: &[ast::PathSegment],
4422 type_scheme: TypeScheme<'tcx>,
4423 type_predicates: &ty::GenericPredicates<'tcx>,
4424 opt_self_ty: Option<Ty<'tcx>>,
4427 node_id: ast::NodeId) {
4428 debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
4434 // We need to extract the type parameters supplied by the user in
4435 // the path `path`. Due to the current setup, this is a bit of a
4436 // tricky-process; the problem is that resolve only tells us the
4437 // end-point of the path resolution, and not the intermediate steps.
4438 // Luckily, we can (at least for now) deduce the intermediate steps
4439 // just from the end-point.
4441 // There are basically four cases to consider:
4443 // 1. Reference to a *type*, such as a struct or enum:
4445 // mod a { struct Foo<T> { ... } }
4447 // Because we don't allow types to be declared within one
4448 // another, a path that leads to a type will always look like
4449 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4450 // that only the final segment can have type parameters, and
4451 // they are located in the TypeSpace.
4453 // *Note:* Generally speaking, references to types don't
4454 // actually pass through this function, but rather the
4455 // `ast_ty_to_ty` function in `astconv`. However, in the case
4456 // of struct patterns (and maybe literals) we do invoke
4457 // `instantiate_path` to get the general type of an instance of
4458 // a struct. (In these cases, there are actually no type
4459 // parameters permitted at present, but perhaps we will allow
4460 // them in the future.)
4462 // 1b. Reference to a enum variant or tuple-like struct:
4464 // struct foo<T>(...)
4465 // enum E<T> { foo(...) }
4467 // In these cases, the parameters are declared in the type
4470 // 2. Reference to a *fn item*:
4474 // In this case, the path will again always have the form
4475 // `a::b::foo::<T>` where only the final segment should have
4476 // type parameters. However, in this case, those parameters are
4477 // declared on a value, and hence are in the `FnSpace`.
4479 // 3. Reference to a *method*:
4481 // impl<A> SomeStruct<A> {
4485 // Here we can have a path like
4486 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4487 // may appear in two places. The penultimate segment,
4488 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4489 // final segment, `foo::<B>` contains parameters in fn space.
4491 // 4. Reference to an *associated const*:
4493 // impl<A> AnotherStruct<A> {
4494 // const FOO: B = BAR;
4497 // The path in this case will look like
4498 // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
4499 // only will have parameters in TypeSpace.
4501 // The first step then is to categorize the segments appropriately.
4503 assert!(!segments.is_empty());
4505 let mut ufcs_associated = None;
4506 let mut segment_spaces: Vec<_>;
4508 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4509 def::DefSelfTy(..) |
4510 def::DefStruct(..) |
4511 def::DefVariant(..) |
4513 def::DefAssociatedTy(..) |
4515 def::DefPrimTy(..) |
4516 def::DefTyParam(..) => {
4517 // Everything but the final segment should have no
4518 // parameters at all.
4519 segment_spaces = vec![None; segments.len() - 1];
4520 segment_spaces.push(Some(subst::TypeSpace));
4523 // Case 2. Reference to a top-level value.
4526 def::DefStatic(..) => {
4527 segment_spaces = vec![None; segments.len() - 1];
4528 segment_spaces.push(Some(subst::FnSpace));
4531 // Case 3. Reference to a method.
4532 def::DefMethod(def_id) => {
4533 let container = fcx.tcx().impl_or_trait_item(def_id).container();
4535 ty::TraitContainer(trait_did) => {
4536 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4538 ty::ImplContainer(_) => {}
4541 if segments.len() >= 2 {
4542 segment_spaces = vec![None; segments.len() - 2];
4543 segment_spaces.push(Some(subst::TypeSpace));
4544 segment_spaces.push(Some(subst::FnSpace));
4546 // `<T>::method` will end up here, and so can `T::method`.
4547 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4548 segment_spaces = vec![Some(subst::FnSpace)];
4549 ufcs_associated = Some((container, self_ty));
4553 def::DefAssociatedConst(def_id) => {
4554 let container = fcx.tcx().impl_or_trait_item(def_id).container();
4556 ty::TraitContainer(trait_did) => {
4557 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4559 ty::ImplContainer(_) => {}
4562 if segments.len() >= 2 {
4563 segment_spaces = vec![None; segments.len() - 2];
4564 segment_spaces.push(Some(subst::TypeSpace));
4565 segment_spaces.push(None);
4567 // `<T>::CONST` will end up here, and so can `T::CONST`.
4568 let self_ty = opt_self_ty.expect("UFCS sugared const missing Self");
4569 segment_spaces = vec![None];
4570 ufcs_associated = Some((container, self_ty));
4574 // Other cases. Various nonsense that really shouldn't show up
4575 // here. If they do, an error will have been reported
4576 // elsewhere. (I hope)
4578 def::DefForeignMod(..) |
4581 def::DefRegion(..) |
4583 def::DefUpvar(..) => {
4584 segment_spaces = vec![None; segments.len()];
4587 assert_eq!(segment_spaces.len(), segments.len());
4589 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4590 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4591 // type parameters are not mandatory.
4592 let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none();
4594 debug!("segment_spaces={:?}", segment_spaces);
4596 // Next, examine the definition, and determine how many type
4597 // parameters we expect from each space.
4598 let type_defs = &type_scheme.generics.types;
4599 let region_defs = &type_scheme.generics.regions;
4601 // Now that we have categorized what space the parameters for each
4602 // segment belong to, let's sort out the parameters that the user
4603 // provided (if any) into their appropriate spaces. We'll also report
4604 // errors if type parameters are provided in an inappropriate place.
4605 let mut substs = Substs::empty();
4606 for (opt_space, segment) in segment_spaces.iter().zip(segments) {
4609 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4610 NO_TPS | NO_REGIONS);
4614 push_explicit_parameters_from_segment_to_substs(fcx,
4624 if let Some(self_ty) = opt_self_ty {
4625 if type_defs.len(subst::SelfSpace) == 1 {
4626 substs.types.push(subst::SelfSpace, self_ty);
4630 // Now we have to compare the types that the user *actually*
4631 // provided against the types that were *expected*. If the user
4632 // did not provide any types, then we want to substitute inference
4633 // variables. If the user provided some types, we may still need
4634 // to add defaults. If the user provided *too many* types, that's
4636 for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
4637 adjust_type_parameters(fcx, span, space, type_defs,
4638 require_type_space, &mut substs);
4639 assert_eq!(substs.types.len(space), type_defs.len(space));
4641 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4642 assert_eq!(substs.regions().len(space), region_defs.len(space));
4645 // The things we are substituting into the type should not contain
4646 // escaping late-bound regions, and nor should the base type scheme.
4647 assert!(!substs.has_regions_escaping_depth(0));
4648 assert!(!type_scheme.has_escaping_regions());
4650 // Add all the obligations that are required, substituting and
4651 // normalized appropriately.
4652 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4653 fcx.add_obligations_for_parameters(
4654 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4657 // Substitute the values for the type parameters into the type of
4658 // the referenced item.
4659 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4662 if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated {
4663 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4664 // is inherent, there is no `Self` parameter, instead, the impl needs
4665 // type parameters, which we can infer by unifying the provided `Self`
4666 // with the substituted impl type.
4667 let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
4668 assert_eq!(substs.types.len(subst::TypeSpace),
4669 impl_scheme.generics.types.len(subst::TypeSpace));
4670 assert_eq!(substs.regions().len(subst::TypeSpace),
4671 impl_scheme.generics.regions.len(subst::TypeSpace));
4673 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4674 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4675 fcx.tcx().sess.span_bug(span,
4677 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
4683 fcx.write_ty(node_id, ty_substituted);
4684 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4687 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4688 /// parameters are provided, then reports an error and clears the output vector.
4690 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4691 /// use inference variables. This seems less likely to lead to derived errors.
4693 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4694 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4695 /// here because we can easily use the precise span of the N+1'th parameter.
4696 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4697 fcx: &FnCtxt<'a, 'tcx>,
4698 space: subst::ParamSpace,
4700 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4701 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4702 segment: &ast::PathSegment,
4703 substs: &mut Substs<'tcx>)
4705 match segment.parameters {
4706 ast::AngleBracketedParameters(ref data) => {
4707 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4708 fcx, space, type_defs, region_defs, data, substs);
4711 ast::ParenthesizedParameters(ref data) => {
4712 span_err!(fcx.tcx().sess, span, E0238,
4713 "parenthesized parameters may only be used with a trait");
4714 push_explicit_parenthesized_parameters_from_segment_to_substs(
4715 fcx, space, span, type_defs, data, substs);
4720 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4721 fcx: &FnCtxt<'a, 'tcx>,
4722 space: subst::ParamSpace,
4723 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4724 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4725 data: &ast::AngleBracketedParameterData,
4726 substs: &mut Substs<'tcx>)
4729 let type_count = type_defs.len(space);
4730 assert_eq!(substs.types.len(space), 0);
4731 for (i, typ) in data.types.iter().enumerate() {
4732 let t = fcx.to_ty(&**typ);
4734 substs.types.push(space, t);
4735 } else if i == type_count {
4736 span_err!(fcx.tcx().sess, typ.span, E0087,
4737 "too many type parameters provided: \
4738 expected at most {} parameter{}, \
4739 found {} parameter{}",
4741 if type_count == 1 {""} else {"s"},
4743 if data.types.len() == 1 {""} else {"s"});
4744 substs.types.truncate(space, 0);
4750 if !data.bindings.is_empty() {
4751 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4752 "unexpected binding of associated item in expression path \
4753 (only allowed in type paths)");
4757 let region_count = region_defs.len(space);
4758 assert_eq!(substs.regions().len(space), 0);
4759 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4760 let r = ast_region_to_region(fcx.tcx(), lifetime);
4761 if i < region_count {
4762 substs.mut_regions().push(space, r);
4763 } else if i == region_count {
4764 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4765 "too many lifetime parameters provided: \
4766 expected {} parameter{}, found {} parameter{}",
4768 if region_count == 1 {""} else {"s"},
4769 data.lifetimes.len(),
4770 if data.lifetimes.len() == 1 {""} else {"s"});
4771 substs.mut_regions().truncate(space, 0);
4779 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4780 /// but intended for `Foo(A,B) -> C` form. This expands to
4781 /// roughly the same thing as `Foo<(A,B),C>`. One important
4782 /// difference has to do with the treatment of anonymous
4783 /// regions, which are translated into bound regions (NYI).
4784 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4785 fcx: &FnCtxt<'a, 'tcx>,
4786 space: subst::ParamSpace,
4788 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4789 data: &ast::ParenthesizedParameterData,
4790 substs: &mut Substs<'tcx>)
4792 let type_count = type_defs.len(space);
4794 span_err!(fcx.tcx().sess, span, E0167,
4795 "parenthesized form always supplies 2 type parameters, \
4796 but only {} parameter(s) were expected",
4800 let input_tys: Vec<Ty> =
4801 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4803 let tuple_ty = fcx.tcx().mk_tup(input_tys);
4805 if type_count >= 1 {
4806 substs.types.push(space, tuple_ty);
4809 let output_ty: Option<Ty> =
4810 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4813 output_ty.unwrap_or(fcx.tcx().mk_nil());
4815 if type_count >= 2 {
4816 substs.types.push(space, output_ty);
4820 fn adjust_type_parameters<'a, 'tcx>(
4821 fcx: &FnCtxt<'a, 'tcx>,
4824 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4825 require_type_space: bool,
4826 substs: &mut Substs<'tcx>)
4828 let provided_len = substs.types.len(space);
4829 let desired = defs.get_slice(space);
4830 let required_len = desired.iter()
4831 .take_while(|d| d.default.is_none())
4834 debug!("adjust_type_parameters(space={:?}, \
4843 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4844 assert!(provided_len <= desired.len());
4846 // Nothing specified at all: supply inference variables for
4848 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4849 substs.types.replace(space, Vec::new());
4850 fcx.infcx().type_vars_for_defs(span, space, substs, &desired[..]);
4854 // Too few parameters specified: report an error and use Err
4856 if provided_len < required_len {
4858 if desired.len() != required_len { "at least " } else { "" };
4859 span_err!(fcx.tcx().sess, span, E0089,
4860 "too few type parameters provided: expected {}{} parameter{}, \
4861 found {} parameter{}",
4862 qualifier, required_len,
4863 if required_len == 1 {""} else {"s"},
4865 if provided_len == 1 {""} else {"s"});
4866 substs.types.replace(space, vec![fcx.tcx().types.err; desired.len()]);
4870 // Otherwise, add in any optional parameters that the user
4871 // omitted. The case of *too many* parameters is handled
4873 // push_explicit_parameters_from_segment_to_substs(). Note
4874 // that the *default* type are expressed in terms of all prior
4875 // parameters, so we have to substitute as we go with the
4876 // partial substitution that we have built up.
4877 for i in provided_len..desired.len() {
4878 let default = desired[i].default.unwrap();
4879 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4880 substs.types.push(space, default);
4882 assert_eq!(substs.types.len(space), desired.len());
4884 debug!("Final substs: {:?}", substs);
4887 fn adjust_region_parameters(
4891 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4892 substs: &mut Substs)
4894 let provided_len = substs.mut_regions().len(space);
4895 let desired = defs.get_slice(space);
4897 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4898 assert!(provided_len <= desired.len());
4900 // If nothing was provided, just use inference variables.
4901 if provided_len == 0 {
4902 substs.mut_regions().replace(
4904 fcx.infcx().region_vars_for_defs(span, desired));
4908 // If just the right number were provided, everybody is happy.
4909 if provided_len == desired.len() {
4913 // Otherwise, too few were provided. Report an error and then
4914 // use inference variables.
4915 span_err!(fcx.tcx().sess, span, E0090,
4916 "too few lifetime parameters provided: expected {} parameter{}, \
4917 found {} parameter{}",
4919 if desired.len() == 1 {""} else {"s"},
4921 if provided_len == 1 {""} else {"s"});
4923 substs.mut_regions().replace(
4925 fcx.infcx().region_vars_for_defs(span, desired));
4929 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4933 where F: Fn() -> Ty<'tcx>
4935 let mut ty = fcx.resolve_type_vars_if_possible(ty);
4938 let alternative = f();
4941 if alternative.is_ty_var() || alternative.references_error() {
4942 fcx.type_error_message(sp, |_actual| {
4943 "the type of this value must be known in this context".to_string()
4945 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4946 ty = fcx.tcx().types.err;
4948 demand::suptype(fcx, sp, alternative, ty);
4956 // Resolves `typ` by a single level if `typ` is a type variable. If no
4957 // resolution is possible, then an error is reported.
4958 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4963 structurally_resolve_type_or_else(fcx, sp, ty, || {
4968 // Returns true if b contains a break that can exit from b
4969 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4970 // First: is there an unlabeled break immediately
4972 (loop_query(&*b, |e| {
4974 ast::ExprBreak(None) => true,
4978 // Second: is there a labeled break with label
4979 // <id> nested anywhere inside the loop?
4980 (block_query(b, |e| {
4981 if let ast::ExprBreak(Some(_)) = e.node {
4982 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
4989 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4991 tps: &OwnedSlice<ast::TyParam>,
4993 debug!("check_bounds_are_used(n_tps={}, ty={:?})",
4996 // make a vector of booleans initially false, set to true when used
4997 if tps.is_empty() { return; }
4998 let mut tps_used = vec![false; tps.len()];
5000 for leaf_ty in ty.walk() {
5001 if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
5002 debug!("Found use of ty param num {}", idx);
5003 tps_used[idx as usize] = true;
5007 for (i, b) in tps_used.iter().enumerate() {
5009 span_err!(ccx.tcx.sess, span, E0091,
5010 "type parameter `{}` is unused",
5016 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
5017 /// and in libcore/intrinsics.rs
5018 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5019 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5020 let name = token::intern(&format!("P{}", n));
5021 ccx.tcx.mk_param(subst::FnSpace, n, name)
5025 let name = it.ident.name.as_str();
5026 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5027 let split : Vec<&str> = name.split('_').collect();
5028 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5030 //We only care about the operation here
5031 let (n_tps, inputs, output) = match split[1] {
5032 "cxchg" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
5036 "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
5038 "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5041 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5042 "min" | "umax" | "umin" => {
5043 (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
5046 "fence" | "singlethreadfence" => {
5047 (0, Vec::new(), tcx.mk_nil())
5050 span_err!(tcx.sess, it.span, E0092,
5051 "unrecognized atomic operation function: `{}`", op);
5055 (n_tps, inputs, ty::FnConverging(output))
5056 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5057 (0, Vec::new(), ty::FnDiverging)
5059 let (n_tps, inputs, output) = match &name[..] {
5060 "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
5062 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
5063 "size_of_val" | "min_align_of_val" => {
5065 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5068 ], ccx.tcx.types.usize)
5070 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
5071 "uninit" => (1, Vec::new(), param(ccx, 0)),
5072 "forget" => (1, vec!( param(ccx, 0) ), tcx.mk_nil()),
5073 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5074 "move_val_init" => {
5077 tcx.mk_mut_ptr(param(ccx, 0)),
5082 "drop_in_place" => {
5083 (1, vec![tcx.mk_mut_ptr(param(ccx, 0))], tcx.mk_nil())
5085 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5087 "type_name" => (1, Vec::new(), tcx.mk_static_str()),
5088 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5089 "offset" | "arith_offset" => {
5092 tcx.mk_ptr(ty::TypeAndMut {
5094 mutbl: ast::MutImmutable
5098 tcx.mk_ptr(ty::TypeAndMut {
5100 mutbl: ast::MutImmutable
5103 "copy" | "copy_nonoverlapping" => {
5106 tcx.mk_ptr(ty::TypeAndMut {
5108 mutbl: ast::MutImmutable
5110 tcx.mk_ptr(ty::TypeAndMut {
5112 mutbl: ast::MutMutable
5118 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5121 tcx.mk_ptr(ty::TypeAndMut {
5123 mutbl: ast::MutMutable
5125 tcx.mk_ptr(ty::TypeAndMut {
5127 mutbl: ast::MutImmutable
5133 "write_bytes" | "volatile_set_memory" => {
5136 tcx.mk_ptr(ty::TypeAndMut {
5138 mutbl: ast::MutMutable
5145 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5146 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5149 vec!( tcx.types.f32, tcx.types.i32 ),
5154 vec!( tcx.types.f64, tcx.types.i32 ),
5157 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5158 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5159 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5160 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5163 vec!( tcx.types.f32, tcx.types.f32 ),
5168 vec!( tcx.types.f64, tcx.types.f64 ),
5171 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5172 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5173 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5174 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5175 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5176 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5177 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5178 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5179 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5180 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5183 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5188 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5191 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5192 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5193 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5194 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5195 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5196 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5197 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5198 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5199 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5200 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5201 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5202 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5203 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5204 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5205 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5206 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5207 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5208 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5209 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5210 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5211 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5212 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5213 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5214 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5215 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5216 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5217 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5218 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5219 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5220 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5221 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5224 (1, vec!( tcx.mk_imm_ptr(param(ccx, 0)) ), param(ccx, 0)),
5226 (1, vec!( tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ), tcx.mk_nil()),
5228 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5229 (0, vec!(tcx.types.i8, tcx.types.i8),
5230 tcx.mk_tup(vec!(tcx.types.i8, tcx.types.bool))),
5232 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5233 (0, vec!(tcx.types.i16, tcx.types.i16),
5234 tcx.mk_tup(vec!(tcx.types.i16, tcx.types.bool))),
5236 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5237 (0, vec!(tcx.types.i32, tcx.types.i32),
5238 tcx.mk_tup(vec!(tcx.types.i32, tcx.types.bool))),
5240 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5241 (0, vec!(tcx.types.i64, tcx.types.i64),
5242 tcx.mk_tup(vec!(tcx.types.i64, tcx.types.bool))),
5244 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5245 (0, vec!(tcx.types.u8, tcx.types.u8),
5246 tcx.mk_tup(vec!(tcx.types.u8, tcx.types.bool))),
5248 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5249 (0, vec!(tcx.types.u16, tcx.types.u16),
5250 tcx.mk_tup(vec!(tcx.types.u16, tcx.types.bool))),
5252 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5253 (0, vec!(tcx.types.u32, tcx.types.u32),
5254 tcx.mk_tup(vec!(tcx.types.u32, tcx.types.bool))),
5256 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5257 (0, vec!(tcx.types.u64, tcx.types.u64),
5258 tcx.mk_tup(vec!(tcx.types.u64, tcx.types.bool))),
5260 "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
5261 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5263 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5264 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5266 "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
5268 "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
5270 "discriminant_value" => (1, vec![
5271 tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5273 param(ccx, 0))], tcx.types.u64),
5276 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
5277 let fn_ty = ty::BareFnTy {
5278 unsafety: ast::Unsafety::Normal,
5280 sig: ty::Binder(FnSig {
5281 inputs: vec![mut_u8],
5282 output: ty::FnOutput::FnConverging(tcx.mk_nil()),
5286 let fn_ty = tcx.mk_bare_fn(fn_ty);
5287 (0, vec![tcx.mk_fn(None, fn_ty), mut_u8], mut_u8)
5291 span_err!(tcx.sess, it.span, E0093,
5292 "unrecognized intrinsic function: `{}`", *other);
5296 (n_tps, inputs, ty::FnConverging(output))
5298 let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
5299 unsafety: ast::Unsafety::Unsafe,
5300 abi: abi::RustIntrinsic,
5301 sig: ty::Binder(FnSig {
5307 let i_ty = ccx.tcx.lookup_item_type(local_def(it.id));
5308 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5309 if i_n_tps != n_tps {
5310 span_err!(tcx.sess, it.span, E0094,
5311 "intrinsic has wrong number of type \
5312 parameters: found {}, expected {}",
5315 require_same_types(tcx,
5322 format!("intrinsic has wrong type: expected `{}`",