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::mem_categorization as mc;
91 use middle::mem_categorization::McResult;
92 use middle::pat_util::{self, pat_id_map};
93 use middle::privacy::{AllPublic, LastMod};
94 use middle::region::{self, CodeExtent};
95 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
96 use middle::traits::{self, report_fulfillment_errors};
97 use middle::ty::{FnSig, GenericPredicates, TypeScheme};
98 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
99 use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
100 use middle::ty::liberate_late_bound_regions;
101 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
102 use middle::ty_fold::{TypeFolder, TypeFoldable};
103 use rscope::RegionScope;
104 use session::Session;
105 use {CrateCtxt, lookup_full_def, require_same_types};
108 use util::common::{block_query, ErrorReported, indenter, loop_query};
109 use util::ppaux::{self, Repr};
110 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
111 use util::lev_distance::lev_distance;
113 use std::cell::{Cell, Ref, RefCell};
114 use std::mem::replace;
115 use std::iter::repeat;
117 use syntax::{self, abi, attr};
118 use syntax::attr::AttrMetaMethods;
119 use syntax::ast::{self, DefId, Visibility};
120 use syntax::ast_util::{self, local_def};
121 use syntax::codemap::{self, Span};
122 use syntax::feature_gate;
123 use syntax::owned_slice::OwnedSlice;
124 use syntax::parse::token;
125 use syntax::print::pprust;
127 use syntax::visit::{self, Visitor};
145 /// closures defined within the function. For example:
148 /// bar(move|| { ... })
151 /// Here, the function `foo()` and the closure passed to
152 /// `bar()` will each have their own `FnCtxt`, but they will
153 /// share the inherited fields.
154 pub struct Inherited<'a, 'tcx: 'a> {
155 infcx: infer::InferCtxt<'a, 'tcx>,
156 locals: RefCell<NodeMap<Ty<'tcx>>>,
157 param_env: ty::ParameterEnvironment<'a, 'tcx>,
160 node_types: RefCell<NodeMap<Ty<'tcx>>>,
161 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
162 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
163 method_map: MethodMap<'tcx>,
164 upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
165 closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
166 closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
167 object_cast_map: ObjectCastMap<'tcx>,
169 // A mapping from each fn's id to its signature, with all bound
170 // regions replaced with free ones. Unlike the other tables, this
171 // one is never copied into the tcx: it is only used by regionck.
172 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
174 // Tracks trait obligations incurred during this function body.
175 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
177 // When we process a call like `c()` where `c` is a closure type,
178 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
179 // `FnOnce` closure. In that case, we defer full resolution of the
180 // call until upvar inference can kick in and make the
181 // decision. We keep these deferred resolutions grouped by the
182 // def-id of the closure, so that once we decide, we can easily go
183 // back and process them.
184 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
186 deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
189 trait DeferredCallResolution<'tcx> {
190 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
193 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
195 /// When type-checking an expression, we propagate downward
196 /// whatever type hint we are able in the form of an `Expectation`.
197 #[derive(Copy, Clone)]
198 pub enum Expectation<'tcx> {
199 /// We know nothing about what type this expression should have.
202 /// This expression should have the type given (or some subtype)
203 ExpectHasType(Ty<'tcx>),
205 /// This expression will be cast to the `Ty`
206 ExpectCastableToType(Ty<'tcx>),
208 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
209 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
210 ExpectRvalueLikeUnsized(Ty<'tcx>),
213 impl<'tcx> Expectation<'tcx> {
214 // Disregard "castable to" expectations because they
215 // can lead us astray. Consider for example `if cond
216 // {22} else {c} as u8` -- if we propagate the
217 // "castable to u8" constraint to 22, it will pick the
218 // type 22u8, which is overly constrained (c might not
219 // be a u8). In effect, the problem is that the
220 // "castable to" expectation is not the tightest thing
221 // we can say, so we want to drop it in this case.
222 // The tightest thing we can say is "must unify with
223 // else branch". Note that in the case of a "has type"
224 // constraint, this limitation does not hold.
226 // If the expected type is just a type variable, then don't use
227 // an expected type. Otherwise, we might write parts of the type
228 // when checking the 'then' block which are incompatible with the
230 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
232 ExpectHasType(ety) => {
233 let ety = fcx.infcx().shallow_resolve(ety);
234 if !ty::type_is_ty_var(ety) {
240 ExpectRvalueLikeUnsized(ety) => {
241 ExpectRvalueLikeUnsized(ety)
248 #[derive(Copy, Clone)]
249 pub struct UnsafetyState {
250 pub def: ast::NodeId,
251 pub unsafety: ast::Unsafety,
256 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
257 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
260 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
261 match self.unsafety {
262 // If this unsafe, then if the outer function was already marked as
263 // unsafe we shouldn't attribute the unsafe'ness to the block. This
264 // way the block can be warned about instead of ignoring this
265 // extraneous block (functions are never warned about).
266 ast::Unsafety::Unsafe if self.from_fn => *self,
269 let (unsafety, def) = match blk.rules {
270 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
271 ast::DefaultBlock => (unsafety, self.def),
273 UnsafetyState{ def: def,
282 pub struct FnCtxt<'a, 'tcx: 'a> {
283 body_id: ast::NodeId,
285 // This flag is set to true if, during the writeback phase, we encounter
286 // a type error in this function.
287 writeback_errors: Cell<bool>,
289 // Number of errors that had been reported when we started
290 // checking this function. On exit, if we find that *more* errors
291 // have been reported, we will skip regionck and other work that
292 // expects the types within the function to be consistent.
293 err_count_on_creation: usize,
295 ret_ty: ty::FnOutput<'tcx>,
297 ps: RefCell<UnsafetyState>,
299 inh: &'a Inherited<'a, 'tcx>,
301 ccx: &'a CrateCtxt<'a, 'tcx>,
304 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
305 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
306 let ty = self.node_ty(id);
307 self.resolve_type_vars_or_error(&ty)
309 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
310 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
311 self.resolve_type_vars_or_error(&ty)
313 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
314 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
315 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
317 fn node_method_ty(&self, method_call: ty::MethodCall)
318 -> Option<Ty<'tcx>> {
319 self.inh.method_map.borrow()
321 .map(|method| method.ty)
322 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
324 fn node_method_origin(&self, method_call: ty::MethodCall)
325 -> Option<ty::MethodOrigin<'tcx>>
327 self.inh.method_map.borrow()
329 .map(|method| method.origin.clone())
331 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
332 &self.inh.adjustments
334 fn is_method_call(&self, id: ast::NodeId) -> bool {
335 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
337 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
338 self.param_env().temporary_scope(rvalue_id)
340 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
341 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
345 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
346 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
350 fn closure_kind(&self,
352 -> Option<ty::ClosureKind>
354 self.inh.closure_kinds.borrow().get(&def_id).cloned()
357 fn closure_type(&self,
359 substs: &subst::Substs<'tcx>)
360 -> ty::ClosureTy<'tcx>
362 self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs)
365 fn closure_upvars(&self,
367 substs: &Substs<'tcx>)
368 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
370 ty::closure_upvars(self, def_id, substs)
374 impl<'a, 'tcx> Inherited<'a, 'tcx> {
375 fn new(tcx: &'a ty::ctxt<'tcx>,
376 param_env: ty::ParameterEnvironment<'a, 'tcx>)
377 -> Inherited<'a, 'tcx> {
379 infcx: infer::new_infer_ctxt(tcx),
380 locals: RefCell::new(NodeMap()),
381 param_env: param_env,
382 node_types: RefCell::new(NodeMap()),
383 item_substs: RefCell::new(NodeMap()),
384 adjustments: RefCell::new(NodeMap()),
385 method_map: RefCell::new(FnvHashMap()),
386 object_cast_map: RefCell::new(NodeMap()),
387 upvar_capture_map: RefCell::new(FnvHashMap()),
388 closure_tys: RefCell::new(DefIdMap()),
389 closure_kinds: RefCell::new(DefIdMap()),
390 fn_sig_map: RefCell::new(NodeMap()),
391 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
392 deferred_call_resolutions: RefCell::new(DefIdMap()),
393 deferred_cast_checks: RefCell::new(Vec::new()),
397 fn normalize_associated_types_in<T>(&self,
398 typer: &ty::ClosureTyper<'tcx>,
400 body_id: ast::NodeId,
403 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
405 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
406 assoc::normalize_associated_types_in(&self.infcx,
408 &mut *fulfillment_cx, span,
415 // Used by check_const and check_enum_variants
416 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
417 inh: &'a Inherited<'a, 'tcx>,
418 rty: ty::FnOutput<'tcx>,
419 body_id: ast::NodeId)
420 -> FnCtxt<'a, 'tcx> {
423 writeback_errors: Cell::new(false),
424 err_count_on_creation: ccx.tcx.sess.err_count(),
426 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
432 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
433 -> Inherited<'a, 'tcx> {
434 // It's kind of a kludge to manufacture a fake function context
435 // and statement context, but we might as well do write the code only once
436 let param_env = ty::empty_parameter_environment(ccx.tcx);
437 Inherited::new(ccx.tcx, param_env)
440 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
441 struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
443 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
444 fn visit_item(&mut self, i: &'tcx ast::Item) {
445 check_item_type(self.ccx, i);
446 visit::walk_item(self, i);
449 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
451 ast::TyFixedLengthVec(_, ref expr) => {
452 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
457 visit::walk_ty(self, t);
461 impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
462 fn visit_item(&mut self, i: &'tcx ast::Item) {
463 check_item_body(self.ccx, i);
464 visit::walk_item(self, i);
468 pub fn check_item_types(ccx: &CrateCtxt) {
469 let krate = ccx.tcx.map.krate();
470 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
471 visit::walk_crate(&mut visit, krate);
473 // If types are not well-formed, it leads to all manner of errors
474 // downstream, so stop reporting errors at this point.
475 ccx.tcx.sess.abort_if_errors();
477 let mut visit = CheckItemTypesVisitor { ccx: ccx };
478 visit::walk_crate(&mut visit, krate);
480 ccx.tcx.sess.abort_if_errors();
482 let mut visit = CheckItemBodiesVisitor { ccx: ccx };
483 visit::walk_crate(&mut visit, krate);
485 ccx.tcx.sess.abort_if_errors();
487 for drop_method_did in ccx.tcx.destructors.borrow().iter() {
488 if drop_method_did.krate == ast::LOCAL_CRATE {
489 let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
490 match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
493 assert!(ccx.tcx.sess.has_errors());
499 ccx.tcx.sess.abort_if_errors();
502 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
503 decl: &'tcx ast::FnDecl,
504 body: &'tcx ast::Block,
508 param_env: ty::ParameterEnvironment<'a, 'tcx>)
511 ty::ty_bare_fn(_, ref fn_ty) => {
512 let inh = Inherited::new(ccx.tcx, param_env);
514 // Compute the fty from point of view of inside fn.
516 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
518 liberate_late_bound_regions(ccx.tcx,
519 region::DestructionScopeData::new(body.id),
522 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
524 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
525 decl, fn_id, body, &inh);
527 fcx.select_all_obligations_and_apply_defaults();
528 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
529 fcx.select_all_obligations_or_error();
532 fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
534 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
535 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
537 _ => ccx.tcx.sess.impossible_case(body.span,
538 "check_bare_fn: function type expected")
542 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
543 fcx: &'a FnCtxt<'a, 'tcx>
546 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
547 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
550 // infer the variable's type
551 let var_ty = self.fcx.infcx().next_ty_var();
552 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
556 // take type that the user specified
557 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
564 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
565 // Add explicitly-declared locals.
566 fn visit_local(&mut self, local: &'tcx ast::Local) {
567 let o_ty = match local.ty {
568 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
571 self.assign(local.span, local.id, o_ty);
572 debug!("Local variable {} is assigned type {}",
573 self.fcx.pat_to_string(&*local.pat),
574 self.fcx.infcx().ty_to_string(
575 self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
576 visit::walk_local(self, local);
579 // Add pattern bindings.
580 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
581 if let ast::PatIdent(_, ref path1, _) = p.node {
582 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
583 let var_ty = self.assign(p.span, p.id, None);
585 self.fcx.require_type_is_sized(var_ty, p.span,
586 traits::VariableType(p.id));
588 debug!("Pattern binding {} is assigned to {} with type {}",
589 token::get_ident(path1.node),
590 self.fcx.infcx().ty_to_string(
591 self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
592 var_ty.repr(self.fcx.tcx()));
595 visit::walk_pat(self, p);
598 fn visit_block(&mut self, b: &'tcx ast::Block) {
599 // non-obvious: the `blk` variable maps to region lb, so
600 // we have to keep this up-to-date. This
601 // is... unfortunate. It'd be nice to not need this.
602 visit::walk_block(self, b);
605 // Since an expr occurs as part of the type fixed size arrays we
606 // need to record the type for that node
607 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
609 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
610 self.visit_ty(&**ty);
611 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
613 _ => visit::walk_ty(self, t)
617 // Don't descend into fns and items
618 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
619 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
620 fn visit_item(&mut self, _: &ast::Item) { }
624 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
625 /// body and returns the function context used for that purpose, since in the case of a fn item
626 /// there is still a bit more to do.
629 /// * inherited: other fields inherited from the enclosing fn (if any)
630 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
631 unsafety: ast::Unsafety,
632 unsafety_id: ast::NodeId,
633 fn_sig: &ty::FnSig<'tcx>,
634 decl: &'tcx ast::FnDecl,
636 body: &'tcx ast::Block,
637 inherited: &'a Inherited<'a, 'tcx>)
641 let err_count_on_creation = tcx.sess.err_count();
643 let arg_tys = &fn_sig.inputs;
644 let ret_ty = fn_sig.output;
646 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
651 // Create the function context. This is either derived from scratch or,
652 // in the case of function expressions, based on the outer context.
655 writeback_errors: Cell::new(false),
656 err_count_on_creation: err_count_on_creation,
658 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
663 // Remember return type so that regionck can access it later.
664 let mut fn_sig_tys: Vec<Ty> =
669 if let ty::FnConverging(ret_ty) = ret_ty {
670 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
671 fn_sig_tys.push(ret_ty);
674 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
676 fn_sig_tys.repr(tcx));
678 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
681 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
683 // Add formal parameters.
684 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
685 // Create type variables for each argument.
686 pat_util::pat_bindings(
689 |_bm, pat_id, sp, _path| {
690 let var_ty = visit.assign(sp, pat_id, None);
691 fcx.require_type_is_sized(var_ty, sp,
692 traits::VariableType(pat_id));
695 // Check the pattern.
698 map: pat_id_map(&tcx.def_map, &*input.pat),
700 _match::check_pat(&pcx, &*input.pat, *arg_ty);
703 visit.visit_block(body);
706 check_block_with_expected(&fcx, body, match ret_ty {
707 ty::FnConverging(result_type) => ExpectHasType(result_type),
708 ty::FnDiverging => NoExpectation
711 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
712 fcx.write_ty(input.id, *arg);
718 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
721 check_representable(tcx, span, id, "struct");
722 check_instantiable(tcx, span, id);
724 if ty::lookup_simd(tcx, local_def(id)) {
725 check_simd(tcx, span, id);
729 pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
730 debug!("check_item_type(it.id={}, it.ident={})",
732 ty::item_path_str(ccx.tcx, local_def(it.id)));
733 let _indenter = indenter();
735 // Consts can play a role in type-checking, so they are included here.
736 ast::ItemStatic(_, _, ref e) |
737 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
738 ast::ItemEnum(ref enum_definition, _) => {
739 check_enum_variants(ccx,
741 &enum_definition.variants,
744 ast::ItemFn(_, _, _, _, _) => {} // entirely within check_item_body
745 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
746 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
747 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
748 Some(impl_trait_ref) => {
749 check_impl_items_against_trait(ccx,
757 ast::ItemTrait(_, ref generics, _, _) => {
758 check_trait_on_unimplemented(ccx, generics, it);
760 ast::ItemStruct(..) => {
761 check_struct(ccx, it.id, it.span);
763 ast::ItemTy(ref t, ref generics) => {
764 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
765 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
767 ast::ItemForeignMod(ref m) => {
768 if m.abi == abi::RustIntrinsic {
769 for item in &m.items {
770 check_intrinsic_type(ccx, &**item);
773 for item in &m.items {
774 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
775 if !pty.generics.types.is_empty() {
776 span_err!(ccx.tcx.sess, item.span, E0044,
777 "foreign items may not have type parameters");
780 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
781 if fn_decl.variadic && m.abi != abi::C {
782 span_err!(ccx.tcx.sess, item.span, E0045,
783 "variadic function must have C calling convention");
789 _ => {/* nothing to do */ }
793 pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
794 debug!("check_item_body(it.id={}, it.ident={})",
796 ty::item_path_str(ccx.tcx, local_def(it.id)));
797 let _indenter = indenter();
799 ast::ItemFn(ref decl, _, _, _, ref body) => {
800 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
801 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
802 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
804 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
805 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
807 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
809 for impl_item in impl_items {
810 match impl_item.node {
811 ast::ConstImplItem(_, ref expr) => {
812 check_const(ccx, impl_item.span, &*expr, impl_item.id)
814 ast::MethodImplItem(ref sig, ref body) => {
815 check_method_body(ccx, &impl_pty.generics, sig, body,
816 impl_item.id, impl_item.span);
818 ast::TypeImplItem(_) |
819 ast::MacImplItem(_) => {
820 // Nothing to do here.
825 ast::ItemTrait(_, _, _, ref trait_items) => {
826 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
827 for trait_item in trait_items {
828 match trait_item.node {
829 ast::ConstTraitItem(_, Some(ref expr)) => {
830 check_const(ccx, trait_item.span, &*expr, trait_item.id)
832 ast::MethodTraitItem(ref sig, Some(ref body)) => {
833 check_method_body(ccx, &trait_def.generics, sig, body,
834 trait_item.id, trait_item.span);
836 ast::ConstTraitItem(_, None) |
837 ast::MethodTraitItem(_, None) |
838 ast::TypeTraitItem(..) => {
844 _ => {/* nothing to do */ }
848 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
849 generics: &ast::Generics,
851 if let Some(ref attr) = item.attrs.iter().find(|a| {
852 a.check_name("rustc_on_unimplemented")
854 if let Some(ref istring) = attr.value_str() {
855 let parser = Parser::new(&istring);
856 let types = &*generics.ty_params;
857 for token in parser {
859 Piece::String(_) => (), // Normal string, no need to check it
860 Piece::NextArgument(a) => match a.position {
861 // `{Self}` is allowed
862 Position::ArgumentNamed(s) if s == "Self" => (),
863 // So is `{A}` if A is a type parameter
864 Position::ArgumentNamed(s) => match types.iter().find(|t| {
865 t.ident.as_str() == s
869 span_err!(ccx.tcx.sess, attr.span, E0230,
870 "there is no type parameter \
872 s, item.ident.as_str());
875 // `{:1}` and `{}` are not to be used
876 Position::ArgumentIs(_) | Position::ArgumentNext => {
877 span_err!(ccx.tcx.sess, attr.span, E0231,
878 "only named substitution \
879 parameters are allowed");
885 span_err!(ccx.tcx.sess, attr.span, E0232,
886 "this attribute must have a value, \
887 eg `#[rustc_on_unimplemented = \"foo\"]`")
892 /// Type checks a method body.
896 /// * `item_generics`: generics defined on the impl/trait that contains
898 /// * `self_bound`: bound for the `Self` type parameter, if any
899 /// * `method`: the method definition
900 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
901 item_generics: &ty::Generics<'tcx>,
902 sig: &'tcx ast::MethodSig,
903 body: &'tcx ast::Block,
904 id: ast::NodeId, span: Span) {
905 debug!("check_method_body(item_generics={}, id={})",
906 item_generics.repr(ccx.tcx), id);
907 let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
909 let fty = ty::node_id_to_type(ccx.tcx, id);
910 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
912 check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
915 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
917 impl_trait_ref: &ty::TraitRef<'tcx>,
918 impl_items: &[P<ast::ImplItem>]) {
919 // Locate trait methods
921 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
923 // Check existing impl methods to see if they are both present in trait
924 // and compatible with trait signature
925 for impl_item in impl_items {
926 match impl_item.node {
927 ast::ConstImplItem(..) => {
928 let impl_const_def_id = local_def(impl_item.id);
929 let impl_const_ty = ty::impl_or_trait_item(ccx.tcx,
932 // Find associated const definition.
933 let opt_associated_const =
935 .find(|ac| ac.name() == impl_const_ty.name());
936 match opt_associated_const {
937 Some(associated_const) => {
938 match (associated_const, &impl_const_ty) {
939 (&ty::ConstTraitItem(ref const_trait),
940 &ty::ConstTraitItem(ref const_impl)) => {
941 compare_const_impl(ccx.tcx,
948 span_err!(tcx.sess, impl_item.span, E0323,
949 "item `{}` is an associated const, \
950 which doesn't match its trait `{}`",
951 token::get_name(impl_const_ty.name()),
952 impl_trait_ref.repr(tcx))
957 // This is `span_bug` as it should have already been
958 // caught in resolve.
962 "associated const `{}` is not a member of \
964 token::get_name(impl_const_ty.name()),
965 impl_trait_ref.repr(tcx)));
969 ast::MethodImplItem(_, ref body) => {
970 let impl_method_def_id = local_def(impl_item.id);
971 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
974 // If this is an impl of a trait method, find the
975 // corresponding method definition in the trait.
976 let opt_trait_method_ty =
978 .find(|ti| ti.name() == impl_item_ty.name());
979 match opt_trait_method_ty {
980 Some(trait_method_ty) => {
981 match (trait_method_ty, &impl_item_ty) {
982 (&ty::MethodTraitItem(ref trait_method_ty),
983 &ty::MethodTraitItem(ref impl_method_ty)) => {
984 compare_impl_method(ccx.tcx,
992 span_err!(tcx.sess, impl_item.span, E0324,
993 "item `{}` is an associated method, \
994 which doesn't match its trait `{}`",
995 token::get_name(impl_item_ty.name()),
996 impl_trait_ref.repr(tcx))
1001 // This is span_bug as it should have already been
1002 // caught in resolve.
1005 &format!("method `{}` is not a member of trait `{}`",
1006 token::get_name(impl_item_ty.name()),
1007 impl_trait_ref.repr(tcx)));
1011 ast::TypeImplItem(_) => {
1012 let typedef_def_id = local_def(impl_item.id);
1013 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
1016 // If this is an impl of an associated type, find the
1017 // corresponding type definition in the trait.
1018 let opt_associated_type =
1020 .find(|ti| ti.name() == typedef_ty.name());
1021 match opt_associated_type {
1022 Some(associated_type) => {
1023 match (associated_type, &typedef_ty) {
1024 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
1026 span_err!(tcx.sess, impl_item.span, E0325,
1027 "item `{}` is an associated type, \
1028 which doesn't match its trait `{}`",
1029 token::get_name(typedef_ty.name()),
1030 impl_trait_ref.repr(tcx))
1035 // This is `span_bug` as it should have already been
1036 // caught in resolve.
1040 "associated type `{}` is not a member of \
1042 token::get_name(typedef_ty.name()),
1043 impl_trait_ref.repr(tcx)));
1047 ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
1052 // Check for missing items from trait
1053 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
1054 let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
1055 let mut missing_methods = Vec::new();
1056 for trait_item in &*trait_items {
1058 ty::ConstTraitItem(ref associated_const) => {
1059 let is_implemented = impl_items.iter().any(|ii| {
1061 ast::ConstImplItem(..) => {
1062 ii.ident.name == associated_const.name
1068 associated_consts.iter().any(|ac| ac.default.is_some() &&
1069 ac.name == associated_const.name);
1070 if !is_implemented && !is_provided {
1071 missing_methods.push(format!("`{}`",
1072 token::get_name(associated_const.name)));
1075 ty::MethodTraitItem(ref trait_method) => {
1076 let is_implemented =
1077 impl_items.iter().any(|ii| {
1079 ast::MethodImplItem(..) => {
1080 ii.ident.name == trait_method.name
1086 provided_methods.iter().any(|m| m.name == trait_method.name);
1087 if !is_implemented && !is_provided {
1088 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
1091 ty::TypeTraitItem(ref associated_type) => {
1092 let is_implemented = impl_items.iter().any(|ii| {
1094 ast::TypeImplItem(_) => {
1095 ii.ident.name == associated_type.name
1100 if !is_implemented {
1101 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1107 if !missing_methods.is_empty() {
1108 span_err!(tcx.sess, impl_span, E0046,
1109 "not all trait items implemented, missing: {}",
1110 missing_methods.connect(", "));
1114 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1121 let tstr = fcx.infcx().ty_to_string(t_cast);
1122 fcx.type_error_message(span, |actual| {
1123 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1126 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1127 let mtstr = match mt {
1128 ast::MutMutable => "mut ",
1129 ast::MutImmutable => ""
1131 if ty::type_is_trait(t_cast) {
1132 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1134 fcx.tcx().sess.span_suggestion(t_span,
1135 "try casting to a reference instead:",
1136 format!("&{}{}", mtstr, s));
1139 span_help!(fcx.tcx().sess, t_span,
1140 "did you mean `&{}{}`?", mtstr, tstr),
1143 span_help!(fcx.tcx().sess, span,
1144 "consider using an implicit coercion to `&{}{}` instead",
1148 ty::ty_uniq(..) => {
1149 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
1151 fcx.tcx().sess.span_suggestion(t_span,
1152 "try casting to a `Box` instead:",
1153 format!("Box<{}>", s));
1156 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr),
1160 span_help!(fcx.tcx().sess, e_span,
1161 "consider using a box or reference as appropriate");
1164 fcx.write_error(id);
1168 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1169 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1171 fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
1172 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
1174 Ok(ty::lookup_item_type(self.tcx(), id))
1177 fn get_trait_def(&self, _: Span, id: ast::DefId)
1178 -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
1180 Ok(ty::lookup_trait_def(self.tcx(), id))
1183 fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
1184 // all super predicates are ensured during collect pass
1188 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1189 Some(&self.inh.param_env.free_substs)
1192 fn get_type_parameter_bounds(&self,
1194 node_id: ast::NodeId)
1195 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1197 let def = self.tcx().type_parameter_def(node_id);
1198 let r = self.inh.param_env.caller_bounds
1200 .filter_map(|predicate| {
1202 ty::Predicate::Trait(ref data) => {
1203 if data.0.self_ty().is_param(def.space, def.index) {
1204 Some(data.to_poly_trait_ref())
1218 fn trait_defines_associated_type_named(&self,
1219 trait_def_id: ast::DefId,
1220 assoc_name: ast::Name)
1223 let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
1224 trait_def.associated_type_names.contains(&assoc_name)
1227 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1228 self.infcx().next_ty_var()
1231 fn projected_ty_from_poly_trait_ref(&self,
1233 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1234 item_name: ast::Name)
1237 let (trait_ref, _) =
1238 self.infcx().replace_late_bound_regions_with_fresh_var(
1240 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1243 self.normalize_associated_type(span, trait_ref, item_name)
1246 fn projected_ty(&self,
1248 trait_ref: ty::TraitRef<'tcx>,
1249 item_name: ast::Name)
1252 self.normalize_associated_type(span, trait_ref, item_name)
1256 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1257 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1259 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1263 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1267 pub fn sess(&self) -> &Session {
1271 pub fn err_count_since_creation(&self) -> usize {
1272 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1275 /// Resolves type variables in `ty` if possible. Unlike the infcx
1276 /// version, this version will also select obligations if it seems
1277 /// useful, in an effort to get more type information.
1278 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1279 debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx()));
1281 // No ty::infer()? Nothing needs doing.
1282 if !ty::type_has_ty_infer(ty) {
1283 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1287 // If `ty` is a type variable, see whether we already know what it is.
1288 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1289 if !ty::type_has_ty_infer(ty) {
1290 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1294 // If not, try resolving any new fcx obligations that have cropped up.
1295 self.select_new_obligations();
1296 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1297 if !ty::type_has_ty_infer(ty) {
1298 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1302 // If not, try resolving *all* pending obligations as much as
1303 // possible. This can help substantially when there are
1304 // indirect dependencies that don't seem worth tracking
1306 self.select_obligations_where_possible();
1307 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1309 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1313 /// Resolves all type variables in `t` and then, if any were left
1314 /// unresolved, substitutes an error type. This is used after the
1315 /// main checking when doing a second pass before writeback. The
1316 /// justification is that writeback will produce an error for
1317 /// these unconstrained type variables.
1318 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1319 let t = self.infcx().resolve_type_vars_if_possible(t);
1320 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1323 fn record_deferred_call_resolution(&self,
1324 closure_def_id: ast::DefId,
1325 r: DeferredCallResolutionHandler<'tcx>) {
1326 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1327 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1330 fn remove_deferred_call_resolutions(&self,
1331 closure_def_id: ast::DefId)
1332 -> Vec<DeferredCallResolutionHandler<'tcx>>
1334 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1335 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1338 pub fn tag(&self) -> String {
1339 let self_ptr: *const FnCtxt = self;
1340 format!("{:?}", self_ptr)
1343 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1344 match self.inh.locals.borrow().get(&nid) {
1347 self.tcx().sess.span_err(
1349 &format!("no type for local variable {}", nid));
1350 self.tcx().types.err
1355 /// Apply "fallbacks" to some types
1356 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1357 pub fn default_type_parameters(&self) {
1358 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1359 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1360 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1361 if self.infcx().type_var_diverges(resolved) {
1362 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1364 match self.infcx().type_is_unconstrained_numeric(resolved) {
1365 UnconstrainedInt => {
1366 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1368 UnconstrainedFloat => {
1369 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1378 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1379 debug!("write_ty({}, {}) in fcx {}",
1380 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1381 self.inh.node_types.borrow_mut().insert(node_id, ty);
1384 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1385 if !substs.substs.is_noop() {
1386 debug!("write_substs({}, {}) in fcx {}",
1388 substs.repr(self.tcx()),
1391 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1395 pub fn write_autoderef_adjustment(&self,
1396 node_id: ast::NodeId,
1398 self.write_adjustment(
1400 ty::AdjustDerefRef(ty::AutoDerefRef {
1408 pub fn write_adjustment(&self,
1409 node_id: ast::NodeId,
1410 adj: ty::AutoAdjustment<'tcx>) {
1411 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1413 if adj.is_identity() {
1417 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1420 /// Basically whenever we are converting from a type scheme into
1421 /// the fn body space, we always want to normalize associated
1422 /// types as well. This function combines the two.
1423 fn instantiate_type_scheme<T>(&self,
1425 substs: &Substs<'tcx>,
1428 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1430 let value = value.subst(self.tcx(), substs);
1431 let result = self.normalize_associated_types_in(span, &value);
1432 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1433 value.repr(self.tcx()),
1434 substs.repr(self.tcx()),
1435 result.repr(self.tcx()));
1439 /// As `instantiate_type_scheme`, but for the bounds found in a
1440 /// generic type scheme.
1441 fn instantiate_bounds(&self,
1443 substs: &Substs<'tcx>,
1444 bounds: &ty::GenericPredicates<'tcx>)
1445 -> ty::InstantiatedPredicates<'tcx>
1447 ty::InstantiatedPredicates {
1448 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1453 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1454 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1456 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1459 fn normalize_associated_type(&self,
1461 trait_ref: ty::TraitRef<'tcx>,
1462 item_name: ast::Name)
1465 let cause = traits::ObligationCause::new(span,
1467 traits::ObligationCauseCode::MiscObligation);
1468 self.inh.fulfillment_cx
1470 .normalize_projection_type(self.infcx(),
1473 trait_ref: trait_ref,
1474 item_name: item_name,
1479 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1480 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1481 /// Registers any trait obligations specified on `def_id` at the same time.
1483 /// Note that function is only intended to be used with types (notably, not fns). This is
1484 /// because it doesn't do any instantiation of late-bound regions.
1485 pub fn instantiate_type(&self,
1488 -> TypeAndSubsts<'tcx>
1491 ty::lookup_item_type(self.tcx(), def_id);
1492 let type_predicates =
1493 ty::lookup_predicates(self.tcx(), def_id);
1495 self.infcx().fresh_substs_for_generics(
1497 &type_scheme.generics);
1499 self.instantiate_bounds(span, &substs, &type_predicates);
1500 self.add_obligations_for_parameters(
1501 traits::ObligationCause::new(
1504 traits::ItemObligation(def_id)),
1507 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1515 /// Returns the type that this AST path refers to. If the path has no type
1516 /// parameters and the corresponding type has type parameters, fresh type
1517 /// and/or region variables are substituted.
1519 /// This is used when checking the constructor in struct literals.
1520 fn instantiate_struct_literal_ty(&self,
1523 -> TypeAndSubsts<'tcx>
1525 let tcx = self.tcx();
1527 let ty::TypeScheme { generics, ty: decl_ty } =
1528 ty::lookup_item_type(tcx, did);
1530 let substs = astconv::ast_path_substs_for_ty(self, self,
1532 PathParamMode::Optional,
1534 path.segments.last().unwrap());
1536 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1538 TypeAndSubsts { substs: substs, ty: ty }
1541 pub fn write_nil(&self, node_id: ast::NodeId) {
1542 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1544 pub fn write_error(&self, node_id: ast::NodeId) {
1545 self.write_ty(node_id, self.tcx().types.err);
1548 pub fn require_type_meets(&self,
1551 code: traits::ObligationCauseCode<'tcx>,
1552 bound: ty::BuiltinBound)
1554 self.register_builtin_bound(
1557 traits::ObligationCause::new(span, self.body_id, code));
1560 pub fn require_type_is_sized(&self,
1563 code: traits::ObligationCauseCode<'tcx>)
1565 self.require_type_meets(ty, span, code, ty::BoundSized);
1568 pub fn require_expr_have_sized_type(&self,
1570 code: traits::ObligationCauseCode<'tcx>)
1572 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1575 pub fn type_is_known_to_be_sized(&self,
1580 traits::type_known_to_meet_builtin_bound(self.infcx(),
1587 pub fn register_builtin_bound(&self,
1589 builtin_bound: ty::BuiltinBound,
1590 cause: traits::ObligationCause<'tcx>)
1592 self.inh.fulfillment_cx.borrow_mut()
1593 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1596 pub fn register_predicate(&self,
1597 obligation: traits::PredicateObligation<'tcx>)
1599 debug!("register_predicate({})",
1600 obligation.repr(self.tcx()));
1601 self.inh.fulfillment_cx
1603 .register_predicate_obligation(self.infcx(), obligation);
1606 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1607 let t = ast_ty_to_ty(self, self, ast_t);
1609 let mut bounds_checker = wf::BoundsChecker::new(self,
1613 bounds_checker.check_ty(t);
1618 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1619 pat.repr(self.tcx())
1622 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1623 match self.inh.node_types.borrow().get(&ex.id) {
1626 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1632 /// Apply `adjustment` to the type of `expr`
1633 pub fn adjust_expr_ty(&self,
1635 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1638 let raw_ty = self.expr_ty(expr);
1639 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1640 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1641 ty::adjust_ty(self.tcx(),
1646 |method_call| self.inh.method_map.borrow()
1648 .map(|method| resolve_ty(method.ty)))
1651 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1652 match self.inh.node_types.borrow().get(&id) {
1654 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1656 self.tcx().sess.bug(
1657 &format!("no type for node {}: {} in fcx {}",
1658 id, self.tcx().map.node_to_string(id),
1664 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1665 self.inh.item_substs.borrow()
1668 pub fn opt_node_ty_substs<F>(&self,
1671 F: FnOnce(&ty::ItemSubsts<'tcx>),
1673 match self.inh.item_substs.borrow().get(&id) {
1679 pub fn mk_subty(&self,
1680 a_is_expected: bool,
1681 origin: infer::TypeOrigin,
1684 -> Result<(), ty::type_err<'tcx>> {
1685 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1688 pub fn mk_eqty(&self,
1689 a_is_expected: bool,
1690 origin: infer::TypeOrigin,
1693 -> Result<(), ty::type_err<'tcx>> {
1694 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1697 pub fn mk_subr(&self,
1698 origin: infer::SubregionOrigin<'tcx>,
1701 infer::mk_subr(self.infcx(), origin, sub, sup)
1704 pub fn type_error_message<M>(&self,
1707 actual_ty: Ty<'tcx>,
1708 err: Option<&ty::type_err<'tcx>>) where
1709 M: FnOnce(String) -> String,
1711 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1714 pub fn report_mismatched_types(&self,
1718 err: &ty::type_err<'tcx>) {
1719 self.infcx().report_mismatched_types(sp, e, a, err)
1722 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1723 /// outlive the region `r`.
1724 pub fn register_region_obligation(&self,
1727 cause: traits::ObligationCause<'tcx>)
1729 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1730 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1733 pub fn add_default_region_param_bounds(&self,
1734 substs: &Substs<'tcx>,
1737 for &ty in substs.types.iter() {
1738 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1739 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1740 traits::MiscObligation);
1741 self.register_region_obligation(ty, default_bound, cause);
1745 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1746 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1747 /// trait/region obligations.
1749 /// For example, if there is a function:
1752 /// fn foo<'a,T:'a>(...)
1755 /// and a reference:
1761 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1762 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1763 pub fn add_obligations_for_parameters(&self,
1764 cause: traits::ObligationCause<'tcx>,
1765 predicates: &ty::InstantiatedPredicates<'tcx>)
1767 assert!(!predicates.has_escaping_regions());
1769 debug!("add_obligations_for_parameters(predicates={})",
1770 predicates.repr(self.tcx()));
1772 let obligations = traits::predicates_for_generics(self.tcx(),
1776 obligations.map_move(|o| self.register_predicate(o));
1779 // Only for fields! Returns <none> for methods>
1780 // Indifferent to privacy flags
1781 pub fn lookup_field_ty(&self,
1783 class_id: ast::DefId,
1784 items: &[ty::field_ty],
1785 fieldname: ast::Name,
1786 substs: &subst::Substs<'tcx>)
1789 let o_field = items.iter().find(|f| f.name == fieldname);
1790 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1791 .map(|t| self.normalize_associated_types_in(span, &t))
1794 pub fn lookup_tup_field_ty(&self,
1796 class_id: ast::DefId,
1797 items: &[ty::field_ty],
1799 substs: &subst::Substs<'tcx>)
1802 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1803 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1804 .map(|t| self.normalize_associated_types_in(span, &t))
1807 fn check_casts(&self) {
1808 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1809 for cast in deferred_cast_checks.drain(..) {
1814 fn select_all_obligations_and_apply_defaults(&self) {
1815 debug!("select_all_obligations_and_apply_defaults");
1817 self.select_obligations_where_possible();
1818 self.default_type_parameters();
1819 self.select_obligations_where_possible();
1822 fn select_all_obligations_or_error(&self) {
1823 debug!("select_all_obligations_or_error");
1825 // upvar inference should have ensured that all deferred call
1826 // resolutions are handled by now.
1827 assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
1829 self.select_all_obligations_and_apply_defaults();
1830 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1831 match fulfillment_cx.select_all_or_error(self.infcx(), self) {
1833 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1837 /// Select as many obligations as we can at present.
1838 fn select_obligations_where_possible(&self) {
1840 self.inh.fulfillment_cx
1842 .select_where_possible(self.infcx(), self)
1845 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1849 /// Try to select any fcx obligation that we haven't tried yet, in an effort
1850 /// to improve inference. You could just call
1851 /// `select_obligations_where_possible` except that it leads to repeated
1853 fn select_new_obligations(&self) {
1855 self.inh.fulfillment_cx
1857 .select_new_obligations(self.infcx(), self)
1860 Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
1866 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1867 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1868 // RFC #599 specifies that object lifetime defaults take
1869 // precedence over other defaults. But within a fn body we
1870 // don't have a *default* region, rather we use inference to
1871 // find the *correct* region, which is strictly more general
1872 // (and anyway, within a fn body the right region may not even
1873 // be something the user can write explicitly, since it might
1874 // be some expression).
1875 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1878 fn anon_regions(&self, span: Span, count: usize)
1879 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
1880 Ok((0..count).map(|_| {
1881 self.infcx().next_region_var(infer::MiscVariable(span))
1886 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1887 pub enum LvaluePreference {
1892 /// Whether `autoderef` requires types to resolve.
1893 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1894 pub enum UnresolvedTypeAction {
1895 /// Produce an error and return `ty_err` whenever a type cannot
1896 /// be resolved (i.e. it is `ty_infer`).
1898 /// Go on without emitting any errors, and return the unresolved
1899 /// type. Useful for probing, e.g. in coercions.
1903 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1904 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1906 /// Note: this method does not modify the adjustments table. The caller is responsible for
1907 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1908 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1911 opt_expr: Option<&ast::Expr>,
1912 unresolved_type_action: UnresolvedTypeAction,
1913 mut lvalue_pref: LvaluePreference,
1915 -> (Ty<'tcx>, usize, Option<T>)
1916 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
1918 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1919 base_ty.repr(fcx.tcx()),
1920 opt_expr.repr(fcx.tcx()),
1923 let mut t = base_ty;
1924 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1925 let resolved_t = match unresolved_type_action {
1926 UnresolvedTypeAction::Error => {
1927 structurally_resolved_type(fcx, sp, t)
1929 UnresolvedTypeAction::Ignore => {
1930 // We can continue even when the type cannot be resolved
1931 // (i.e. it is an inference variable) because `ty::deref`
1932 // and `try_overloaded_deref` both simply return `None`
1933 // in such a case without producing spurious errors.
1934 fcx.resolve_type_vars_if_possible(t)
1937 if ty::type_is_error(resolved_t) {
1938 return (resolved_t, autoderefs, None);
1941 match should_stop(resolved_t, autoderefs) {
1942 Some(x) => return (resolved_t, autoderefs, Some(x)),
1946 // Otherwise, deref if type is derefable:
1947 let mt = match ty::deref(resolved_t, false) {
1948 Some(mt) => Some(mt),
1951 opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs as u32));
1953 // Super subtle: it might seem as though we should
1954 // pass `opt_expr` to `try_overloaded_deref`, so that
1955 // the (implicit) autoref of using an overloaded deref
1956 // would get added to the adjustment table. However we
1957 // do not do that, because it's kind of a
1958 // "meta-adjustment" -- instead, we just leave it
1959 // unrecorded and know that there "will be" an
1960 // autoref. regionck and other bits of the code base,
1961 // when they encounter an overloaded autoderef, have
1962 // to do some reconstructive surgery. This is a pretty
1963 // complex mess that is begging for a proper MIR.
1964 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1970 if mt.mutbl == ast::MutImmutable {
1971 lvalue_pref = NoPreference;
1974 None => return (resolved_t, autoderefs, None)
1978 // We've reached the recursion limit, error gracefully.
1979 span_err!(fcx.tcx().sess, sp, E0055,
1980 "reached the recursion limit while auto-dereferencing {}",
1981 base_ty.repr(fcx.tcx()));
1982 (fcx.tcx().types.err, 0, None)
1985 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1987 method_call: Option<MethodCall>,
1988 base_expr: Option<&ast::Expr>,
1990 lvalue_pref: LvaluePreference)
1991 -> Option<ty::mt<'tcx>>
1993 // Try DerefMut first, if preferred.
1994 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1995 (PreferMutLvalue, Some(trait_did)) => {
1996 method::lookup_in_trait(fcx, span, base_expr,
1997 token::intern("deref_mut"), trait_did,
2003 // Otherwise, fall back to Deref.
2004 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2005 (None, Some(trait_did)) => {
2006 method::lookup_in_trait(fcx, span, base_expr,
2007 token::intern("deref"), trait_did,
2010 (method, _) => method
2013 make_overloaded_lvalue_return_type(fcx, method_call, method)
2016 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2017 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2018 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2019 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2020 method_call: Option<MethodCall>,
2021 method: Option<MethodCallee<'tcx>>)
2022 -> Option<ty::mt<'tcx>>
2026 // extract method method return type, which will be &T;
2027 // all LB regions should have been instantiated during method lookup
2028 let ret_ty = ty::ty_fn_ret(method.ty);
2029 let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap();
2031 if let Some(method_call) = method_call {
2032 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2035 // method returns &T, but the type as visible to user is T, so deref
2036 ty::deref(ret_ty, true)
2042 fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2044 base_expr: &'tcx ast::Expr,
2047 lvalue_pref: LvaluePreference)
2048 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2050 // FIXME(#18741) -- this is almost but not quite the same as the
2051 // autoderef that normal method probing does. They could likely be
2054 let (ty, autoderefs, final_mt) = autoderef(fcx,
2058 UnresolvedTypeAction::Error,
2061 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2062 adj_ty, idx, false, lvalue_pref, idx_ty)
2065 if final_mt.is_some() {
2069 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2070 // do a final unsized coercion to yield [T].
2071 if let ty::ty_vec(element_ty, Some(_)) = ty.sty {
2072 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2073 try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
2074 adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
2080 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2081 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2082 /// This loop implements one step in that search; the autoderef loop is implemented by
2083 /// `lookup_indexing`.
2084 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2085 method_call: MethodCall,
2087 base_expr: &'tcx ast::Expr,
2088 adjusted_ty: Ty<'tcx>,
2091 lvalue_pref: LvaluePreference,
2093 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2095 let tcx = fcx.tcx();
2096 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, \
2097 autoderefs={}, unsize={}, index_ty={})",
2099 base_expr.repr(tcx),
2100 adjusted_ty.repr(tcx),
2103 index_ty.repr(tcx));
2105 let input_ty = fcx.infcx().next_ty_var();
2107 // First, try built-in indexing.
2108 match (ty::index(adjusted_ty), &index_ty.sty) {
2109 (Some(ty), &ty::ty_uint(ast::TyUs)) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2110 debug!("try_index_step: success, using built-in indexing");
2111 // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2113 fcx.write_autoderef_adjustment(base_expr.id, autoderefs);
2114 return Some((tcx.types.usize, ty));
2119 // Try `IndexMut` first, if preferred.
2120 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2121 (PreferMutLvalue, Some(trait_did)) => {
2122 method::lookup_in_trait_adjusted(fcx,
2125 token::intern("index_mut"),
2130 Some(vec![input_ty]))
2135 // Otherwise, fall back to `Index`.
2136 let method = match (method, tcx.lang_items.index_trait()) {
2137 (None, Some(trait_did)) => {
2138 method::lookup_in_trait_adjusted(fcx,
2141 token::intern("index"),
2146 Some(vec![input_ty]))
2148 (method, _) => method,
2151 // If some lookup succeeds, write callee into table and extract index/element
2152 // type from the method signature.
2153 // If some lookup succeeded, install method in table
2154 method.and_then(|method| {
2155 debug!("try_index_step: success, using overloaded indexing");
2156 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2157 map(|ret| (input_ty, ret.ty))
2161 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2163 method_fn_ty: Ty<'tcx>,
2164 callee_expr: &'tcx ast::Expr,
2165 args_no_rcvr: &'tcx [P<ast::Expr>],
2166 tuple_arguments: TupleArgumentsFlag,
2167 expected: Expectation<'tcx>)
2168 -> ty::FnOutput<'tcx> {
2169 if ty::type_is_error(method_fn_ty) {
2170 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2172 let err_inputs = match tuple_arguments {
2173 DontTupleArguments => err_inputs,
2174 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2177 check_argument_types(fcx,
2184 ty::FnConverging(fcx.tcx().types.err)
2186 match method_fn_ty.sty {
2187 ty::ty_bare_fn(_, ref fty) => {
2188 // HACK(eddyb) ignore self in the definition (see above).
2189 let expected_arg_tys = expected_types_for_fn_args(fcx,
2193 &fty.sig.0.inputs[1..]);
2194 check_argument_types(fcx,
2196 &fty.sig.0.inputs[1..],
2197 &expected_arg_tys[..],
2204 fcx.tcx().sess.span_bug(callee_expr.span,
2205 "method without bare fn type");
2211 /// Generic function that factors out common logic from function calls, method calls and overloaded
2213 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2215 fn_inputs: &[Ty<'tcx>],
2216 expected_arg_tys: &[Ty<'tcx>],
2217 args: &'tcx [P<ast::Expr>],
2219 tuple_arguments: TupleArgumentsFlag) {
2220 let tcx = fcx.ccx.tcx;
2222 // Grab the argument types, supplying fresh type variables
2223 // if the wrong number of arguments were supplied
2224 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2230 let mut expected_arg_tys = expected_arg_tys;
2231 let expected_arg_count = fn_inputs.len();
2232 let formal_tys = if tuple_arguments == TupleArguments {
2233 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2234 match tuple_type.sty {
2235 ty::ty_tup(ref arg_types) => {
2236 if arg_types.len() != args.len() {
2237 span_err!(tcx.sess, sp, E0057,
2238 "this function takes {} parameter{} but {} parameter{} supplied",
2240 if arg_types.len() == 1 {""} else {"s"},
2242 if args.len() == 1 {" was"} else {"s were"});
2243 expected_arg_tys = &[];
2244 err_args(fcx.tcx(), args.len())
2246 expected_arg_tys = match expected_arg_tys.get(0) {
2247 Some(&ty) => match ty.sty {
2248 ty::ty_tup(ref tys) => &**tys,
2253 (*arg_types).clone()
2257 span_err!(tcx.sess, sp, E0059,
2258 "cannot use call notation; the first type parameter \
2259 for the function trait is neither a tuple nor unit");
2260 expected_arg_tys = &[];
2261 err_args(fcx.tcx(), args.len())
2264 } else if expected_arg_count == supplied_arg_count {
2266 } else if variadic {
2267 if supplied_arg_count >= expected_arg_count {
2270 span_err!(tcx.sess, sp, E0060,
2271 "this function takes at least {} parameter{} \
2272 but {} parameter{} supplied",
2274 if expected_arg_count == 1 {""} else {"s"},
2276 if supplied_arg_count == 1 {" was"} else {"s were"});
2277 expected_arg_tys = &[];
2278 err_args(fcx.tcx(), supplied_arg_count)
2281 span_err!(tcx.sess, sp, E0061,
2282 "this function takes {} parameter{} but {} parameter{} supplied",
2284 if expected_arg_count == 1 {""} else {"s"},
2286 if supplied_arg_count == 1 {" was"} else {"s were"});
2287 expected_arg_tys = &[];
2288 err_args(fcx.tcx(), supplied_arg_count)
2291 debug!("check_argument_types: formal_tys={:?}",
2292 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2294 // Check the arguments.
2295 // We do this in a pretty awful way: first we typecheck any arguments
2296 // that are not anonymous functions, then we typecheck the anonymous
2297 // functions. This is so that we have more information about the types
2298 // of arguments when we typecheck the functions. This isn't really the
2299 // right way to do this.
2300 let xs = [false, true];
2301 for check_blocks in &xs {
2302 let check_blocks = *check_blocks;
2303 debug!("check_blocks={}", check_blocks);
2305 // More awful hacks: before we check argument types, try to do
2306 // an "opportunistic" vtable resolution of any trait bounds on
2307 // the call. This helps coercions.
2309 fcx.select_new_obligations();
2312 // For variadic functions, we don't have a declared type for all of
2313 // the arguments hence we only do our usual type checking with
2314 // the arguments who's types we do know.
2315 let t = if variadic {
2317 } else if tuple_arguments == TupleArguments {
2322 for (i, arg) in args.iter().take(t).enumerate() {
2323 let is_block = match arg.node {
2324 ast::ExprClosure(..) => true,
2328 if is_block == check_blocks {
2329 debug!("checking the argument");
2330 let formal_ty = formal_tys[i];
2332 // The special-cased logic below has three functions:
2333 // 1. Provide as good of an expected type as possible.
2334 let expected = expected_arg_tys.get(i).map(|&ty| {
2335 Expectation::rvalue_hint(ty)
2338 check_expr_with_unifier(fcx, &**arg,
2339 expected.unwrap_or(ExpectHasType(formal_ty)),
2341 // 2. Coerce to the most detailed type that could be coerced
2342 // to, which is `expected_ty` if `rvalue_hint` returns an
2343 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2344 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2345 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2347 // 3. Relate the expected type and the formal one,
2348 // if the expected type was used for the coercion.
2349 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2355 // We also need to make sure we at least write the ty of the other
2356 // arguments which we skipped above.
2358 for arg in args.iter().skip(expected_arg_count) {
2359 check_expr(fcx, &**arg);
2361 // There are a few types which get autopromoted when passed via varargs
2362 // in C but we just error out instead and require explicit casts.
2363 let arg_ty = structurally_resolved_type(fcx, arg.span,
2364 fcx.expr_ty(&**arg));
2366 ty::ty_float(ast::TyF32) => {
2367 fcx.type_error_message(arg.span,
2369 format!("can't pass an {} to variadic \
2370 function, cast to c_double", t)
2373 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2374 fcx.type_error_message(arg.span, |t| {
2375 format!("can't pass {} to variadic \
2376 function, cast to c_int",
2380 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2381 fcx.type_error_message(arg.span, |t| {
2382 format!("can't pass {} to variadic \
2383 function, cast to c_uint",
2393 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2394 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2395 (0..len).map(|_| tcx.types.err).collect()
2398 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2399 call_expr: &ast::Expr,
2400 output: ty::FnOutput<'tcx>) {
2401 fcx.write_ty(call_expr.id, match output {
2402 ty::FnConverging(output_ty) => output_ty,
2403 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2407 // AST fragment checking
2408 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2410 expected: Expectation<'tcx>)
2413 let tcx = fcx.ccx.tcx;
2416 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2417 ast::LitBinary(ref v) => {
2418 ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
2419 ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
2420 mutbl: ast::MutImmutable,
2423 ast::LitByte(_) => tcx.types.u8,
2424 ast::LitChar(_) => tcx.types.char,
2425 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2426 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2427 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2428 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2430 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2431 ty::ty_char => Some(tcx.types.u8),
2432 ty::ty_ptr(..) => Some(tcx.types.usize),
2433 ty::ty_bare_fn(..) => Some(tcx.types.usize),
2437 opt_ty.unwrap_or_else(
2438 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2440 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2441 ast::LitFloatUnsuffixed(_) => {
2442 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2444 ty::ty_float(_) => Some(ty),
2448 opt_ty.unwrap_or_else(
2449 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2451 ast::LitBool(_) => tcx.types.bool
2455 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2456 expr: &'tcx ast::Expr,
2457 expected: Ty<'tcx>) {
2458 check_expr_with_unifier(
2459 fcx, expr, ExpectHasType(expected), NoPreference,
2460 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2463 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2464 expr: &'tcx ast::Expr,
2465 expected: Ty<'tcx>) {
2466 check_expr_with_unifier(
2467 fcx, expr, ExpectHasType(expected), NoPreference,
2468 || demand::coerce(fcx, expr.span, expected, expr));
2471 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2472 expected: Ty<'tcx>) {
2473 check_expr_with_unifier(
2474 fcx, expr, ExpectHasType(expected), NoPreference,
2478 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2479 expr: &'tcx ast::Expr,
2480 expected: Expectation<'tcx>) {
2481 check_expr_with_unifier(
2482 fcx, expr, expected, NoPreference,
2486 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2487 expr: &'tcx ast::Expr,
2488 expected: Expectation<'tcx>,
2489 lvalue_pref: LvaluePreference)
2491 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2494 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2495 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2498 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2499 lvalue_pref: LvaluePreference) {
2500 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2503 // determine the `self` type, using fresh variables for all variables
2504 // declared on the impl declaration e.g., `impl<A,B> for Vec<(A,B)>`
2505 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2507 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2508 span: Span, // (potential) receiver for this impl
2510 -> TypeAndSubsts<'tcx> {
2511 let tcx = fcx.tcx();
2513 let ity = ty::lookup_item_type(tcx, did);
2514 let (n_tps, rps, raw_ty) =
2515 (ity.generics.types.len(subst::TypeSpace),
2516 ity.generics.regions.get_slice(subst::TypeSpace),
2519 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2520 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2521 let substs = subst::Substs::new_type(tps, rps);
2522 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2524 TypeAndSubsts { substs: substs, ty: substd_ty }
2527 /// Controls whether the arguments are tupled. This is used for the call
2530 /// Tupling means that all call-side arguments are packed into a tuple and
2531 /// passed as a single parameter. For example, if tupling is enabled, this
2534 /// fn f(x: (isize, isize))
2536 /// Can be called as:
2543 #[derive(Clone, Eq, PartialEq)]
2544 enum TupleArgumentsFlag {
2549 /// Unifies the return type with the expected type early, for more coercions
2550 /// and forward type information on the argument expressions.
2551 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2553 expected_ret: Expectation<'tcx>,
2554 formal_ret: ty::FnOutput<'tcx>,
2555 formal_args: &[Ty<'tcx>])
2557 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2558 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2559 fcx.infcx().commit_regions_if_ok(|| {
2560 // Attempt to apply a subtyping relationship between the formal
2561 // return type (likely containing type variables if the function
2562 // is polymorphic) and the expected return type.
2563 // No argument expectations are produced if unification fails.
2564 let origin = infer::Misc(call_span);
2565 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2566 // FIXME(#15760) can't use try! here, FromError doesn't default
2567 // to identity so the resulting type is not constrained.
2568 if let Err(e) = ures {
2572 // Record all the argument types, with the substitutions
2573 // produced from the above subtyping unification.
2574 Ok(formal_args.iter().map(|ty| {
2575 fcx.infcx().resolve_type_vars_if_possible(ty)
2581 }).unwrap_or(vec![]);
2582 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2583 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2584 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2589 /// If an expression has any sub-expressions that result in a type error,
2590 /// inspecting that expression's type with `ty::type_is_error` will return
2591 /// true. Likewise, if an expression is known to diverge, inspecting its
2592 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2593 /// strict, _|_ can appear in the type of an expression that does not,
2594 /// itself, diverge: for example, fn() -> _|_.)
2595 /// Note that inspecting a type's structure *directly* may expose the fact
2596 /// that there are actually multiple representations for `ty_err`, so avoid
2597 /// that when err needs to be handled differently.
2598 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2599 expr: &'tcx ast::Expr,
2600 expected: Expectation<'tcx>,
2601 lvalue_pref: LvaluePreference,
2605 debug!(">> typechecking: expr={} expected={}",
2606 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2608 // Checks a method call.
2609 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2610 expr: &'tcx ast::Expr,
2611 method_name: ast::SpannedIdent,
2612 args: &'tcx [P<ast::Expr>],
2614 expected: Expectation<'tcx>,
2615 lvalue_pref: LvaluePreference) {
2616 let rcvr = &*args[0];
2617 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2619 // no need to check for bot/err -- callee does that
2620 let expr_t = structurally_resolved_type(fcx,
2622 fcx.expr_ty(&*rcvr));
2624 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2625 let fn_ty = match method::lookup(fcx,
2627 method_name.node.name,
2633 let method_ty = method.ty;
2634 let method_call = MethodCall::expr(expr.id);
2635 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2639 method::report_error(fcx, method_name.span, expr_t,
2640 method_name.node.name, Some(rcvr), error);
2641 fcx.write_error(expr.id);
2646 // Call the generic checker.
2647 let ret_ty = check_method_argument_types(fcx,
2655 write_call(fcx, expr, ret_ty);
2658 // A generic function for checking the then and else in an if
2660 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2661 cond_expr: &'tcx ast::Expr,
2662 then_blk: &'tcx ast::Block,
2663 opt_else_expr: Option<&'tcx ast::Expr>,
2666 expected: Expectation<'tcx>) {
2667 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2669 let expected = expected.adjust_for_branches(fcx);
2670 check_block_with_expected(fcx, then_blk, expected);
2671 let then_ty = fcx.node_ty(then_blk.id);
2673 let branches_ty = match opt_else_expr {
2674 Some(ref else_expr) => {
2675 check_expr_with_expectation(fcx, &**else_expr, expected);
2676 let else_ty = fcx.expr_ty(&**else_expr);
2677 infer::common_supertype(fcx.infcx(),
2678 infer::IfExpression(sp),
2684 infer::common_supertype(fcx.infcx(),
2685 infer::IfExpressionWithNoElse(sp),
2688 ty::mk_nil(fcx.tcx()))
2692 let cond_ty = fcx.expr_ty(cond_expr);
2693 let if_ty = if ty::type_is_error(cond_ty) {
2699 fcx.write_ty(id, if_ty);
2702 // Check field access expressions
2703 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2704 expr: &'tcx ast::Expr,
2705 lvalue_pref: LvaluePreference,
2706 base: &'tcx ast::Expr,
2707 field: &ast::SpannedIdent) {
2708 let tcx = fcx.ccx.tcx;
2709 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2710 let expr_t = structurally_resolved_type(fcx, expr.span,
2712 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2713 let (_, autoderefs, field_ty) = autoderef(fcx,
2717 UnresolvedTypeAction::Error,
2721 ty::ty_struct(base_id, substs) => {
2722 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2723 let fields = ty::lookup_struct_fields(tcx, base_id);
2724 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
2725 field.node.name, &(*substs))
2732 fcx.write_ty(expr.id, field_ty);
2733 fcx.write_autoderef_adjustment(base.id, autoderefs);
2739 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2740 fcx.type_error_message(
2743 format!("attempted to take value of method `{}` on type \
2744 `{}`", token::get_ident(field.node), actual)
2748 tcx.sess.fileline_help(field.span,
2749 "maybe a `()` to call it is missing? \
2750 If not, try an anonymous function");
2752 fcx.type_error_message(
2755 format!("attempted access of field `{}` on \
2756 type `{}`, but no field with that \
2758 token::get_ident(field.node),
2762 if let ty::ty_struct(did, _) = expr_t.sty {
2763 suggest_field_names(did, field, tcx, vec![]);
2767 fcx.write_error(expr.id);
2770 // displays hints about the closest matches in field names
2771 fn suggest_field_names<'tcx>(id : DefId,
2772 field : &ast::SpannedIdent,
2773 tcx : &ty::ctxt<'tcx>,
2775 let ident = token::get_ident(field.node);
2777 // only find fits with at least one matching letter
2778 let mut best_dist = name.len();
2779 let fields = ty::lookup_struct_fields(tcx, id);
2780 let mut best = None;
2781 for elem in &fields {
2782 let n = elem.name.as_str();
2783 // ignore already set fields
2784 if skip.iter().any(|&x| x == n) {
2787 // ignore private fields from non-local crates
2788 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2791 let dist = lev_distance(n, name);
2792 if dist < best_dist {
2797 if let Some(n) = best {
2798 tcx.sess.span_help(field.span,
2799 &format!("did you mean `{}`?", n));
2803 // Check tuple index expressions
2804 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2805 expr: &'tcx ast::Expr,
2806 lvalue_pref: LvaluePreference,
2807 base: &'tcx ast::Expr,
2808 idx: codemap::Spanned<usize>) {
2809 let tcx = fcx.ccx.tcx;
2810 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2811 let expr_t = structurally_resolved_type(fcx, expr.span,
2813 let mut tuple_like = false;
2814 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2815 let (_, autoderefs, field_ty) = autoderef(fcx,
2819 UnresolvedTypeAction::Error,
2823 ty::ty_struct(base_id, substs) => {
2824 tuple_like = ty::is_tuple_struct(tcx, base_id);
2826 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
2827 let fields = ty::lookup_struct_fields(tcx, base_id);
2828 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
2829 idx.node, &(*substs))
2834 ty::ty_tup(ref v) => {
2836 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2843 fcx.write_ty(expr.id, field_ty);
2844 fcx.write_autoderef_adjustment(base.id, autoderefs);
2849 fcx.type_error_message(
2853 format!("attempted out-of-bounds tuple index `{}` on \
2858 format!("attempted tuple index `{}` on type `{}`, but the \
2859 type was not a tuple or tuple struct",
2866 fcx.write_error(expr.id);
2869 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2870 struct_ty: Ty<'tcx>,
2872 class_id: ast::DefId,
2873 node_id: ast::NodeId,
2874 substitutions: &'tcx subst::Substs<'tcx>,
2875 field_types: &[ty::field_ty],
2876 ast_fields: &'tcx [ast::Field],
2877 check_completeness: bool,
2878 enum_id_opt: Option<ast::DefId>) {
2879 let tcx = fcx.ccx.tcx;
2881 let mut class_field_map = FnvHashMap();
2882 let mut fields_found = 0;
2883 for field in field_types {
2884 class_field_map.insert(field.name, (field.id, false));
2887 let mut error_happened = false;
2889 // Typecheck each field.
2890 for field in ast_fields {
2891 let mut expected_field_type = tcx.types.err;
2893 let pair = class_field_map.get(&field.ident.node.name).cloned();
2896 fcx.type_error_message(
2898 |actual| match enum_id_opt {
2900 let variant_type = ty::enum_variant_with_id(tcx,
2903 format!("struct variant `{}::{}` has no field named `{}`",
2904 actual, variant_type.name.as_str(),
2905 token::get_ident(field.ident.node))
2908 format!("structure `{}` has no field named `{}`",
2910 token::get_ident(field.ident.node))
2915 // prevent all specified fields from being suggested
2916 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
2917 let actual_id = match enum_id_opt {
2918 Some(_) => class_id,
2919 None => ty::ty_to_def_id(struct_ty).unwrap()
2921 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
2922 error_happened = true;
2924 Some((_, true)) => {
2925 span_err!(fcx.tcx().sess, field.ident.span, E0062,
2926 "field `{}` specified more than once",
2927 token::get_ident(field.ident.node));
2928 error_happened = true;
2930 Some((field_id, false)) => {
2931 expected_field_type =
2932 ty::lookup_field_type(
2933 tcx, class_id, field_id, substitutions);
2934 expected_field_type =
2935 fcx.normalize_associated_types_in(
2936 field.span, &expected_field_type);
2937 class_field_map.insert(
2938 field.ident.node.name, (field_id, true));
2943 // Make sure to give a type to the field even if there's
2944 // an error, so we can continue typechecking
2945 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
2949 fcx.write_error(node_id);
2952 if check_completeness && !error_happened {
2953 // Make sure the programmer specified all the fields.
2954 assert!(fields_found <= field_types.len());
2955 if fields_found < field_types.len() {
2956 let mut missing_fields = Vec::new();
2957 for class_field in field_types {
2958 let name = class_field.name;
2959 let (_, seen) = *class_field_map.get(&name).unwrap();
2961 missing_fields.push(
2962 format!("`{}`", &token::get_name(name)))
2966 span_err!(tcx.sess, span, E0063,
2967 "missing field{}: {}",
2968 if missing_fields.len() == 1 {""} else {"s"},
2969 missing_fields.connect(", "));
2973 if !error_happened {
2974 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2975 class_id, substitutions));
2979 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2981 span: codemap::Span,
2982 class_id: ast::DefId,
2983 fields: &'tcx [ast::Field],
2984 base_expr: Option<&'tcx ast::Expr>) {
2985 let tcx = fcx.ccx.tcx;
2987 // Generate the struct type.
2989 ty: mut struct_type,
2990 substs: struct_substs
2991 } = fcx.instantiate_type(span, class_id);
2993 // Look up and check the fields.
2994 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2995 check_struct_or_variant_fields(fcx,
3000 fcx.ccx.tcx.mk_substs(struct_substs),
3003 base_expr.is_none(),
3005 if ty::type_is_error(fcx.node_ty(id)) {
3006 struct_type = tcx.types.err;
3009 // Check the base expression if necessary.
3012 Some(base_expr) => {
3013 check_expr_has_type(fcx, &*base_expr, struct_type);
3017 // Write in the resulting type.
3018 fcx.write_ty(id, struct_type);
3021 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3023 span: codemap::Span,
3024 enum_id: ast::DefId,
3025 variant_id: ast::DefId,
3026 fields: &'tcx [ast::Field]) {
3027 let tcx = fcx.ccx.tcx;
3029 // Look up the number of type parameters and the raw type, and
3030 // determine whether the enum is region-parameterized.
3033 substs: substitutions
3034 } = fcx.instantiate_type(span, enum_id);
3036 // Look up and check the enum variant fields.
3037 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3038 check_struct_or_variant_fields(fcx,
3043 fcx.ccx.tcx.mk_substs(substitutions),
3044 &variant_fields[..],
3048 fcx.write_ty(id, enum_type);
3051 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3053 fields: &'tcx [ast::Field],
3054 base_expr: &'tcx Option<P<ast::Expr>>) {
3055 // Make sure to still write the types
3056 // otherwise we might ICE
3057 fcx.write_error(id);
3058 for field in fields {
3059 check_expr(fcx, &*field.expr);
3062 Some(ref base) => check_expr(fcx, &**base),
3067 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3069 let tcx = fcx.ccx.tcx;
3072 ast::ExprBox(ref opt_place, ref subexpr) => {
3073 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3074 check_expr(fcx, &**subexpr);
3076 let mut checked = false;
3077 opt_place.as_ref().map(|place| match place.node {
3078 ast::ExprPath(None, ref path) => {
3079 // FIXME(pcwalton): For now we hardcode the only permissible
3080 // place: the exchange heap.
3081 let definition = lookup_full_def(tcx, path.span, place.id);
3082 let def_id = definition.def_id();
3083 let referent_ty = fcx.expr_ty(&**subexpr);
3084 if tcx.lang_items.exchange_heap() == Some(def_id) {
3085 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3093 span_err!(tcx.sess, expr.span, E0066,
3094 "only the exchange heap is currently supported");
3095 fcx.write_ty(id, tcx.types.err);
3099 ast::ExprLit(ref lit) => {
3100 let typ = check_lit(fcx, &**lit, expected);
3101 fcx.write_ty(id, typ);
3103 ast::ExprBinary(op, ref lhs, ref rhs) => {
3104 op::check_binop(fcx, expr, op, lhs, rhs);
3106 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3107 op::check_binop_assign(fcx, expr, op, lhs, rhs);
3109 ast::ExprUnary(unop, ref oprnd) => {
3110 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3112 ast::UnUniq => match ty.sty {
3113 ty::ty_uniq(ty) => {
3114 Expectation::rvalue_hint(ty)
3120 ast::UnNot | ast::UnNeg => {
3128 let lvalue_pref = match unop {
3129 ast::UnDeref => lvalue_pref,
3132 check_expr_with_expectation_and_lvalue_pref(
3133 fcx, &**oprnd, expected_inner, lvalue_pref);
3134 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3136 if !ty::type_is_error(oprnd_t) {
3139 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3142 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3143 oprnd_t = match ty::deref(oprnd_t, true) {
3145 None => match try_overloaded_deref(fcx, expr.span,
3146 Some(MethodCall::expr(expr.id)),
3147 Some(&**oprnd), oprnd_t, lvalue_pref) {
3150 fcx.type_error_message(expr.span, |actual| {
3151 format!("type `{}` cannot be \
3152 dereferenced", actual)
3160 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3162 if !(ty::type_is_integral(oprnd_t) ||
3163 oprnd_t.sty == ty::ty_bool) {
3164 oprnd_t = op::check_user_unop(fcx, "!", "not",
3165 tcx.lang_items.not_trait(),
3166 expr, &**oprnd, oprnd_t, unop);
3170 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3172 if !(ty::type_is_integral(oprnd_t) ||
3173 ty::type_is_fp(oprnd_t)) {
3174 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3175 tcx.lang_items.neg_trait(),
3176 expr, &**oprnd, oprnd_t, unop);
3178 if let ty::ty_uint(_) = oprnd_t.sty {
3179 if !tcx.sess.features.borrow().negate_unsigned {
3180 feature_gate::emit_feature_err(
3181 &tcx.sess.parse_sess.span_diagnostic,
3184 "unary negation of unsigned integers may be removed in the future");
3190 fcx.write_ty(id, oprnd_t);
3192 ast::ExprAddrOf(mutbl, ref oprnd) => {
3193 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3195 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3196 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3197 // Lvalues may legitimately have unsized types.
3198 // For example, dereferences of a fat pointer and
3199 // the last field of a struct can be unsized.
3200 ExpectHasType(mt.ty)
3202 Expectation::rvalue_hint(mt.ty)
3208 let lvalue_pref = match mutbl {
3209 ast::MutMutable => PreferMutLvalue,
3210 ast::MutImmutable => NoPreference
3212 check_expr_with_expectation_and_lvalue_pref(fcx,
3217 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3218 let oprnd_t = if ty::type_is_error(tm.ty) {
3221 // Note: at this point, we cannot say what the best lifetime
3222 // is to use for resulting pointer. We want to use the
3223 // shortest lifetime possible so as to avoid spurious borrowck
3224 // errors. Moreover, the longest lifetime will depend on the
3225 // precise details of the value whose address is being taken
3226 // (and how long it is valid), which we don't know yet until type
3227 // inference is complete.
3229 // Therefore, here we simply generate a region variable. The
3230 // region inferencer will then select the ultimate value.
3231 // Finally, borrowck is charged with guaranteeing that the
3232 // value whose address was taken can actually be made to live
3233 // as long as it needs to live.
3234 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3235 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3237 fcx.write_ty(id, oprnd_t);
3239 ast::ExprPath(ref maybe_qself, ref path) => {
3240 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3241 fcx.to_ty(&qself.ty)
3244 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3246 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3247 // Create some fake resolution that can't possibly be a type.
3248 def::PathResolution {
3249 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3250 last_private: LastMod(AllPublic),
3251 depth: path.segments.len()
3254 tcx.sess.span_bug(expr.span,
3255 &format!("unbound path {}", expr.repr(tcx)))
3258 if let Some((opt_ty, segments, def)) =
3259 resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
3260 expr.span, expr.id) {
3261 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
3264 instantiate_path(fcx,
3274 // We always require that the type provided as the value for
3275 // a type parameter outlives the moment of instantiation.
3276 constrain_path_type_parameters(fcx, expr);
3278 ast::ExprInlineAsm(ref ia) => {
3279 for &(_, ref input) in &ia.inputs {
3280 check_expr(fcx, &**input);
3282 for &(_, ref out, _) in &ia.outputs {
3283 check_expr(fcx, &**out);
3287 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3288 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3289 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3290 ast::ExprRet(ref expr_opt) => {
3292 ty::FnConverging(result_type) => {
3295 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3296 result_type, ty::mk_nil(fcx.tcx())) {
3297 span_err!(tcx.sess, expr.span, E0069,
3298 "`return;` in a function whose return type is \
3302 check_expr_coercable_to_type(fcx, &**e, result_type);
3306 ty::FnDiverging => {
3307 if let Some(ref e) = *expr_opt {
3308 check_expr(fcx, &**e);
3310 span_err!(tcx.sess, expr.span, E0166,
3311 "`return` in a function declared as diverging");
3314 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3316 ast::ExprParen(ref a) => {
3317 check_expr_with_expectation_and_lvalue_pref(fcx,
3321 fcx.write_ty(id, fcx.expr_ty(&**a));
3323 ast::ExprAssign(ref lhs, ref rhs) => {
3324 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3326 let tcx = fcx.tcx();
3327 if !ty::expr_is_lval(tcx, &**lhs) {
3328 span_err!(tcx.sess, expr.span, E0070,
3329 "illegal left-hand side expression");
3332 let lhs_ty = fcx.expr_ty(&**lhs);
3333 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3334 let rhs_ty = fcx.expr_ty(&**rhs);
3336 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3338 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3339 fcx.write_error(id);
3344 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3345 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3346 id, expr.span, expected);
3348 ast::ExprIfLet(..) => {
3349 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3351 ast::ExprWhile(ref cond, ref body, _) => {
3352 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3353 check_block_no_value(fcx, &**body);
3354 let cond_ty = fcx.expr_ty(&**cond);
3355 let body_ty = fcx.node_ty(body.id);
3356 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3357 fcx.write_error(id);
3363 ast::ExprWhileLet(..) => {
3364 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3366 ast::ExprForLoop(..) => {
3367 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3369 ast::ExprLoop(ref body, _) => {
3370 check_block_no_value(fcx, &**body);
3371 if !may_break(tcx, expr.id, &**body) {
3372 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3377 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3378 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3380 ast::ExprClosure(capture, ref decl, ref body) => {
3381 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3383 ast::ExprBlock(ref b) => {
3384 check_block_with_expected(fcx, &**b, expected);
3385 fcx.write_ty(id, fcx.node_ty(b.id));
3387 ast::ExprCall(ref callee, ref args) => {
3388 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3390 ast::ExprMethodCall(ident, ref tps, ref args) => {
3391 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3392 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3393 let args_err = arg_tys.fold(false,
3395 rest_err || ty::type_is_error(a)});
3397 fcx.write_error(id);
3400 ast::ExprCast(ref e, ref t) => {
3401 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3402 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3405 // Find the type of `e`. Supply hints based on the type we are casting to,
3407 let t_cast = fcx.to_ty(t);
3408 let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
3409 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
3410 let t_expr = fcx.expr_ty(e);
3412 // Eagerly check for some obvious errors.
3413 if ty::type_is_error(t_expr) {
3414 fcx.write_error(id);
3415 } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
3416 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
3418 // Write a type for the whole expression, assuming everything is going
3420 fcx.write_ty(id, t_cast);
3422 // Defer other checks until we're done type checking.
3423 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3424 let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span);
3425 deferred_cast_checks.push(cast_check);
3428 ast::ExprVec(ref args) => {
3429 let uty = expected.to_option(fcx).and_then(|uty| {
3431 ty::ty_vec(ty, _) => Some(ty),
3436 let typ = match uty {
3439 check_expr_coercable_to_type(fcx, &**e, uty);
3444 let t: Ty = fcx.infcx().next_ty_var();
3446 check_expr_has_type(fcx, &**e, t);
3451 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3452 fcx.write_ty(id, typ);
3454 ast::ExprRepeat(ref element, ref count_expr) => {
3455 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3456 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3458 let uty = match expected {
3459 ExpectHasType(uty) => {
3461 ty::ty_vec(ty, _) => Some(ty),
3468 let (element_ty, t) = match uty {
3470 check_expr_coercable_to_type(fcx, &**element, uty);
3474 let t: Ty = fcx.infcx().next_ty_var();
3475 check_expr_has_type(fcx, &**element, t);
3476 (fcx.expr_ty(&**element), t)
3481 // For [foo, ..n] where n > 1, `foo` must have
3483 fcx.require_type_meets(
3490 if ty::type_is_error(element_ty) {
3491 fcx.write_error(id);
3493 let t = ty::mk_vec(tcx, t, Some(count));
3494 fcx.write_ty(id, t);
3497 ast::ExprTup(ref elts) => {
3498 let flds = expected.only_has_type(fcx).and_then(|ty| {
3500 ty::ty_tup(ref flds) => Some(&flds[..]),
3504 let mut err_field = false;
3506 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3507 let t = match flds {
3508 Some(ref fs) if i < fs.len() => {
3510 check_expr_coercable_to_type(fcx, &**e, ety);
3514 check_expr_with_expectation(fcx, &**e, NoExpectation);
3518 err_field = err_field || ty::type_is_error(t);
3522 fcx.write_error(id);
3524 let typ = ty::mk_tup(tcx, elt_ts);
3525 fcx.write_ty(id, typ);
3528 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3529 // Resolve the path.
3530 let def = lookup_full_def(tcx, path.span, id);
3531 let struct_id = match def {
3532 def::DefVariant(enum_id, variant_id, true) => {
3533 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3534 variant_id, &fields[..]);
3537 def::DefTrait(def_id) => {
3538 span_err!(tcx.sess, path.span, E0159,
3539 "use of trait `{}` as a struct constructor",
3540 pprust::path_to_string(path));
3541 check_struct_fields_on_error(fcx,
3548 // Verify that this was actually a struct.
3549 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3551 ty::ty_struct(struct_did, _) => {
3552 check_struct_constructor(fcx,
3557 base_expr.as_ref().map(|e| &**e));
3560 span_err!(tcx.sess, path.span, E0071,
3561 "`{}` does not name a structure",
3562 pprust::path_to_string(path));
3563 check_struct_fields_on_error(fcx,
3574 // Turn the path into a type and verify that that type unifies with
3575 // the resulting structure type. This is needed to handle type
3576 // parameters correctly.
3577 let actual_structure_type = fcx.expr_ty(&*expr);
3578 if !ty::type_is_error(actual_structure_type) {
3579 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3580 match fcx.mk_subty(false,
3581 infer::Misc(path.span),
3582 actual_structure_type,
3583 type_and_substs.ty) {
3585 Err(type_error) => {
3586 let type_error_description =
3587 ty::type_err_to_str(tcx, &type_error);
3588 span_err!(fcx.tcx().sess, path.span, E0235,
3589 "structure constructor specifies a \
3590 structure of type `{}`, but this \
3591 structure has type `{}`: {}",
3593 .ty_to_string(type_and_substs.ty),
3596 actual_structure_type),
3597 type_error_description);
3598 ty::note_and_explain_type_err(tcx, &type_error, path.span);
3603 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3605 ast::ExprField(ref base, ref field) => {
3606 check_field(fcx, expr, lvalue_pref, &**base, field);
3608 ast::ExprTupField(ref base, idx) => {
3609 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3611 ast::ExprIndex(ref base, ref idx) => {
3612 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3613 check_expr(fcx, &**idx);
3615 let base_t = fcx.expr_ty(&**base);
3616 let idx_t = fcx.expr_ty(&**idx);
3618 if ty::type_is_error(base_t) {
3619 fcx.write_ty(id, base_t);
3620 } else if ty::type_is_error(idx_t) {
3621 fcx.write_ty(id, idx_t);
3623 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3624 match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3625 Some((index_ty, element_ty)) => {
3626 let idx_expr_ty = fcx.expr_ty(idx);
3627 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3628 fcx.write_ty(id, element_ty);
3631 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3632 fcx.type_error_message(
3635 format!("cannot index a value of type `{}`",
3640 fcx.write_ty(id, fcx.tcx().types.err);
3645 ast::ExprRange(ref start, ref end) => {
3646 let t_start = start.as_ref().map(|e| {
3647 check_expr(fcx, &**e);
3650 let t_end = end.as_ref().map(|e| {
3651 check_expr(fcx, &**e);
3655 let idx_type = match (t_start, t_end) {
3656 (Some(ty), None) | (None, Some(ty)) => {
3659 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3660 ty::type_is_error(t_end)) => {
3661 Some(fcx.tcx().types.err)
3663 (Some(t_start), Some(t_end)) => {
3664 Some(infer::common_supertype(fcx.infcx(),
3665 infer::RangeExpression(expr.span),
3673 // Note that we don't check the type of start/end satisfy any
3674 // bounds because right now the range structs do not have any. If we add
3675 // some bounds, then we'll need to check `t_start` against them here.
3677 let range_type = match idx_type {
3678 Some(idx_type) if ty::type_is_error(idx_type) => {
3682 // Find the did from the appropriate lang item.
3683 let did = match (start, end) {
3684 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3685 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3686 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3688 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3692 if let Some(did) = did {
3693 let predicates = ty::lookup_predicates(tcx, did);
3694 let substs = Substs::new_type(vec![idx_type], vec![]);
3695 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
3696 fcx.add_obligations_for_parameters(
3697 traits::ObligationCause::new(expr.span,
3699 traits::ItemObligation(did)),
3702 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3704 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
3709 // Neither start nor end => RangeFull
3710 if let Some(did) = tcx.lang_items.range_full_struct() {
3711 let substs = Substs::new_type(vec![], vec![]);
3712 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3714 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
3720 fcx.write_ty(id, range_type);
3725 debug!("type of expr({}) {} is...", expr.id,
3726 syntax::print::pprust::expr_to_string(expr));
3727 debug!("... {}, expected is {}",
3728 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3729 expected.repr(tcx));
3734 pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
3735 path_res: def::PathResolution,
3736 opt_self_ty: Option<Ty<'tcx>>,
3737 path: &'a ast::Path,
3739 node_id: ast::NodeId)
3740 -> Option<(Option<Ty<'tcx>>,
3741 &'a [ast::PathSegment],
3744 // If fully resolved already, we don't have to do anything.
3745 if path_res.depth == 0 {
3746 Some((opt_self_ty, &path.segments, path_res.base_def))
3748 let mut def = path_res.base_def;
3749 let ty_segments = path.segments.init();
3750 let base_ty_end = path.segments.len() - path_res.depth;
3751 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
3752 PathParamMode::Optional,
3755 &ty_segments[..base_ty_end],
3756 &ty_segments[base_ty_end..]);
3757 let item_segment = path.segments.last().unwrap();
3758 let item_name = item_segment.identifier.name;
3759 match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
3761 // Write back the new resolution.
3762 fcx.ccx.tcx.def_map.borrow_mut()
3763 .insert(node_id, def::PathResolution {
3765 last_private: path_res.last_private.or(lp),
3768 Some((Some(ty), slice::ref_slice(item_segment), def))
3771 method::report_error(fcx, span, ty,
3772 item_name, None, error);
3773 fcx.write_error(node_id);
3780 fn constrain_path_type_parameters(fcx: &FnCtxt,
3783 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3784 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3788 impl<'tcx> Expectation<'tcx> {
3789 /// Provide an expectation for an rvalue expression given an *optional*
3790 /// hint, which is not required for type safety (the resulting type might
3791 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3792 /// is useful in determining the concrete type.
3794 /// The primary use case is where the expected type is a fat pointer,
3795 /// like `&[isize]`. For example, consider the following statement:
3797 /// let x: &[isize] = &[1, 2, 3];
3799 /// In this case, the expected type for the `&[1, 2, 3]` expression is
3800 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3801 /// expectation `ExpectHasType([isize])`, that would be too strong --
3802 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3803 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3804 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3805 /// which still is useful, because it informs integer literals and the like.
3806 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3807 /// for examples of where this comes up,.
3808 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
3810 ty::ty_vec(_, None) | ty::ty_trait(..) => {
3811 ExpectRvalueLikeUnsized(ty)
3813 _ => ExpectHasType(ty)
3817 // Resolves `expected` by a single level if it is a variable. If
3818 // there is no expected type or resolution is not possible (e.g.,
3819 // no constraints yet present), just returns `None`.
3820 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3825 ExpectCastableToType(t) => {
3826 ExpectCastableToType(
3827 fcx.infcx().resolve_type_vars_if_possible(&t))
3829 ExpectHasType(t) => {
3831 fcx.infcx().resolve_type_vars_if_possible(&t))
3833 ExpectRvalueLikeUnsized(t) => {
3834 ExpectRvalueLikeUnsized(
3835 fcx.infcx().resolve_type_vars_if_possible(&t))
3840 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3841 match self.resolve(fcx) {
3842 NoExpectation => None,
3843 ExpectCastableToType(ty) |
3845 ExpectRvalueLikeUnsized(ty) => Some(ty),
3849 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3850 match self.resolve(fcx) {
3851 ExpectHasType(ty) => Some(ty),
3857 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
3858 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
3860 NoExpectation => format!("NoExpectation"),
3861 ExpectHasType(t) => format!("ExpectHasType({})",
3863 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3865 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
3871 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3872 local: &'tcx ast::Local,
3873 init: &'tcx ast::Expr)
3875 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
3877 let local_ty = fcx.local_ty(init.span, local.id);
3879 check_expr_coercable_to_type(fcx, init, local_ty)
3881 // Somewhat subtle: if we have a `ref` binding in the pattern,
3882 // we want to avoid introducing coercions for the RHS. This is
3883 // both because it helps preserve sanity and, in the case of
3884 // ref mut, for soundness (issue #23116). In particular, in
3885 // the latter case, we need to be clear that the type of the
3886 // referent for the reference that results is *equal to* the
3887 // type of the lvalue it is referencing, and not some
3888 // supertype thereof.
3889 check_expr(fcx, init);
3890 let init_ty = fcx.expr_ty(init);
3891 demand::eqtype(fcx, init.span, init_ty, local_ty);
3895 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
3896 let tcx = fcx.ccx.tcx;
3898 let t = fcx.local_ty(local.span, local.id);
3899 fcx.write_ty(local.id, t);
3901 if let Some(ref init) = local.init {
3902 check_decl_initializer(fcx, local, &**init);
3903 let init_ty = fcx.expr_ty(&**init);
3904 if ty::type_is_error(init_ty) {
3905 fcx.write_ty(local.id, init_ty);
3909 let pcx = pat_ctxt {
3911 map: pat_id_map(&tcx.def_map, &*local.pat),
3913 _match::check_pat(&pcx, &*local.pat, t);
3914 let pat_ty = fcx.node_ty(local.pat.id);
3915 if ty::type_is_error(pat_ty) {
3916 fcx.write_ty(local.id, pat_ty);
3920 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
3922 let mut saw_bot = false;
3923 let mut saw_err = false;
3925 ast::StmtDecl(ref decl, id) => {
3928 ast::DeclLocal(ref l) => {
3929 check_decl_local(fcx, &**l);
3930 let l_t = fcx.node_ty(l.id);
3931 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
3932 saw_err = saw_err || ty::type_is_error(l_t);
3934 ast::DeclItem(_) => {/* ignore for now */ }
3937 ast::StmtExpr(ref expr, id) => {
3939 // Check with expected type of ()
3940 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
3941 let expr_ty = fcx.expr_ty(&**expr);
3942 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
3943 saw_err = saw_err || ty::type_is_error(expr_ty);
3945 ast::StmtSemi(ref expr, id) => {
3947 check_expr(fcx, &**expr);
3948 let expr_ty = fcx.expr_ty(&**expr);
3949 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
3950 saw_err |= ty::type_is_error(expr_ty);
3952 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3955 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
3958 fcx.write_error(node_id);
3961 fcx.write_nil(node_id)
3965 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
3966 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
3967 let blkty = fcx.node_ty(blk.id);
3968 if ty::type_is_error(blkty) {
3969 fcx.write_error(blk.id);
3971 let nilty = ty::mk_nil(fcx.tcx());
3972 demand::suptype(fcx, blk.span, nilty, blkty);
3976 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3977 blk: &'tcx ast::Block,
3978 expected: Expectation<'tcx>) {
3980 let mut fcx_ps = fcx.ps.borrow_mut();
3981 let unsafety_state = fcx_ps.recurse(blk);
3982 replace(&mut *fcx_ps, unsafety_state)
3985 let mut warned = false;
3986 let mut any_diverges = false;
3987 let mut any_err = false;
3988 for s in &blk.stmts {
3989 check_stmt(fcx, &**s);
3990 let s_id = ast_util::stmt_id(&**s);
3991 let s_ty = fcx.node_ty(s_id);
3992 if any_diverges && !warned && match s.node {
3993 ast::StmtDecl(ref decl, _) => {
3995 ast::DeclLocal(_) => true,
3999 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4005 .add_lint(lint::builtin::UNREACHABLE_CODE,
4008 "unreachable statement".to_string());
4011 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4012 any_err = any_err || ty::type_is_error(s_ty);
4015 None => if any_err {
4016 fcx.write_error(blk.id);
4017 } else if any_diverges {
4018 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4020 fcx.write_nil(blk.id);
4023 if any_diverges && !warned {
4027 .add_lint(lint::builtin::UNREACHABLE_CODE,
4030 "unreachable expression".to_string());
4032 let ety = match expected {
4033 ExpectHasType(ety) => {
4034 check_expr_coercable_to_type(fcx, &**e, ety);
4038 check_expr_with_expectation(fcx, &**e, expected);
4044 fcx.write_error(blk.id);
4045 } else if any_diverges {
4046 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4048 fcx.write_ty(blk.id, ety);
4053 *fcx.ps.borrow_mut() = prev;
4056 /// Checks a constant appearing in a type. At the moment this is just the
4057 /// length expression in a fixed-length vector, but someday it might be
4058 /// extended to type-level numeric literals.
4059 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4060 expr: &'tcx ast::Expr,
4061 expected_type: Ty<'tcx>) {
4062 let inh = static_inherited_fields(ccx);
4063 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4064 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4067 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4071 let inh = static_inherited_fields(ccx);
4072 let rty = ty::node_id_to_type(ccx.tcx, id);
4073 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4074 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
4075 check_const_with_ty(&fcx, sp, e, declty);
4078 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4082 // Gather locals in statics (because of block expressions).
4083 // This is technically unnecessary because locals in static items are forbidden,
4084 // but prevents type checking from blowing up before const checking can properly
4086 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4088 check_expr_with_hint(fcx, e, declty);
4089 demand::coerce(fcx, e.span, declty, e);
4090 fcx.select_all_obligations_or_error();
4092 regionck::regionck_expr(fcx, e);
4093 writeback::resolve_type_vars_in_expr(fcx, e);
4096 /// Checks whether a type can be represented in memory. In particular, it
4097 /// identifies types that contain themselves without indirection through a
4098 /// pointer, which would mean their size is unbounded. This is different from
4099 /// the question of whether a type can be instantiated. See the definition of
4100 /// `check_instantiable`.
4101 pub fn check_representable(tcx: &ty::ctxt,
4103 item_id: ast::NodeId,
4104 designation: &str) -> bool {
4105 let rty = ty::node_id_to_type(tcx, item_id);
4107 // Check that it is possible to represent this type. This call identifies
4108 // (1) types that contain themselves and (2) types that contain a different
4109 // recursive type. It is only necessary to throw an error on those that
4110 // contain themselves. For case 2, there must be an inner type that will be
4111 // caught by case 1.
4112 match ty::is_type_representable(tcx, sp, rty) {
4113 ty::SelfRecursive => {
4114 span_err!(tcx.sess, sp, E0072,
4115 "illegal recursive {} type; \
4116 wrap the inner value in a box to make it representable",
4120 ty::Representable | ty::ContainsRecursive => (),
4125 /// Checks whether a type can be created without an instance of itself.
4126 /// This is similar but different from the question of whether a type
4127 /// can be represented. For example, the following type:
4129 /// enum foo { None, Some(foo) }
4131 /// is instantiable but is not representable. Similarly, the type
4133 /// enum foo { Some(@foo) }
4135 /// is representable, but not instantiable.
4136 pub fn check_instantiable(tcx: &ty::ctxt,
4138 item_id: ast::NodeId)
4140 let item_ty = ty::node_id_to_type(tcx, item_id);
4141 if !ty::is_instantiable(tcx, item_ty) {
4142 span_err!(tcx.sess, sp, E0073,
4143 "this type cannot be instantiated without an \
4144 instance of itself");
4145 fileline_help!(tcx.sess, sp, "consider using `Option<{}>`",
4146 ppaux::ty_to_string(tcx, item_ty));
4153 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4154 let t = ty::node_id_to_type(tcx, id);
4155 if ty::type_needs_subst(t) {
4156 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4160 ty::ty_struct(did, substs) => {
4161 let fields = ty::lookup_struct_fields(tcx, did);
4162 if fields.is_empty() {
4163 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4166 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4167 if !fields.iter().all(
4168 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4169 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4172 if !ty::type_is_machine(e) {
4173 span_err!(tcx.sess, sp, E0077,
4174 "SIMD vector element type should be machine type");
4182 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4184 vs: &'tcx [P<ast::Variant>],
4187 fn disr_in_range(ccx: &CrateCtxt,
4189 disr: ty::Disr) -> bool {
4190 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4192 ast::TyU8 => disr as u8 as Disr == disr,
4193 ast::TyU16 => disr as u16 as Disr == disr,
4194 ast::TyU32 => disr as u32 as Disr == disr,
4195 ast::TyU64 => disr as u64 as Disr == disr,
4196 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4199 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4201 ast::TyI8 => disr as i8 as Disr == disr,
4202 ast::TyI16 => disr as i16 as Disr == disr,
4203 ast::TyI32 => disr as i32 as Disr == disr,
4204 ast::TyI64 => disr as i64 as Disr == disr,
4205 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4209 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4210 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4214 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4215 vs: &'tcx [P<ast::Variant>],
4217 hint: attr::ReprAttr) {
4218 #![allow(trivial_numeric_casts)]
4220 let rty = ty::node_id_to_type(ccx.tcx, id);
4221 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4223 let inh = static_inherited_fields(ccx);
4224 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
4226 let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint));
4228 if let Some(ref e) = v.node.disr_expr {
4229 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
4233 let def_id = local_def(id);
4235 // ty::enum_variants guards against discriminant overflows, so
4236 // we need not check for that.
4237 let variants = ty::enum_variants(ccx.tcx, def_id);
4239 for (v, variant) in vs.iter().zip(variants.iter()) {
4240 let current_disr_val = variant.disr_val;
4242 // Check for duplicate discriminant values
4243 match disr_vals.iter().position(|&x| x == current_disr_val) {
4245 span_err!(ccx.tcx.sess, v.span, E0081,
4246 "discriminant value `{}` already exists", disr_vals[i]);
4247 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4248 "conflicting discriminant here")
4252 // Check for unrepresentable discriminant values
4254 attr::ReprAny | attr::ReprExtern => (),
4255 attr::ReprInt(sp, ity) => {
4256 if !disr_in_range(ccx, ity, current_disr_val) {
4257 span_err!(ccx.tcx.sess, v.span, E0082,
4258 "discriminant value outside specified type");
4259 span_note!(ccx.tcx.sess, sp,
4260 "discriminant type specified here");
4263 attr::ReprPacked => {
4264 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4267 disr_vals.push(current_disr_val);
4271 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4272 .get(0).unwrap_or(&attr::ReprAny);
4274 if hint != attr::ReprAny && vs.len() <= 1 {
4276 span_err!(ccx.tcx.sess, sp, E0083,
4277 "unsupported representation for univariant enum");
4279 span_err!(ccx.tcx.sess, sp, E0084,
4280 "unsupported representation for zero-variant enum");
4284 do_check(ccx, vs, id, hint);
4286 check_representable(ccx.tcx, sp, id, "enum");
4288 // Check that it is possible to instantiate this enum:
4290 // This *sounds* like the same that as representable, but it's
4291 // not. See def'n of `check_instantiable()` for details.
4292 check_instantiable(ccx.tcx, sp, id);
4295 // Returns the type parameter count and the type for the given definition.
4296 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4299 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4301 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4302 let typ = fcx.local_ty(sp, nid);
4303 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4304 ty::GenericPredicates::empty())
4306 def::DefFn(id, _) | def::DefMethod(id, _) |
4307 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4308 def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
4309 (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4313 def::DefAssociatedTy(..) |
4315 def::DefTyParam(..) |
4317 def::DefForeignMod(..) |
4319 def::DefRegion(..) |
4321 def::DefSelfTy(..) => {
4322 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4327 // Instantiates the given path, which must refer to an item with the given
4328 // number of type parameters and type.
4329 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4330 segments: &[ast::PathSegment],
4331 type_scheme: TypeScheme<'tcx>,
4332 type_predicates: &ty::GenericPredicates<'tcx>,
4333 opt_self_ty: Option<Ty<'tcx>>,
4336 node_id: ast::NodeId) {
4337 debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
4339 def.repr(fcx.tcx()),
4341 type_scheme.repr(fcx.tcx()));
4343 // We need to extract the type parameters supplied by the user in
4344 // the path `path`. Due to the current setup, this is a bit of a
4345 // tricky-process; the problem is that resolve only tells us the
4346 // end-point of the path resolution, and not the intermediate steps.
4347 // Luckily, we can (at least for now) deduce the intermediate steps
4348 // just from the end-point.
4350 // There are basically four cases to consider:
4352 // 1. Reference to a *type*, such as a struct or enum:
4354 // mod a { struct Foo<T> { ... } }
4356 // Because we don't allow types to be declared within one
4357 // another, a path that leads to a type will always look like
4358 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4359 // that only the final segment can have type parameters, and
4360 // they are located in the TypeSpace.
4362 // *Note:* Generally speaking, references to types don't
4363 // actually pass through this function, but rather the
4364 // `ast_ty_to_ty` function in `astconv`. However, in the case
4365 // of struct patterns (and maybe literals) we do invoke
4366 // `instantiate_path` to get the general type of an instance of
4367 // a struct. (In these cases, there are actually no type
4368 // parameters permitted at present, but perhaps we will allow
4369 // them in the future.)
4371 // 1b. Reference to a enum variant or tuple-like struct:
4373 // struct foo<T>(...)
4374 // enum E<T> { foo(...) }
4376 // In these cases, the parameters are declared in the type
4379 // 2. Reference to a *fn item*:
4383 // In this case, the path will again always have the form
4384 // `a::b::foo::<T>` where only the final segment should have
4385 // type parameters. However, in this case, those parameters are
4386 // declared on a value, and hence are in the `FnSpace`.
4388 // 3. Reference to a *method*:
4390 // impl<A> SomeStruct<A> {
4394 // Here we can have a path like
4395 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4396 // may appear in two places. The penultimate segment,
4397 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4398 // final segment, `foo::<B>` contains parameters in fn space.
4400 // 4. Reference to an *associated const*:
4402 // impl<A> AnotherStruct<A> {
4403 // const FOO: B = BAR;
4406 // The path in this case will look like
4407 // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
4408 // only will have parameters in TypeSpace.
4410 // The first step then is to categorize the segments appropriately.
4412 assert!(!segments.is_empty());
4414 let mut ufcs_method = None;
4415 let mut segment_spaces: Vec<_>;
4417 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4418 def::DefSelfTy(..) |
4419 def::DefStruct(..) |
4420 def::DefVariant(..) |
4422 def::DefAssociatedTy(..) |
4424 def::DefPrimTy(..) |
4425 def::DefTyParam(..) => {
4426 // Everything but the final segment should have no
4427 // parameters at all.
4428 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4429 segment_spaces.push(Some(subst::TypeSpace));
4432 // Case 2. Reference to a top-level value.
4435 def::DefStatic(..) => {
4436 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4437 segment_spaces.push(Some(subst::FnSpace));
4440 // Case 3. Reference to a method.
4441 def::DefMethod(_, provenance) => {
4443 def::FromTrait(trait_did) => {
4444 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4446 def::FromImpl(_) => {}
4449 if segments.len() >= 2 {
4450 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4451 segment_spaces.push(Some(subst::TypeSpace));
4452 segment_spaces.push(Some(subst::FnSpace));
4454 // `<T>::method` will end up here, and so can `T::method`.
4455 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4456 segment_spaces = vec![Some(subst::FnSpace)];
4457 ufcs_method = Some((provenance, self_ty));
4461 def::DefAssociatedConst(_, provenance) => {
4463 def::FromTrait(trait_did) => {
4464 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4466 def::FromImpl(_) => {}
4469 if segments.len() >= 2 {
4470 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4471 segment_spaces.push(Some(subst::TypeSpace));
4472 segment_spaces.push(None);
4474 segment_spaces = vec![None];
4478 // Other cases. Various nonsense that really shouldn't show up
4479 // here. If they do, an error will have been reported
4480 // elsewhere. (I hope)
4482 def::DefForeignMod(..) |
4485 def::DefRegion(..) |
4487 def::DefUpvar(..) => {
4488 segment_spaces = repeat(None).take(segments.len()).collect();
4491 assert_eq!(segment_spaces.len(), segments.len());
4493 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4494 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4495 // type parameters are not mandatory.
4496 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
4498 debug!("segment_spaces={:?}", segment_spaces);
4500 // Next, examine the definition, and determine how many type
4501 // parameters we expect from each space.
4502 let type_defs = &type_scheme.generics.types;
4503 let region_defs = &type_scheme.generics.regions;
4505 // Now that we have categorized what space the parameters for each
4506 // segment belong to, let's sort out the parameters that the user
4507 // provided (if any) into their appropriate spaces. We'll also report
4508 // errors if type parameters are provided in an inappropriate place.
4509 let mut substs = Substs::empty();
4510 for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
4513 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4514 NO_TPS | NO_REGIONS);
4518 push_explicit_parameters_from_segment_to_substs(fcx,
4528 if let Some(self_ty) = opt_self_ty {
4529 if type_defs.len(subst::SelfSpace) == 1 {
4530 substs.types.push(subst::SelfSpace, self_ty);
4534 // Now we have to compare the types that the user *actually*
4535 // provided against the types that were *expected*. If the user
4536 // did not provide any types, then we want to substitute inference
4537 // variables. If the user provided some types, we may still need
4538 // to add defaults. If the user provided *too many* types, that's
4540 for &space in &ParamSpace::all() {
4541 adjust_type_parameters(fcx, span, space, type_defs,
4542 require_type_space, &mut substs);
4543 assert_eq!(substs.types.len(space), type_defs.len(space));
4545 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4546 assert_eq!(substs.regions().len(space), region_defs.len(space));
4549 // The things we are substituting into the type should not contain
4550 // escaping late-bound regions, and nor should the base type scheme.
4551 assert!(!substs.has_regions_escaping_depth(0));
4552 assert!(!type_scheme.has_escaping_regions());
4554 // Add all the obligations that are required, substituting and
4555 // normalized appropriately.
4556 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4557 fcx.add_obligations_for_parameters(
4558 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4561 // Substitute the values for the type parameters into the type of
4562 // the referenced item.
4563 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4566 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4567 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4568 // is inherent, there is no `Self` parameter, instead, the impl needs
4569 // type parameters, which we can infer by unifying the provided `Self`
4570 // with the substituted impl type.
4571 let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
4572 assert_eq!(substs.types.len(subst::TypeSpace),
4573 impl_scheme.generics.types.len(subst::TypeSpace));
4574 assert_eq!(substs.regions().len(subst::TypeSpace),
4575 impl_scheme.generics.regions.len(subst::TypeSpace));
4577 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4578 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4579 fcx.tcx().sess.span_bug(span,
4581 "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
4582 self_ty.repr(fcx.tcx()),
4583 impl_ty.repr(fcx.tcx())));
4587 fcx.write_ty(node_id, ty_substituted);
4588 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4591 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4592 /// parameters are provided, then reports an error and clears the output vector.
4594 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4595 /// use inference variables. This seems less likely to lead to derived errors.
4597 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4598 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4599 /// here because we can easily use the precise span of the N+1'th parameter.
4600 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4601 fcx: &FnCtxt<'a, 'tcx>,
4602 space: subst::ParamSpace,
4604 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4605 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4606 segment: &ast::PathSegment,
4607 substs: &mut Substs<'tcx>)
4609 match segment.parameters {
4610 ast::AngleBracketedParameters(ref data) => {
4611 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4612 fcx, space, type_defs, region_defs, data, substs);
4615 ast::ParenthesizedParameters(ref data) => {
4616 span_err!(fcx.tcx().sess, span, E0238,
4617 "parenthesized parameters may only be used with a trait");
4618 push_explicit_parenthesized_parameters_from_segment_to_substs(
4619 fcx, space, span, type_defs, data, substs);
4624 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4625 fcx: &FnCtxt<'a, 'tcx>,
4626 space: subst::ParamSpace,
4627 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4628 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4629 data: &ast::AngleBracketedParameterData,
4630 substs: &mut Substs<'tcx>)
4633 let type_count = type_defs.len(space);
4634 assert_eq!(substs.types.len(space), 0);
4635 for (i, typ) in data.types.iter().enumerate() {
4636 let t = fcx.to_ty(&**typ);
4638 substs.types.push(space, t);
4639 } else if i == type_count {
4640 span_err!(fcx.tcx().sess, typ.span, E0087,
4641 "too many type parameters provided: \
4642 expected at most {} parameter(s), \
4643 found {} parameter(s)",
4644 type_count, data.types.len());
4645 substs.types.truncate(space, 0);
4651 if !data.bindings.is_empty() {
4652 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4653 "unexpected binding of associated item in expression path \
4654 (only allowed in type paths)");
4658 let region_count = region_defs.len(space);
4659 assert_eq!(substs.regions().len(space), 0);
4660 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4661 let r = ast_region_to_region(fcx.tcx(), lifetime);
4662 if i < region_count {
4663 substs.mut_regions().push(space, r);
4664 } else if i == region_count {
4665 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4666 "too many lifetime parameters provided: \
4667 expected {} parameter(s), found {} parameter(s)",
4669 data.lifetimes.len());
4670 substs.mut_regions().truncate(space, 0);
4678 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4679 /// but intended for `Foo(A,B) -> C` form. This expands to
4680 /// roughly the same thing as `Foo<(A,B),C>`. One important
4681 /// difference has to do with the treatment of anonymous
4682 /// regions, which are translated into bound regions (NYI).
4683 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4684 fcx: &FnCtxt<'a, 'tcx>,
4685 space: subst::ParamSpace,
4687 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4688 data: &ast::ParenthesizedParameterData,
4689 substs: &mut Substs<'tcx>)
4691 let type_count = type_defs.len(space);
4693 span_err!(fcx.tcx().sess, span, E0167,
4694 "parenthesized form always supplies 2 type parameters, \
4695 but only {} parameter(s) were expected",
4699 let input_tys: Vec<Ty> =
4700 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4703 ty::mk_tup(fcx.tcx(), input_tys);
4705 if type_count >= 1 {
4706 substs.types.push(space, tuple_ty);
4709 let output_ty: Option<Ty> =
4710 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4713 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4715 if type_count >= 2 {
4716 substs.types.push(space, output_ty);
4720 fn adjust_type_parameters<'a, 'tcx>(
4721 fcx: &FnCtxt<'a, 'tcx>,
4724 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4725 require_type_space: bool,
4726 substs: &mut Substs<'tcx>)
4728 let provided_len = substs.types.len(space);
4729 let desired = defs.get_slice(space);
4730 let required_len = desired.iter()
4731 .take_while(|d| d.default.is_none())
4734 debug!("adjust_type_parameters(space={:?}, \
4743 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4744 assert!(provided_len <= desired.len());
4746 // Nothing specified at all: supply inference variables for
4748 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4749 substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
4753 // Too few parameters specified: report an error and use Err
4755 if provided_len < required_len {
4757 if desired.len() != required_len { "at least " } else { "" };
4758 span_err!(fcx.tcx().sess, span, E0089,
4759 "too few type parameters provided: expected {}{} parameter(s) \
4760 , found {} parameter(s)",
4761 qualifier, required_len, provided_len);
4762 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
4766 // Otherwise, add in any optional parameters that the user
4767 // omitted. The case of *too many* parameters is handled
4769 // push_explicit_parameters_from_segment_to_substs(). Note
4770 // that the *default* type are expressed in terms of all prior
4771 // parameters, so we have to substitute as we go with the
4772 // partial substitution that we have built up.
4773 for i in provided_len..desired.len() {
4774 let default = desired[i].default.unwrap();
4775 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4776 substs.types.push(space, default);
4778 assert_eq!(substs.types.len(space), desired.len());
4780 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4783 fn adjust_region_parameters(
4787 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4788 substs: &mut Substs)
4790 let provided_len = substs.mut_regions().len(space);
4791 let desired = defs.get_slice(space);
4793 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4794 assert!(provided_len <= desired.len());
4796 // If nothing was provided, just use inference variables.
4797 if provided_len == 0 {
4798 substs.mut_regions().replace(
4800 fcx.infcx().region_vars_for_defs(span, desired));
4804 // If just the right number were provided, everybody is happy.
4805 if provided_len == desired.len() {
4809 // Otherwise, too few were provided. Report an error and then
4810 // use inference variables.
4811 span_err!(fcx.tcx().sess, span, E0090,
4812 "too few lifetime parameters provided: expected {} parameter(s), \
4813 found {} parameter(s)",
4814 desired.len(), provided_len);
4816 substs.mut_regions().replace(
4818 fcx.infcx().region_vars_for_defs(span, desired));
4822 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4826 where F: Fn() -> Ty<'tcx>
4828 let mut ty = fcx.resolve_type_vars_if_possible(ty);
4830 if ty::type_is_ty_var(ty) {
4831 let alternative = f();
4834 if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
4835 fcx.type_error_message(sp, |_actual| {
4836 "the type of this value must be known in this context".to_string()
4838 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4839 ty = fcx.tcx().types.err;
4841 demand::suptype(fcx, sp, alternative, ty);
4849 // Resolves `typ` by a single level if `typ` is a type variable. If no
4850 // resolution is possible, then an error is reported.
4851 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4856 structurally_resolve_type_or_else(fcx, sp, ty, || {
4861 // Returns true if b contains a break that can exit from b
4862 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4863 // First: is there an unlabeled break immediately
4865 (loop_query(&*b, |e| {
4867 ast::ExprBreak(None) => true,
4871 // Second: is there a labeled break with label
4872 // <id> nested anywhere inside the loop?
4873 (block_query(b, |e| {
4874 if let ast::ExprBreak(Some(_)) = e.node {
4875 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
4882 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4884 tps: &OwnedSlice<ast::TyParam>,
4886 debug!("check_bounds_are_used(n_tps={}, ty={})",
4887 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4889 // make a vector of booleans initially false, set to true when used
4890 if tps.is_empty() { return; }
4891 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
4893 ty::walk_ty(ty, |t| {
4895 ty::ty_param(ParamTy {idx, ..}) => {
4896 debug!("Found use of ty param num {}", idx);
4897 tps_used[idx as usize] = true;
4903 for (i, b) in tps_used.iter().enumerate() {
4905 span_err!(ccx.tcx.sess, span, E0091,
4906 "type parameter `{}` is unused",
4907 token::get_ident(tps[i].ident));
4912 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
4913 /// and in libcore/intrinsics.rs
4914 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4915 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
4916 let name = token::intern(&format!("P{}", n));
4917 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
4921 let name = token::get_ident(it.ident);
4922 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
4923 let split : Vec<&str> = name.split('_').collect();
4924 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4926 //We only care about the operation here
4927 let (n_tps, inputs, output) = match split[1] {
4928 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4932 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4934 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4937 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4938 "min" | "umax" | "umin" => {
4939 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4942 "fence" | "singlethreadfence" => {
4943 (0, Vec::new(), ty::mk_nil(tcx))
4946 span_err!(tcx.sess, it.span, E0092,
4947 "unrecognized atomic operation function: `{}`", op);
4951 (n_tps, inputs, ty::FnConverging(output))
4952 } else if &name[..] == "abort" || &name[..] == "unreachable" {
4953 (0, Vec::new(), ty::FnDiverging)
4955 let (n_tps, inputs, output) = match &name[..] {
4956 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
4958 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
4959 "size_of_val" | "min_align_of_val" => {
4961 ty::mk_imm_rptr(tcx,
4962 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
4965 ], ccx.tcx.types.usize)
4967 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
4968 "uninit" => (1, Vec::new(), param(ccx, 0)),
4969 "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
4970 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4971 "move_val_init" => {
4974 ty::mk_mut_rptr(tcx,
4975 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
4982 "drop_in_place" => {
4983 (1, vec![ty::mk_mut_ptr(tcx, param(ccx, 0))], ty::mk_nil(tcx))
4985 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
4987 "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
4988 ast::MutImmutable)),
4989 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
4990 "offset" | "arith_offset" => {
4993 ty::mk_ptr(tcx, ty::mt {
4995 mutbl: ast::MutImmutable
4999 ty::mk_ptr(tcx, ty::mt {
5001 mutbl: ast::MutImmutable
5004 "copy" | "copy_nonoverlapping" => {
5007 ty::mk_ptr(tcx, ty::mt {
5009 mutbl: ast::MutImmutable
5011 ty::mk_ptr(tcx, ty::mt {
5013 mutbl: ast::MutMutable
5019 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5022 ty::mk_ptr(tcx, ty::mt {
5024 mutbl: ast::MutMutable
5026 ty::mk_ptr(tcx, ty::mt {
5028 mutbl: ast::MutImmutable
5034 "write_bytes" | "volatile_set_memory" => {
5037 ty::mk_ptr(tcx, ty::mt {
5039 mutbl: ast::MutMutable
5046 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5047 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5050 vec!( tcx.types.f32, tcx.types.i32 ),
5055 vec!( tcx.types.f64, tcx.types.i32 ),
5058 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5059 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5060 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5061 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5064 vec!( tcx.types.f32, tcx.types.f32 ),
5069 vec!( tcx.types.f64, tcx.types.f64 ),
5072 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5073 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5074 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5075 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5076 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5077 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5078 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5079 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5080 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5081 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5084 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5089 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5092 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5093 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5094 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5095 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5096 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5097 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5098 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5099 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5100 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5101 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5102 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5103 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5104 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5105 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5106 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5107 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5108 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5109 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5110 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5111 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5112 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5113 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5114 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5115 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5116 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5117 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5118 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5119 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5120 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5121 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5122 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5125 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5127 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5129 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5130 (0, vec!(tcx.types.i8, tcx.types.i8),
5131 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5133 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5134 (0, vec!(tcx.types.i16, tcx.types.i16),
5135 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5137 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5138 (0, vec!(tcx.types.i32, tcx.types.i32),
5139 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5141 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5142 (0, vec!(tcx.types.i64, tcx.types.i64),
5143 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5145 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5146 (0, vec!(tcx.types.u8, tcx.types.u8),
5147 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5149 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5150 (0, vec!(tcx.types.u16, tcx.types.u16),
5151 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5153 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5154 (0, vec!(tcx.types.u32, tcx.types.u32),
5155 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5157 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5158 (0, vec!(tcx.types.u64, tcx.types.u64),
5159 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5161 "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
5162 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5164 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5165 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5167 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5169 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5171 "discriminant_value" => (1, vec![
5172 ty::mk_imm_rptr(tcx,
5173 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5175 param(ccx, 0))], tcx.types.u64),
5178 span_err!(tcx.sess, it.span, E0093,
5179 "unrecognized intrinsic function: `{}`", *other);
5183 (n_tps, inputs, ty::FnConverging(output))
5185 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5186 unsafety: ast::Unsafety::Unsafe,
5187 abi: abi::RustIntrinsic,
5188 sig: ty::Binder(FnSig {
5194 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5195 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5196 if i_n_tps != n_tps {
5197 span_err!(tcx.sess, it.span, E0094,
5198 "intrinsic has wrong number of type \
5199 parameters: found {}, expected {}",
5202 require_same_types(tcx,
5209 format!("intrinsic has wrong type: expected `{}`",
5210 ppaux::ty_to_string(ccx.tcx, fty))