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;
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};
88 use middle::{const_eval, def};
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};
97 use middle::ty::{FnSig, GenericPredicates, VariantInfo, 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;
116 use std::iter::repeat;
118 use syntax::{self, abi, attr};
119 use syntax::attr::AttrMetaMethods;
120 use syntax::ast::{self, DefId, Visibility};
121 use syntax::ast_util::{self, local_def};
122 use syntax::codemap::{self, Span};
123 use syntax::owned_slice::OwnedSlice;
124 use syntax::parse::token;
125 use syntax::print::pprust;
127 use syntax::visit::{self, Visitor};
146 /// closures defined within the function. For example:
149 /// bar(move|| { ... })
152 /// Here, the function `foo()` and the closure passed to
153 /// `bar()` will each have their own `FnCtxt`, but they will
154 /// share the inherited fields.
155 pub struct Inherited<'a, 'tcx: 'a> {
156 infcx: infer::InferCtxt<'a, 'tcx>,
157 locals: RefCell<NodeMap<Ty<'tcx>>>,
158 param_env: ty::ParameterEnvironment<'a, 'tcx>,
161 node_types: RefCell<NodeMap<Ty<'tcx>>>,
162 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
163 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
164 method_map: MethodMap<'tcx>,
165 upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
166 closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
167 closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
168 object_cast_map: ObjectCastMap<'tcx>,
170 // A mapping from each fn's id to its signature, with all bound
171 // regions replaced with free ones. Unlike the other tables, this
172 // one is never copied into the tcx: it is only used by regionck.
173 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
175 // Tracks trait obligations incurred during this function body.
176 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
178 // When we process a call like `c()` where `c` is a closure type,
179 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
180 // `FnOnce` closure. In that case, we defer full resolution of the
181 // call until upvar inference can kick in and make the
182 // decision. We keep these deferred resolutions grouped by the
183 // def-id of the closure, so that once we decide, we can easily go
184 // back and process them.
185 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
187 deferred_cast_checks: RefCell<Vec<CastCheck<'tcx>>>,
190 trait DeferredCallResolution<'tcx> {
191 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
194 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
196 /// Reifies a cast check to be checked once we have full type information for
197 /// a function context.
198 struct CastCheck<'tcx> {
205 /// When type-checking an expression, we propagate downward
206 /// whatever type hint we are able in the form of an `Expectation`.
208 pub enum Expectation<'tcx> {
209 /// We know nothing about what type this expression should have.
212 /// This expression should have the type given (or some subtype)
213 ExpectHasType(Ty<'tcx>),
215 /// This expression will be cast to the `Ty`
216 ExpectCastableToType(Ty<'tcx>),
218 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
219 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
220 ExpectRvalueLikeUnsized(Ty<'tcx>),
223 impl<'tcx> Expectation<'tcx> {
224 // Disregard "castable to" expectations because they
225 // can lead us astray. Consider for example `if cond
226 // {22} else {c} as u8` -- if we propagate the
227 // "castable to u8" constraint to 22, it will pick the
228 // type 22u8, which is overly constrained (c might not
229 // be a u8). In effect, the problem is that the
230 // "castable to" expectation is not the tightest thing
231 // we can say, so we want to drop it in this case.
232 // The tightest thing we can say is "must unify with
233 // else branch". Note that in the case of a "has type"
234 // constraint, this limitation does not hold.
236 // If the expected type is just a type variable, then don't use
237 // an expected type. Otherwise, we might write parts of the type
238 // when checking the 'then' block which are incompatible with the
240 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
242 ExpectHasType(ety) => {
243 let ety = fcx.infcx().shallow_resolve(ety);
244 if !ty::type_is_ty_var(ety) {
250 ExpectRvalueLikeUnsized(ety) => {
251 ExpectRvalueLikeUnsized(ety)
258 #[derive(Copy, Clone)]
259 pub struct UnsafetyState {
260 pub def: ast::NodeId,
261 pub unsafety: ast::Unsafety,
266 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
267 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
270 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
271 match self.unsafety {
272 // If this unsafe, then if the outer function was already marked as
273 // unsafe we shouldn't attribute the unsafe'ness to the block. This
274 // way the block can be warned about instead of ignoring this
275 // extraneous block (functions are never warned about).
276 ast::Unsafety::Unsafe if self.from_fn => *self,
279 let (unsafety, def) = match blk.rules {
280 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
281 ast::DefaultBlock => (unsafety, self.def),
283 UnsafetyState{ def: def,
292 pub struct FnCtxt<'a, 'tcx: 'a> {
293 body_id: ast::NodeId,
295 // This flag is set to true if, during the writeback phase, we encounter
296 // a type error in this function.
297 writeback_errors: Cell<bool>,
299 // Number of errors that had been reported when we started
300 // checking this function. On exit, if we find that *more* errors
301 // have been reported, we will skip regionck and other work that
302 // expects the types within the function to be consistent.
303 err_count_on_creation: usize,
305 ret_ty: ty::FnOutput<'tcx>,
307 ps: RefCell<UnsafetyState>,
309 inh: &'a Inherited<'a, 'tcx>,
311 ccx: &'a CrateCtxt<'a, 'tcx>,
314 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
315 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
316 let ty = self.node_ty(id);
317 self.resolve_type_vars_or_error(&ty)
319 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
320 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
321 self.resolve_type_vars_or_error(&ty)
323 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
324 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
325 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
327 fn node_method_ty(&self, method_call: ty::MethodCall)
328 -> Option<Ty<'tcx>> {
329 self.inh.method_map.borrow()
331 .map(|method| method.ty)
332 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
334 fn node_method_origin(&self, method_call: ty::MethodCall)
335 -> Option<ty::MethodOrigin<'tcx>>
337 self.inh.method_map.borrow()
339 .map(|method| method.origin.clone())
341 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
342 &self.inh.adjustments
344 fn is_method_call(&self, id: ast::NodeId) -> bool {
345 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
347 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
348 self.param_env().temporary_scope(rvalue_id)
350 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
351 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
355 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
356 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
360 fn closure_kind(&self,
362 -> Option<ty::ClosureKind>
364 self.inh.closure_kinds.borrow().get(&def_id).cloned()
367 fn closure_type(&self,
369 substs: &subst::Substs<'tcx>)
370 -> ty::ClosureTy<'tcx>
372 self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs)
375 fn closure_upvars(&self,
377 substs: &Substs<'tcx>)
378 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
380 ty::closure_upvars(self, def_id, substs)
384 impl<'a, 'tcx> Inherited<'a, 'tcx> {
385 fn new(tcx: &'a ty::ctxt<'tcx>,
386 param_env: ty::ParameterEnvironment<'a, 'tcx>)
387 -> Inherited<'a, 'tcx> {
389 infcx: infer::new_infer_ctxt(tcx),
390 locals: RefCell::new(NodeMap()),
391 param_env: param_env,
392 node_types: RefCell::new(NodeMap()),
393 item_substs: RefCell::new(NodeMap()),
394 adjustments: RefCell::new(NodeMap()),
395 method_map: RefCell::new(FnvHashMap()),
396 object_cast_map: RefCell::new(NodeMap()),
397 upvar_capture_map: RefCell::new(FnvHashMap()),
398 closure_tys: RefCell::new(DefIdMap()),
399 closure_kinds: RefCell::new(DefIdMap()),
400 fn_sig_map: RefCell::new(NodeMap()),
401 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
402 deferred_call_resolutions: RefCell::new(DefIdMap()),
403 deferred_cast_checks: RefCell::new(Vec::new()),
407 fn normalize_associated_types_in<T>(&self,
408 typer: &ty::ClosureTyper<'tcx>,
410 body_id: ast::NodeId,
413 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
415 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
416 assoc::normalize_associated_types_in(&self.infcx,
418 &mut *fulfillment_cx, span,
425 // Used by check_const and check_enum_variants
426 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
427 inh: &'a Inherited<'a, 'tcx>,
428 rty: ty::FnOutput<'tcx>,
429 body_id: ast::NodeId)
430 -> FnCtxt<'a, 'tcx> {
433 writeback_errors: Cell::new(false),
434 err_count_on_creation: ccx.tcx.sess.err_count(),
436 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
442 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
443 -> Inherited<'a, 'tcx> {
444 // It's kind of a kludge to manufacture a fake function context
445 // and statement context, but we might as well do write the code only once
446 let param_env = ty::empty_parameter_environment(ccx.tcx);
447 Inherited::new(ccx.tcx, param_env)
450 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
452 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
453 fn visit_item(&mut self, i: &'tcx ast::Item) {
454 check_item(self.ccx, i);
455 visit::walk_item(self, i);
458 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
460 ast::TyFixedLengthVec(_, ref expr) => {
461 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
466 visit::walk_ty(self, t);
470 pub fn check_item_types(ccx: &CrateCtxt) {
471 let krate = ccx.tcx.map.krate();
472 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
473 visit::walk_crate(&mut visit, krate);
475 // If types are not well-formed, it leads to all manner of errors
476 // downstream, so stop reporting errors at this point.
477 ccx.tcx.sess.abort_if_errors();
479 let mut visit = CheckItemTypesVisitor { ccx: ccx };
480 visit::walk_crate(&mut visit, krate);
482 ccx.tcx.sess.abort_if_errors();
484 for drop_method_did in ccx.tcx.destructors.borrow().iter() {
485 if drop_method_did.krate == ast::LOCAL_CRATE {
486 let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
487 match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
490 assert!(ccx.tcx.sess.has_errors());
496 ccx.tcx.sess.abort_if_errors();
499 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
500 decl: &'tcx ast::FnDecl,
501 body: &'tcx ast::Block,
505 param_env: ty::ParameterEnvironment<'a, 'tcx>)
508 ty::ty_bare_fn(_, ref fn_ty) => {
509 let inh = Inherited::new(ccx.tcx, param_env);
511 // Compute the fty from point of view of inside fn.
513 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
515 liberate_late_bound_regions(ccx.tcx,
516 region::DestructionScopeData::new(body.id),
519 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
521 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
522 decl, fn_id, body, &inh);
524 vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
525 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
526 vtable::select_all_fcx_obligations_or_error(&fcx);
528 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
529 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
531 _ => ccx.tcx.sess.impossible_case(body.span,
532 "check_bare_fn: function type expected")
536 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
537 fcx: &'a FnCtxt<'a, 'tcx>
540 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
541 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
544 // infer the variable's type
545 let var_ty = self.fcx.infcx().next_ty_var();
546 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
550 // take type that the user specified
551 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
558 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
559 // Add explicitly-declared locals.
560 fn visit_local(&mut self, local: &'tcx ast::Local) {
561 let o_ty = match local.ty {
562 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
565 self.assign(local.span, local.id, o_ty);
566 debug!("Local variable {} is assigned type {}",
567 self.fcx.pat_to_string(&*local.pat),
568 self.fcx.infcx().ty_to_string(
569 self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
570 visit::walk_local(self, local);
573 // Add pattern bindings.
574 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
575 if let ast::PatIdent(_, ref path1, _) = p.node {
576 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
577 let var_ty = self.assign(p.span, p.id, None);
579 self.fcx.require_type_is_sized(var_ty, p.span,
580 traits::VariableType(p.id));
582 debug!("Pattern binding {} is assigned to {} with type {}",
583 token::get_ident(path1.node),
584 self.fcx.infcx().ty_to_string(
585 self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
586 var_ty.repr(self.fcx.tcx()));
589 visit::walk_pat(self, p);
592 fn visit_block(&mut self, b: &'tcx ast::Block) {
593 // non-obvious: the `blk` variable maps to region lb, so
594 // we have to keep this up-to-date. This
595 // is... unfortunate. It'd be nice to not need this.
596 visit::walk_block(self, b);
599 // Since an expr occurs as part of the type fixed size arrays we
600 // need to record the type for that node
601 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
603 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
604 self.visit_ty(&**ty);
605 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
607 _ => visit::walk_ty(self, t)
611 // Don't descend into fns and items
612 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
613 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
614 fn visit_item(&mut self, _: &ast::Item) { }
618 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
619 /// body and returns the function context used for that purpose, since in the case of a fn item
620 /// there is still a bit more to do.
623 /// * inherited: other fields inherited from the enclosing fn (if any)
624 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
625 unsafety: ast::Unsafety,
626 unsafety_id: ast::NodeId,
627 fn_sig: &ty::FnSig<'tcx>,
628 decl: &'tcx ast::FnDecl,
630 body: &'tcx ast::Block,
631 inherited: &'a Inherited<'a, 'tcx>)
635 let err_count_on_creation = tcx.sess.err_count();
637 let arg_tys = &fn_sig.inputs;
638 let ret_ty = fn_sig.output;
640 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
645 // Create the function context. This is either derived from scratch or,
646 // in the case of function expressions, based on the outer context.
649 writeback_errors: Cell::new(false),
650 err_count_on_creation: err_count_on_creation,
652 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
657 // Remember return type so that regionck can access it later.
658 let mut fn_sig_tys: Vec<Ty> =
663 if let ty::FnConverging(ret_ty) = ret_ty {
664 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
665 fn_sig_tys.push(ret_ty);
668 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
670 fn_sig_tys.repr(tcx));
672 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
675 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
677 // Add formal parameters.
678 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
679 // Create type variables for each argument.
680 pat_util::pat_bindings(
683 |_bm, pat_id, sp, _path| {
684 let var_ty = visit.assign(sp, pat_id, None);
685 fcx.require_type_is_sized(var_ty, sp,
686 traits::VariableType(pat_id));
689 // Check the pattern.
692 map: pat_id_map(&tcx.def_map, &*input.pat),
694 _match::check_pat(&pcx, &*input.pat, *arg_ty);
697 visit.visit_block(body);
700 check_block_with_expected(&fcx, body, match ret_ty {
701 ty::FnConverging(result_type) => ExpectHasType(result_type),
702 ty::FnDiverging => NoExpectation
705 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
706 fcx.write_ty(input.id, *arg);
712 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
715 check_representable(tcx, span, id, "struct");
716 check_instantiable(tcx, span, id);
718 if ty::lookup_simd(tcx, local_def(id)) {
719 check_simd(tcx, span, id);
723 pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
724 debug!("check_item(it.id={}, it.ident={})",
726 ty::item_path_str(ccx.tcx, local_def(it.id)));
727 let _indenter = indenter();
730 ast::ItemStatic(_, _, ref e) |
731 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
732 ast::ItemEnum(ref enum_definition, _) => {
733 check_enum_variants(ccx,
735 &enum_definition.variants,
738 ast::ItemFn(ref decl, _, _, _, ref body) => {
739 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
740 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
741 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
743 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
744 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
746 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
748 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
749 Some(impl_trait_ref) => {
750 check_impl_items_against_trait(ccx,
758 for impl_item in impl_items {
759 match impl_item.node {
760 ast::MethodImplItem(ref sig, ref body) => {
761 check_method_body(ccx, &impl_pty.generics, sig, body,
762 impl_item.id, impl_item.span);
764 ast::TypeImplItem(_) |
765 ast::MacImplItem(_) => {
766 // Nothing to do here.
772 ast::ItemTrait(_, ref generics, _, ref trait_items) => {
773 check_trait_on_unimplemented(ccx, generics, it);
774 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
775 for trait_item in trait_items {
776 match trait_item.node {
777 ast::MethodTraitItem(_, None) => {
778 // Nothing to do, since required methods don't have
781 ast::MethodTraitItem(ref sig, Some(ref body)) => {
782 check_method_body(ccx, &trait_def.generics, sig, body,
783 trait_item.id, trait_item.span);
785 ast::TypeTraitItem(..) => {
791 ast::ItemStruct(..) => {
792 check_struct(ccx, it.id, it.span);
794 ast::ItemTy(ref t, ref generics) => {
795 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
796 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
798 ast::ItemForeignMod(ref m) => {
799 if m.abi == abi::RustIntrinsic {
800 for item in &m.items {
801 check_intrinsic_type(ccx, &**item);
804 for item in &m.items {
805 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
806 if !pty.generics.types.is_empty() {
807 span_err!(ccx.tcx.sess, item.span, E0044,
808 "foreign items may not have type parameters");
811 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
812 if fn_decl.variadic && m.abi != abi::C {
813 span_err!(ccx.tcx.sess, item.span, E0045,
814 "variadic function must have C calling convention");
820 _ => {/* nothing to do */ }
824 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
825 generics: &ast::Generics,
827 if let Some(ref attr) = item.attrs.iter().find(|a| {
828 a.check_name("rustc_on_unimplemented")
830 if let Some(ref istring) = attr.value_str() {
831 let parser = Parser::new(&istring);
832 let types = &*generics.ty_params;
833 for token in parser {
835 Piece::String(_) => (), // Normal string, no need to check it
836 Piece::NextArgument(a) => match a.position {
837 // `{Self}` is allowed
838 Position::ArgumentNamed(s) if s == "Self" => (),
839 // So is `{A}` if A is a type parameter
840 Position::ArgumentNamed(s) => match types.iter().find(|t| {
841 t.ident.as_str() == s
845 span_err!(ccx.tcx.sess, attr.span, E0230,
846 "there is no type parameter \
848 s, item.ident.as_str());
851 // `{:1}` and `{}` are not to be used
852 Position::ArgumentIs(_) | Position::ArgumentNext => {
853 span_err!(ccx.tcx.sess, attr.span, E0231,
854 "only named substitution \
855 parameters are allowed");
861 span_err!(ccx.tcx.sess, attr.span, E0232,
862 "this attribute must have a value, \
863 eg `#[rustc_on_unimplemented = \"foo\"]`")
868 /// Type checks a method body.
872 /// * `item_generics`: generics defined on the impl/trait that contains
874 /// * `self_bound`: bound for the `Self` type parameter, if any
875 /// * `method`: the method definition
876 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
877 item_generics: &ty::Generics<'tcx>,
878 sig: &'tcx ast::MethodSig,
879 body: &'tcx ast::Block,
880 id: ast::NodeId, span: Span) {
881 debug!("check_method_body(item_generics={}, id={})",
882 item_generics.repr(ccx.tcx), id);
883 let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
885 let fty = ty::node_id_to_type(ccx.tcx, id);
886 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
888 check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
891 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
893 impl_trait_ref: &ty::TraitRef<'tcx>,
894 impl_items: &[P<ast::ImplItem>]) {
895 // Locate trait methods
897 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
899 // Check existing impl methods to see if they are both present in trait
900 // and compatible with trait signature
901 for impl_item in impl_items {
902 match impl_item.node {
903 ast::MethodImplItem(_, ref body) => {
904 let impl_method_def_id = local_def(impl_item.id);
905 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
908 // If this is an impl of a trait method, find the
909 // corresponding method definition in the trait.
910 let opt_trait_method_ty =
912 .find(|ti| ti.name() == impl_item_ty.name());
913 match opt_trait_method_ty {
914 Some(trait_method_ty) => {
915 match (trait_method_ty, &impl_item_ty) {
916 (&ty::MethodTraitItem(ref trait_method_ty),
917 &ty::MethodTraitItem(ref impl_method_ty)) => {
918 compare_impl_method(ccx.tcx,
926 // This is span_bug as it should have already been
927 // caught in resolve.
930 &format!("item `{}` is of a different kind from its trait `{}`",
931 token::get_name(impl_item_ty.name()),
932 impl_trait_ref.repr(tcx)));
937 // This is span_bug as it should have already been
938 // caught in resolve.
941 &format!("method `{}` is not a member of trait `{}`",
942 token::get_name(impl_item_ty.name()),
943 impl_trait_ref.repr(tcx)));
947 ast::TypeImplItem(_) => {
948 let typedef_def_id = local_def(impl_item.id);
949 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
952 // If this is an impl of an associated type, find the
953 // corresponding type definition in the trait.
954 let opt_associated_type =
956 .find(|ti| ti.name() == typedef_ty.name());
957 match opt_associated_type {
958 Some(associated_type) => {
959 match (associated_type, &typedef_ty) {
960 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
962 // This is `span_bug` as it should have
963 // already been caught in resolve.
966 &format!("item `{}` is of a different kind from its trait `{}`",
967 token::get_name(typedef_ty.name()),
968 impl_trait_ref.repr(tcx)));
973 // This is `span_bug` as it should have already been
974 // caught in resolve.
978 "associated type `{}` is not a member of \
980 token::get_name(typedef_ty.name()),
981 impl_trait_ref.repr(tcx)));
985 ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
990 // Check for missing items from trait
991 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
992 let mut missing_methods = Vec::new();
993 for trait_item in &*trait_items {
995 ty::MethodTraitItem(ref trait_method) => {
997 impl_items.iter().any(|ii| {
999 ast::MethodImplItem(..) => {
1000 ii.ident.name == trait_method.name
1002 ast::TypeImplItem(_) |
1003 ast::MacImplItem(_) => false,
1007 provided_methods.iter().any(|m| m.name == trait_method.name);
1008 if !is_implemented && !is_provided {
1009 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
1012 ty::TypeTraitItem(ref associated_type) => {
1013 let is_implemented = impl_items.iter().any(|ii| {
1015 ast::TypeImplItem(_) => {
1016 ii.ident.name == associated_type.name
1018 ast::MethodImplItem(..) |
1019 ast::MacImplItem(_) => false,
1022 if !is_implemented {
1023 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1029 if !missing_methods.is_empty() {
1030 span_err!(tcx.sess, impl_span, E0046,
1031 "not all trait items implemented, missing: {}",
1032 missing_methods.connect(", "));
1036 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1043 let tstr = fcx.infcx().ty_to_string(t_1);
1044 fcx.type_error_message(span, |actual| {
1045 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1048 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1049 let mtstr = match mt {
1050 ast::MutMutable => "mut ",
1051 ast::MutImmutable => ""
1053 if ty::type_is_trait(t_1) {
1054 span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
1056 span_help!(fcx.tcx().sess, span,
1057 "consider using an implicit coercion to `&{}{}` instead",
1061 ty::ty_uniq(..) => {
1062 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
1065 span_help!(fcx.tcx().sess, e_span,
1066 "consider using a box or reference as appropriate");
1069 fcx.write_error(id);
1073 fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
1074 fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1078 fcx.type_error_message(span, |actual| {
1079 format!("illegal cast; cast through an \
1080 integer first: `{}` as `{}`",
1082 fcx.infcx().ty_to_string(t_1))
1086 let span = cast.span;
1088 let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
1089 let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
1091 // Check for trivial casts.
1092 if !ty::type_has_ty_infer(t_1) {
1093 if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
1094 if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
1095 fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
1098 format!("trivial numeric cast: `{}` as `{}`. Cast can be \
1099 replaced by coercion, this might require type \
1100 ascription or a temporary variable",
1101 fcx.infcx().ty_to_string(t_e),
1102 fcx.infcx().ty_to_string(t_1)));
1104 fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
1107 format!("trivial cast: `{}` as `{}`. Cast can be \
1108 replaced by coercion, this might require type \
1109 ascription or a temporary variable",
1110 fcx.infcx().ty_to_string(t_e),
1111 fcx.infcx().ty_to_string(t_1)));
1117 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1118 let t_e_is_scalar = ty::type_is_scalar(t_e);
1119 let t_e_is_integral = ty::type_is_integral(t_e);
1120 let t_e_is_float = ty::type_is_floating_point(t_e);
1121 let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
1123 let t_1_is_scalar = ty::type_is_scalar(t_1);
1124 let t_1_is_char = ty::type_is_char(t_1);
1125 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1126 let t_1_is_float = ty::type_is_floating_point(t_1);
1128 // casts to scalars other than `char` and `bare fn` are trivial
1129 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1131 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1132 demand::coerce(fcx, e.span, t_1, &e);
1133 } else if t_1_is_char {
1134 let t_e = fcx.infcx().shallow_resolve(t_e);
1135 if t_e.sty != ty::ty_uint(ast::TyU8) {
1136 fcx.type_error_message(span, |actual| {
1137 format!("only `u8` can be cast as `char`, not `{}`", actual)
1140 } else if t_1.sty == ty::ty_bool {
1141 span_err!(fcx.tcx().sess, span, E0054,
1142 "cannot cast as `bool`, compare with zero instead");
1143 } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
1144 t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
1145 // Casts to float must go through an integer or boolean
1146 cast_through_integer_err(fcx, span, t_1, t_e)
1147 } else if t_e_is_c_enum && t_1_is_trivial {
1148 if ty::type_is_unsafe_ptr(t_1) {
1149 // ... and likewise with C enum -> *T
1150 cast_through_integer_err(fcx, span, t_1, t_e)
1152 // casts from C-like enums are allowed
1153 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1154 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1155 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1157 ty::ty_vec(_, Some(_)) => {}
1160 if ty::type_needs_infer(t2) {
1161 // This prevents this special case from going off when casting
1162 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1167 let el = ty::sequence_element_type(fcx.tcx(), t1);
1168 infer::mk_eqty(fcx.infcx(),
1175 // Due to the limitations of LLVM global constants,
1176 // region pointers end up pointing at copies of
1177 // vector elements instead of the original values.
1178 // To allow unsafe pointers to work correctly, we
1179 // need to special-case obtaining an unsafe pointer
1180 // from a region pointer to a vector.
1182 /* this cast is only allowed from &[T, ..n] to *T or
1184 match (&t_e.sty, &t_1.sty) {
1185 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1186 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1187 if types_compatible(fcx, e.span, mt1, mt2) => {
1188 /* this case is allowed */
1191 demand::coerce(fcx, e.span, t_1, &e);
1194 } else if !(t_e_is_scalar && t_1_is_trivial) {
1196 If more type combinations should be supported than are
1197 supported here, then file an enhancement issue and
1198 record the issue number in this comment.
1200 fcx.type_error_message(span, |actual| {
1201 format!("non-scalar cast: `{}` as `{}`",
1203 fcx.infcx().ty_to_string(t_1))
1208 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1209 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1211 fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
1212 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
1214 Ok(ty::lookup_item_type(self.tcx(), id))
1217 fn get_trait_def(&self, _: Span, id: ast::DefId)
1218 -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
1220 Ok(ty::lookup_trait_def(self.tcx(), id))
1223 fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
1224 // all super predicates are ensured during collect pass
1228 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1229 Some(&self.inh.param_env.free_substs)
1232 fn get_type_parameter_bounds(&self,
1234 node_id: ast::NodeId)
1235 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1237 let def = self.tcx().type_parameter_def(node_id);
1238 let r = self.inh.param_env.caller_bounds
1240 .filter_map(|predicate| {
1242 ty::Predicate::Trait(ref data) => {
1243 if data.0.self_ty().is_param(def.space, def.index) {
1244 Some(data.to_poly_trait_ref())
1258 fn trait_defines_associated_type_named(&self,
1259 trait_def_id: ast::DefId,
1260 assoc_name: ast::Name)
1263 let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
1264 trait_def.associated_type_names.contains(&assoc_name)
1267 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1268 self.infcx().next_ty_var()
1271 fn projected_ty_from_poly_trait_ref(&self,
1273 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1274 item_name: ast::Name)
1277 let (trait_ref, _) =
1278 self.infcx().replace_late_bound_regions_with_fresh_var(
1280 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1283 self.normalize_associated_type(span, trait_ref, item_name)
1286 fn projected_ty(&self,
1288 trait_ref: Rc<ty::TraitRef<'tcx>>,
1289 item_name: ast::Name)
1292 self.normalize_associated_type(span, trait_ref, item_name)
1296 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1297 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1299 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1303 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1307 pub fn sess(&self) -> &Session {
1311 pub fn err_count_since_creation(&self) -> usize {
1312 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1315 /// Resolves type variables in `ty` if possible. Unlike the infcx
1316 /// version, this version will also select obligations if it seems
1317 /// useful, in an effort to get more type information.
1318 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1319 debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx()));
1321 // No ty::infer()? Nothing needs doing.
1322 if !ty::type_has_ty_infer(ty) {
1323 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1327 // If `ty` is a type variable, see whether we already know what it is.
1328 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1329 if !ty::type_has_ty_infer(ty) {
1330 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1334 // If not, try resolving any new fcx obligations that have cropped up.
1335 vtable::select_new_fcx_obligations(self);
1336 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1337 if !ty::type_has_ty_infer(ty) {
1338 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1342 // If not, try resolving *all* pending obligations as much as
1343 // possible. This can help substantially when there are
1344 // indirect dependencies that don't seem worth tracking
1346 vtable::select_fcx_obligations_where_possible(self);
1347 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1349 debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx()));
1353 /// Resolves all type variables in `t` and then, if any were left
1354 /// unresolved, substitutes an error type. This is used after the
1355 /// main checking when doing a second pass before writeback. The
1356 /// justification is that writeback will produce an error for
1357 /// these unconstrained type variables.
1358 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1359 let t = self.infcx().resolve_type_vars_if_possible(t);
1360 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1363 fn record_deferred_call_resolution(&self,
1364 closure_def_id: ast::DefId,
1365 r: DeferredCallResolutionHandler<'tcx>) {
1366 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1367 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1370 fn remove_deferred_call_resolutions(&self,
1371 closure_def_id: ast::DefId)
1372 -> Vec<DeferredCallResolutionHandler<'tcx>>
1374 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1375 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1378 pub fn tag(&self) -> String {
1379 let self_ptr: *const FnCtxt = self;
1380 format!("{:?}", self_ptr)
1383 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1384 match self.inh.locals.borrow().get(&nid) {
1387 self.tcx().sess.span_err(
1389 &format!("no type for local variable {}", nid));
1390 self.tcx().types.err
1395 /// Apply "fallbacks" to some types
1396 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1397 pub fn default_type_parameters(&self) {
1398 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1399 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1400 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1401 if self.infcx().type_var_diverges(resolved) {
1402 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1404 match self.infcx().type_is_unconstrained_numeric(resolved) {
1405 UnconstrainedInt => {
1406 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1408 UnconstrainedFloat => {
1409 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1418 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1419 debug!("write_ty({}, {}) in fcx {}",
1420 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1421 self.inh.node_types.borrow_mut().insert(node_id, ty);
1424 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1425 if !substs.substs.is_noop() {
1426 debug!("write_substs({}, {}) in fcx {}",
1428 substs.repr(self.tcx()),
1431 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1435 pub fn write_autoderef_adjustment(&self,
1436 node_id: ast::NodeId,
1439 if derefs == 0 { return; }
1440 self.write_adjustment(
1443 ty::AdjustDerefRef(ty::AutoDerefRef {
1449 pub fn write_adjustment(&self,
1450 node_id: ast::NodeId,
1452 adj: ty::AutoAdjustment<'tcx>) {
1453 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1455 if adj.is_identity() {
1459 // Careful: adjustments can imply trait obligations if we are
1460 // casting from a concrete type to an object type. I think
1461 // it'd probably be nicer to move the logic that creates the
1462 // obligation into the code that creates the adjustment, but
1463 // that's a bit awkward, so instead we go digging and pull the
1464 // obligation out here.
1465 self.register_adjustment_obligations(span, &adj);
1466 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1469 /// Basically whenever we are converting from a type scheme into
1470 /// the fn body space, we always want to normalize associated
1471 /// types as well. This function combines the two.
1472 fn instantiate_type_scheme<T>(&self,
1474 substs: &Substs<'tcx>,
1477 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1479 let value = value.subst(self.tcx(), substs);
1480 let result = self.normalize_associated_types_in(span, &value);
1481 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1482 value.repr(self.tcx()),
1483 substs.repr(self.tcx()),
1484 result.repr(self.tcx()));
1488 /// As `instantiate_type_scheme`, but for the bounds found in a
1489 /// generic type scheme.
1490 fn instantiate_bounds(&self,
1492 substs: &Substs<'tcx>,
1493 bounds: &ty::GenericPredicates<'tcx>)
1494 -> ty::InstantiatedPredicates<'tcx>
1496 ty::InstantiatedPredicates {
1497 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1502 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1503 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1505 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1508 fn normalize_associated_type(&self,
1510 trait_ref: Rc<ty::TraitRef<'tcx>>,
1511 item_name: ast::Name)
1514 let cause = traits::ObligationCause::new(span,
1516 traits::ObligationCauseCode::MiscObligation);
1517 self.inh.fulfillment_cx
1519 .normalize_projection_type(self.infcx(),
1522 trait_ref: trait_ref,
1523 item_name: item_name,
1528 fn register_adjustment_obligations(&self,
1530 adj: &ty::AutoAdjustment<'tcx>) {
1532 ty::AdjustReifyFnPointer(..) => { }
1533 ty::AdjustUnsafeFnPointer => { }
1534 ty::AdjustDerefRef(ref d_r) => {
1537 self.register_autoref_obligations(span, a_r);
1545 fn register_autoref_obligations(&self,
1547 autoref: &ty::AutoRef<'tcx>) {
1549 ty::AutoUnsize(ref unsize) => {
1550 self.register_unsize_obligations(span, unsize);
1552 ty::AutoPtr(_, _, None) |
1553 ty::AutoUnsafe(_, None) => {
1555 ty::AutoPtr(_, _, Some(ref a_r)) |
1556 ty::AutoUnsafe(_, Some(ref a_r)) => {
1557 self.register_autoref_obligations(span, &**a_r)
1559 ty::AutoUnsizeUniq(ref unsize) => {
1560 self.register_unsize_obligations(span, unsize);
1565 fn register_unsize_obligations(&self,
1567 unsize: &ty::UnsizeKind<'tcx>) {
1568 debug!("register_unsize_obligations: unsize={:?}", unsize);
1571 ty::UnsizeLength(..) => {}
1572 ty::UnsizeStruct(ref u, _) => {
1573 self.register_unsize_obligations(span, &**u)
1575 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1576 vtable::check_object_safety(self.tcx(), ty_trait, span);
1578 // If the type is `Foo+'a`, ensures that the type
1579 // being cast to `Foo+'a` implements `Foo`:
1580 vtable::register_object_cast_obligations(self,
1585 // If the type is `Foo+'a`, ensures that the type
1586 // being cast to `Foo+'a` outlives `'a`:
1587 let cause = traits::ObligationCause { span: span,
1588 body_id: self.body_id,
1589 code: traits::ObjectCastObligation(self_ty) };
1590 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1592 ty::UnsizeUpcast(_) => { }
1596 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1597 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1598 /// Registers any trait obligations specified on `def_id` at the same time.
1600 /// Note that function is only intended to be used with types (notably, not fns). This is
1601 /// because it doesn't do any instantiation of late-bound regions.
1602 pub fn instantiate_type(&self,
1605 -> TypeAndSubsts<'tcx>
1608 ty::lookup_item_type(self.tcx(), def_id);
1609 let type_predicates =
1610 ty::lookup_predicates(self.tcx(), def_id);
1612 self.infcx().fresh_substs_for_generics(
1614 &type_scheme.generics);
1616 self.instantiate_bounds(span, &substs, &type_predicates);
1617 self.add_obligations_for_parameters(
1618 traits::ObligationCause::new(
1621 traits::ItemObligation(def_id)),
1624 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1632 /// Returns the type that this AST path refers to. If the path has no type
1633 /// parameters and the corresponding type has type parameters, fresh type
1634 /// and/or region variables are substituted.
1636 /// This is used when checking the constructor in struct literals.
1637 fn instantiate_struct_literal_ty(&self,
1640 -> TypeAndSubsts<'tcx>
1642 let tcx = self.tcx();
1644 let ty::TypeScheme { generics, ty: decl_ty } =
1645 ty::lookup_item_type(tcx, did);
1647 let substs = astconv::ast_path_substs_for_ty(self, self,
1649 PathParamMode::Optional,
1651 path.segments.last().unwrap());
1653 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1655 TypeAndSubsts { substs: substs, ty: ty }
1658 pub fn write_nil(&self, node_id: ast::NodeId) {
1659 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1661 pub fn write_error(&self, node_id: ast::NodeId) {
1662 self.write_ty(node_id, self.tcx().types.err);
1665 pub fn require_type_meets(&self,
1668 code: traits::ObligationCauseCode<'tcx>,
1669 bound: ty::BuiltinBound)
1671 self.register_builtin_bound(
1674 traits::ObligationCause::new(span, self.body_id, code));
1677 pub fn require_type_is_sized(&self,
1680 code: traits::ObligationCauseCode<'tcx>)
1682 self.require_type_meets(ty, span, code, ty::BoundSized);
1685 pub fn require_expr_have_sized_type(&self,
1687 code: traits::ObligationCauseCode<'tcx>)
1689 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1692 pub fn type_is_known_to_be_sized(&self,
1697 traits::type_known_to_meet_builtin_bound(self.infcx(),
1704 pub fn register_builtin_bound(&self,
1706 builtin_bound: ty::BuiltinBound,
1707 cause: traits::ObligationCause<'tcx>)
1709 self.inh.fulfillment_cx.borrow_mut()
1710 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1713 pub fn register_predicate(&self,
1714 obligation: traits::PredicateObligation<'tcx>)
1716 debug!("register_predicate({})",
1717 obligation.repr(self.tcx()));
1718 self.inh.fulfillment_cx
1720 .register_predicate_obligation(self.infcx(), obligation);
1723 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1724 let t = ast_ty_to_ty(self, self, ast_t);
1726 let mut bounds_checker = wf::BoundsChecker::new(self,
1730 bounds_checker.check_ty(t);
1735 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1736 pat.repr(self.tcx())
1739 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1740 match self.inh.node_types.borrow().get(&ex.id) {
1743 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1749 /// Apply `adjustment` to the type of `expr`
1750 pub fn adjust_expr_ty(&self,
1752 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1755 let raw_ty = self.expr_ty(expr);
1756 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1757 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1758 ty::adjust_ty(self.tcx(),
1763 |method_call| self.inh.method_map.borrow()
1765 .map(|method| resolve_ty(method.ty)))
1768 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1769 match self.inh.node_types.borrow().get(&id) {
1771 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1773 self.tcx().sess.bug(
1774 &format!("no type for node {}: {} in fcx {}",
1775 id, self.tcx().map.node_to_string(id),
1781 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1782 self.inh.item_substs.borrow()
1785 pub fn opt_node_ty_substs<F>(&self,
1788 F: FnOnce(&ty::ItemSubsts<'tcx>),
1790 match self.inh.item_substs.borrow().get(&id) {
1796 pub fn mk_subty(&self,
1797 a_is_expected: bool,
1798 origin: infer::TypeOrigin,
1801 -> Result<(), ty::type_err<'tcx>> {
1802 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1805 pub fn mk_eqty(&self,
1806 a_is_expected: bool,
1807 origin: infer::TypeOrigin,
1810 -> Result<(), ty::type_err<'tcx>> {
1811 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1814 pub fn mk_subr(&self,
1815 origin: infer::SubregionOrigin<'tcx>,
1818 infer::mk_subr(self.infcx(), origin, sub, sup)
1821 pub fn type_error_message<M>(&self,
1824 actual_ty: Ty<'tcx>,
1825 err: Option<&ty::type_err<'tcx>>) where
1826 M: FnOnce(String) -> String,
1828 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1831 pub fn report_mismatched_types(&self,
1835 err: &ty::type_err<'tcx>) {
1836 self.infcx().report_mismatched_types(sp, e, a, err)
1839 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1840 /// outlive the region `r`.
1841 pub fn register_region_obligation(&self,
1844 cause: traits::ObligationCause<'tcx>)
1846 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1847 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1850 pub fn add_default_region_param_bounds(&self,
1851 substs: &Substs<'tcx>,
1854 for &ty in substs.types.iter() {
1855 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1856 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1857 traits::MiscObligation);
1858 self.register_region_obligation(ty, default_bound, cause);
1862 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1863 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1864 /// trait/region obligations.
1866 /// For example, if there is a function:
1869 /// fn foo<'a,T:'a>(...)
1872 /// and a reference:
1878 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1879 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1880 pub fn add_obligations_for_parameters(&self,
1881 cause: traits::ObligationCause<'tcx>,
1882 predicates: &ty::InstantiatedPredicates<'tcx>)
1884 assert!(!predicates.has_escaping_regions());
1886 debug!("add_obligations_for_parameters(predicates={})",
1887 predicates.repr(self.tcx()));
1889 let obligations = traits::predicates_for_generics(self.tcx(),
1893 obligations.map_move(|o| self.register_predicate(o));
1896 // Only for fields! Returns <none> for methods>
1897 // Indifferent to privacy flags
1898 pub fn lookup_field_ty(&self,
1900 class_id: ast::DefId,
1901 items: &[ty::field_ty],
1902 fieldname: ast::Name,
1903 substs: &subst::Substs<'tcx>)
1906 let o_field = items.iter().find(|f| f.name == fieldname);
1907 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1908 .map(|t| self.normalize_associated_types_in(span, &t))
1911 pub fn lookup_tup_field_ty(&self,
1913 class_id: ast::DefId,
1914 items: &[ty::field_ty],
1916 substs: &subst::Substs<'tcx>)
1919 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1920 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1921 .map(|t| self.normalize_associated_types_in(span, &t))
1924 fn check_casts(&self) {
1925 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1926 for check in deferred_cast_checks.iter() {
1927 check_cast(self, check);
1930 deferred_cast_checks.clear();
1934 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1935 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1936 // RFC #599 specifies that object lifetime defaults take
1937 // precedence over other defaults. But within a fn body we
1938 // don't have a *default* region, rather we use inference to
1939 // find the *correct* region, which is strictly more general
1940 // (and anyway, within a fn body the right region may not even
1941 // be something the user can write explicitly, since it might
1942 // be some expression).
1943 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1946 fn anon_regions(&self, span: Span, count: usize)
1947 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
1948 Ok((0..count).map(|_| {
1949 self.infcx().next_region_var(infer::MiscVariable(span))
1954 #[derive(Copy, Debug, PartialEq, Eq)]
1955 pub enum LvaluePreference {
1960 /// Whether `autoderef` requires types to resolve.
1961 #[derive(Copy, Debug, PartialEq, Eq)]
1962 pub enum UnresolvedTypeAction {
1963 /// Produce an error and return `ty_err` whenever a type cannot
1964 /// be resolved (i.e. it is `ty_infer`).
1966 /// Go on without emitting any errors, and return the unresolved
1967 /// type. Useful for probing, e.g. in coercions.
1971 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1972 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1974 /// Note: this method does not modify the adjustments table. The caller is responsible for
1975 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1976 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1979 opt_expr: Option<&ast::Expr>,
1980 unresolved_type_action: UnresolvedTypeAction,
1981 mut lvalue_pref: LvaluePreference,
1983 -> (Ty<'tcx>, usize, Option<T>)
1984 where F: FnMut(Ty<'tcx>, usize) -> Option<T>,
1986 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1987 base_ty.repr(fcx.tcx()),
1988 opt_expr.repr(fcx.tcx()),
1991 let mut t = base_ty;
1992 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1993 let resolved_t = match unresolved_type_action {
1994 UnresolvedTypeAction::Error => {
1995 let resolved_t = structurally_resolved_type(fcx, sp, t);
1996 if ty::type_is_error(resolved_t) {
1997 return (resolved_t, autoderefs, None);
2001 UnresolvedTypeAction::Ignore => {
2002 // We can continue even when the type cannot be resolved
2003 // (i.e. it is an inference variable) because `ty::deref`
2004 // and `try_overloaded_deref` both simply return `None`
2005 // in such a case without producing spurious errors.
2006 fcx.resolve_type_vars_if_possible(t)
2010 match should_stop(resolved_t, autoderefs) {
2011 Some(x) => return (resolved_t, autoderefs, Some(x)),
2015 // Otherwise, deref if type is derefable:
2016 let mt = match ty::deref(resolved_t, false) {
2017 Some(mt) => Some(mt),
2019 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
2021 // Super subtle: it might seem as though we should
2022 // pass `opt_expr` to `try_overloaded_deref`, so that
2023 // the (implicit) autoref of using an overloaded deref
2024 // would get added to the adjustment table. However we
2025 // do not do that, because it's kind of a
2026 // "meta-adjustment" -- instead, we just leave it
2027 // unrecorded and know that there "will be" an
2028 // autoref. regionck and other bits of the code base,
2029 // when they encounter an overloaded autoderef, have
2030 // to do some reconstructive surgery. This is a pretty
2031 // complex mess that is begging for a proper MIR.
2032 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2038 if mt.mutbl == ast::MutImmutable {
2039 lvalue_pref = NoPreference;
2042 None => return (resolved_t, autoderefs, None)
2046 // We've reached the recursion limit, error gracefully.
2047 span_err!(fcx.tcx().sess, sp, E0055,
2048 "reached the recursion limit while auto-dereferencing {}",
2049 base_ty.repr(fcx.tcx()));
2050 (fcx.tcx().types.err, 0, None)
2053 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2055 method_call: Option<MethodCall>,
2056 base_expr: Option<&ast::Expr>,
2058 lvalue_pref: LvaluePreference)
2059 -> Option<ty::mt<'tcx>>
2061 // Try DerefMut first, if preferred.
2062 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2063 (PreferMutLvalue, Some(trait_did)) => {
2064 method::lookup_in_trait(fcx, span, base_expr,
2065 token::intern("deref_mut"), trait_did,
2071 // Otherwise, fall back to Deref.
2072 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2073 (None, Some(trait_did)) => {
2074 method::lookup_in_trait(fcx, span, base_expr,
2075 token::intern("deref"), trait_did,
2078 (method, _) => method
2081 make_overloaded_lvalue_return_type(fcx, method_call, method)
2084 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2085 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2086 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2087 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2088 method_call: Option<MethodCall>,
2089 method: Option<MethodCallee<'tcx>>)
2090 -> Option<ty::mt<'tcx>>
2094 // extract method method return type, which will be &T;
2095 // all LB regions should have been instantiated during method lookup
2096 let ret_ty = ty::ty_fn_ret(method.ty);
2097 let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap();
2099 if let Some(method_call) = method_call {
2100 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2103 // method returns &T, but the type as visible to user is T, so deref
2104 ty::deref(ret_ty, true)
2110 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2111 base_expr: &ast::Expr,
2113 lvalue_pref: LvaluePreference,
2116 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2118 // FIXME(#18741) -- this is almost but not quite the same as the
2119 // autoderef that normal method probing does. They could likely be
2122 let (ty, autoderefs, final_mt) = autoderef(fcx,
2126 UnresolvedTypeAction::Error,
2129 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2130 step(adj_ty, autoderefref)
2133 if final_mt.is_some() {
2137 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2138 // do a final unsized coercion to yield [T].
2140 ty::ty_vec(element_ty, Some(n)) => {
2141 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2142 let autoderefref = ty::AutoDerefRef {
2143 autoderefs: autoderefs,
2144 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2146 step(adjusted_ty, autoderefref)
2154 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2155 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2156 /// This loop implements one step in that search; the autoderef loop is implemented by
2157 /// `autoderef_for_index`.
2158 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2159 method_call: MethodCall,
2161 base_expr: &'tcx ast::Expr,
2162 adjusted_ty: Ty<'tcx>,
2163 adjustment: ty::AutoDerefRef<'tcx>,
2164 lvalue_pref: LvaluePreference,
2166 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2168 let tcx = fcx.tcx();
2169 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2171 base_expr.repr(tcx),
2172 adjusted_ty.repr(tcx),
2174 index_ty.repr(tcx));
2176 let input_ty = fcx.infcx().next_ty_var();
2178 // First, try built-in indexing.
2179 match (ty::index(adjusted_ty), &index_ty.sty) {
2180 (Some(ty), &ty::ty_uint(ast::TyUs)) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2181 debug!("try_index_step: success, using built-in indexing");
2182 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2183 return Some((tcx.types.usize, ty));
2188 // Try `IndexMut` first, if preferred.
2189 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2190 (PreferMutLvalue, Some(trait_did)) => {
2191 method::lookup_in_trait_adjusted(fcx,
2194 token::intern("index_mut"),
2198 Some(vec![input_ty]))
2203 // Otherwise, fall back to `Index`.
2204 let method = match (method, tcx.lang_items.index_trait()) {
2205 (None, Some(trait_did)) => {
2206 method::lookup_in_trait_adjusted(fcx,
2209 token::intern("index"),
2213 Some(vec![input_ty]))
2215 (method, _) => method,
2218 // If some lookup succeeds, write callee into table and extract index/element
2219 // type from the method signature.
2220 // If some lookup succeeded, install method in table
2221 method.and_then(|method| {
2222 debug!("try_index_step: success, using overloaded indexing");
2223 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2224 map(|ret| (input_ty, ret.ty))
2228 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2230 method_fn_ty: Ty<'tcx>,
2231 callee_expr: &'tcx ast::Expr,
2232 args_no_rcvr: &'tcx [P<ast::Expr>],
2233 tuple_arguments: TupleArgumentsFlag,
2234 expected: Expectation<'tcx>)
2235 -> ty::FnOutput<'tcx> {
2236 if ty::type_is_error(method_fn_ty) {
2237 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2239 let err_inputs = match tuple_arguments {
2240 DontTupleArguments => err_inputs,
2241 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2244 check_argument_types(fcx,
2251 ty::FnConverging(fcx.tcx().types.err)
2253 match method_fn_ty.sty {
2254 ty::ty_bare_fn(_, ref fty) => {
2255 // HACK(eddyb) ignore self in the definition (see above).
2256 let expected_arg_tys = expected_types_for_fn_args(fcx,
2260 &fty.sig.0.inputs[1..]);
2261 check_argument_types(fcx,
2263 &fty.sig.0.inputs[1..],
2264 &expected_arg_tys[..],
2271 fcx.tcx().sess.span_bug(callee_expr.span,
2272 "method without bare fn type");
2278 /// Generic function that factors out common logic from function calls, method calls and overloaded
2280 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2282 fn_inputs: &[Ty<'tcx>],
2283 expected_arg_tys: &[Ty<'tcx>],
2284 args: &'tcx [P<ast::Expr>],
2286 tuple_arguments: TupleArgumentsFlag) {
2287 let tcx = fcx.ccx.tcx;
2289 // Grab the argument types, supplying fresh type variables
2290 // if the wrong number of arguments were supplied
2291 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2297 let mut expected_arg_tys = expected_arg_tys;
2298 let expected_arg_count = fn_inputs.len();
2299 let formal_tys = if tuple_arguments == TupleArguments {
2300 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2301 match tuple_type.sty {
2302 ty::ty_tup(ref arg_types) => {
2303 if arg_types.len() != args.len() {
2304 span_err!(tcx.sess, sp, E0057,
2305 "this function takes {} parameter{} but {} parameter{} supplied",
2307 if arg_types.len() == 1 {""} else {"s"},
2309 if args.len() == 1 {" was"} else {"s were"});
2310 expected_arg_tys = &[];
2311 err_args(fcx.tcx(), args.len())
2313 expected_arg_tys = match expected_arg_tys.get(0) {
2314 Some(&ty) => match ty.sty {
2315 ty::ty_tup(ref tys) => &**tys,
2320 (*arg_types).clone()
2324 span_err!(tcx.sess, sp, E0059,
2325 "cannot use call notation; the first type parameter \
2326 for the function trait is neither a tuple nor unit");
2327 expected_arg_tys = &[];
2328 err_args(fcx.tcx(), args.len())
2331 } else if expected_arg_count == supplied_arg_count {
2333 } else if variadic {
2334 if supplied_arg_count >= expected_arg_count {
2337 span_err!(tcx.sess, sp, E0060,
2338 "this function takes at least {} parameter{} \
2339 but {} parameter{} supplied",
2341 if expected_arg_count == 1 {""} else {"s"},
2343 if supplied_arg_count == 1 {" was"} else {"s were"});
2344 expected_arg_tys = &[];
2345 err_args(fcx.tcx(), supplied_arg_count)
2348 span_err!(tcx.sess, sp, E0061,
2349 "this function takes {} parameter{} but {} parameter{} supplied",
2351 if expected_arg_count == 1 {""} else {"s"},
2353 if supplied_arg_count == 1 {" was"} else {"s were"});
2354 expected_arg_tys = &[];
2355 err_args(fcx.tcx(), supplied_arg_count)
2358 debug!("check_argument_types: formal_tys={:?}",
2359 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2361 // Check the arguments.
2362 // We do this in a pretty awful way: first we typecheck any arguments
2363 // that are not anonymous functions, then we typecheck the anonymous
2364 // functions. This is so that we have more information about the types
2365 // of arguments when we typecheck the functions. This isn't really the
2366 // right way to do this.
2367 let xs = [false, true];
2368 for check_blocks in &xs {
2369 let check_blocks = *check_blocks;
2370 debug!("check_blocks={}", check_blocks);
2372 // More awful hacks: before we check argument types, try to do
2373 // an "opportunistic" vtable resolution of any trait bounds on
2374 // the call. This helps coercions.
2376 vtable::select_new_fcx_obligations(fcx);
2379 // For variadic functions, we don't have a declared type for all of
2380 // the arguments hence we only do our usual type checking with
2381 // the arguments who's types we do know.
2382 let t = if variadic {
2384 } else if tuple_arguments == TupleArguments {
2389 for (i, arg) in args.iter().take(t).enumerate() {
2390 let is_block = match arg.node {
2391 ast::ExprClosure(..) => true,
2395 if is_block == check_blocks {
2396 debug!("checking the argument");
2397 let formal_ty = formal_tys[i];
2399 // The special-cased logic below has three functions:
2400 // 1. Provide as good of an expected type as possible.
2401 let expected = expected_arg_tys.get(i).map(|&ty| {
2402 Expectation::rvalue_hint(ty)
2405 check_expr_with_unifier(fcx, &**arg,
2406 expected.unwrap_or(ExpectHasType(formal_ty)),
2408 // 2. Coerce to the most detailed type that could be coerced
2409 // to, which is `expected_ty` if `rvalue_hint` returns an
2410 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2411 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2412 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2414 // 3. Relate the expected type and the formal one,
2415 // if the expected type was used for the coercion.
2416 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2422 // We also need to make sure we at least write the ty of the other
2423 // arguments which we skipped above.
2425 for arg in args.iter().skip(expected_arg_count) {
2426 check_expr(fcx, &**arg);
2428 // There are a few types which get autopromoted when passed via varargs
2429 // in C but we just error out instead and require explicit casts.
2430 let arg_ty = structurally_resolved_type(fcx, arg.span,
2431 fcx.expr_ty(&**arg));
2433 ty::ty_float(ast::TyF32) => {
2434 fcx.type_error_message(arg.span,
2436 format!("can't pass an {} to variadic \
2437 function, cast to c_double", t)
2440 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2441 fcx.type_error_message(arg.span, |t| {
2442 format!("can't pass {} to variadic \
2443 function, cast to c_int",
2447 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2448 fcx.type_error_message(arg.span, |t| {
2449 format!("can't pass {} to variadic \
2450 function, cast to c_uint",
2460 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2461 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
2462 (0..len).map(|_| tcx.types.err).collect()
2465 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2466 call_expr: &ast::Expr,
2467 output: ty::FnOutput<'tcx>) {
2468 fcx.write_ty(call_expr.id, match output {
2469 ty::FnConverging(output_ty) => output_ty,
2470 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2474 // AST fragment checking
2475 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2477 expected: Expectation<'tcx>)
2480 let tcx = fcx.ccx.tcx;
2483 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2484 ast::LitBinary(ref v) => {
2485 ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
2486 ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
2487 mutbl: ast::MutImmutable,
2490 ast::LitByte(_) => tcx.types.u8,
2491 ast::LitChar(_) => tcx.types.char,
2492 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2493 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2494 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2495 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2497 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2498 ty::ty_char => Some(tcx.types.u8),
2499 ty::ty_ptr(..) => Some(tcx.types.usize),
2500 ty::ty_bare_fn(..) => Some(tcx.types.usize),
2504 opt_ty.unwrap_or_else(
2505 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2507 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2508 ast::LitFloatUnsuffixed(_) => {
2509 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2511 ty::ty_float(_) => Some(ty),
2515 opt_ty.unwrap_or_else(
2516 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2518 ast::LitBool(_) => tcx.types.bool
2522 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2523 expr: &'tcx ast::Expr,
2524 expected: Ty<'tcx>) {
2525 check_expr_with_unifier(
2526 fcx, expr, ExpectHasType(expected), NoPreference,
2527 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2530 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2531 expr: &'tcx ast::Expr,
2532 expected: Ty<'tcx>) {
2533 check_expr_with_unifier(
2534 fcx, expr, ExpectHasType(expected), NoPreference,
2535 || demand::coerce(fcx, expr.span, expected, expr));
2538 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2539 expected: Ty<'tcx>) {
2540 check_expr_with_unifier(
2541 fcx, expr, ExpectHasType(expected), NoPreference,
2545 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2546 expr: &'tcx ast::Expr,
2547 expected: Expectation<'tcx>) {
2548 check_expr_with_unifier(
2549 fcx, expr, expected, NoPreference,
2553 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2554 expr: &'tcx ast::Expr,
2555 expected: Expectation<'tcx>,
2556 lvalue_pref: LvaluePreference)
2558 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2561 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2562 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2565 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2566 lvalue_pref: LvaluePreference) {
2567 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2570 // determine the `self` type, using fresh variables for all variables
2571 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2572 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2574 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2575 span: Span, // (potential) receiver for this impl
2577 -> TypeAndSubsts<'tcx> {
2578 let tcx = fcx.tcx();
2580 let ity = ty::lookup_item_type(tcx, did);
2581 let (n_tps, rps, raw_ty) =
2582 (ity.generics.types.len(subst::TypeSpace),
2583 ity.generics.regions.get_slice(subst::TypeSpace),
2586 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2587 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2588 let substs = subst::Substs::new_type(tps, rps);
2589 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2591 TypeAndSubsts { substs: substs, ty: substd_ty }
2594 /// Controls whether the arguments are tupled. This is used for the call
2597 /// Tupling means that all call-side arguments are packed into a tuple and
2598 /// passed as a single parameter. For example, if tupling is enabled, this
2601 /// fn f(x: (isize, isize))
2603 /// Can be called as:
2610 #[derive(Clone, Eq, PartialEq)]
2611 enum TupleArgumentsFlag {
2616 /// Unifies the return type with the expected type early, for more coercions
2617 /// and forward type information on the argument expressions.
2618 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2620 expected_ret: Expectation<'tcx>,
2621 formal_ret: ty::FnOutput<'tcx>,
2622 formal_args: &[Ty<'tcx>])
2624 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2625 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2626 fcx.infcx().commit_regions_if_ok(|| {
2627 // Attempt to apply a subtyping relationship between the formal
2628 // return type (likely containing type variables if the function
2629 // is polymorphic) and the expected return type.
2630 // No argument expectations are produced if unification fails.
2631 let origin = infer::Misc(call_span);
2632 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2633 // FIXME(#15760) can't use try! here, FromError doesn't default
2634 // to identity so the resulting type is not constrained.
2635 if let Err(e) = ures {
2639 // Record all the argument types, with the substitutions
2640 // produced from the above subtyping unification.
2641 Ok(formal_args.iter().map(|ty| {
2642 fcx.infcx().resolve_type_vars_if_possible(ty)
2648 }).unwrap_or(vec![]);
2649 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2650 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2651 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2656 /// If an expression has any sub-expressions that result in a type error,
2657 /// inspecting that expression's type with `ty::type_is_error` will return
2658 /// true. Likewise, if an expression is known to diverge, inspecting its
2659 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2660 /// strict, _|_ can appear in the type of an expression that does not,
2661 /// itself, diverge: for example, fn() -> _|_.)
2662 /// Note that inspecting a type's structure *directly* may expose the fact
2663 /// that there are actually multiple representations for `ty_err`, so avoid
2664 /// that when err needs to be handled differently.
2665 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2666 expr: &'tcx ast::Expr,
2667 expected: Expectation<'tcx>,
2668 lvalue_pref: LvaluePreference,
2672 debug!(">> typechecking: expr={} expected={}",
2673 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2675 // Checks a method call.
2676 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2677 expr: &'tcx ast::Expr,
2678 method_name: ast::SpannedIdent,
2679 args: &'tcx [P<ast::Expr>],
2681 expected: Expectation<'tcx>,
2682 lvalue_pref: LvaluePreference) {
2683 let rcvr = &*args[0];
2684 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2686 // no need to check for bot/err -- callee does that
2687 let expr_t = structurally_resolved_type(fcx,
2689 fcx.expr_ty(&*rcvr));
2691 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2692 let fn_ty = match method::lookup(fcx,
2694 method_name.node.name,
2700 let method_ty = method.ty;
2701 let method_call = MethodCall::expr(expr.id);
2702 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2706 method::report_error(fcx, method_name.span, expr_t,
2707 method_name.node.name, Some(rcvr), error);
2708 fcx.write_error(expr.id);
2713 // Call the generic checker.
2714 let ret_ty = check_method_argument_types(fcx,
2722 write_call(fcx, expr, ret_ty);
2725 // A generic function for checking the then and else in an if
2727 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2728 cond_expr: &'tcx ast::Expr,
2729 then_blk: &'tcx ast::Block,
2730 opt_else_expr: Option<&'tcx ast::Expr>,
2733 expected: Expectation<'tcx>) {
2734 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2736 let expected = expected.adjust_for_branches(fcx);
2737 check_block_with_expected(fcx, then_blk, expected);
2738 let then_ty = fcx.node_ty(then_blk.id);
2740 let branches_ty = match opt_else_expr {
2741 Some(ref else_expr) => {
2742 check_expr_with_expectation(fcx, &**else_expr, expected);
2743 let else_ty = fcx.expr_ty(&**else_expr);
2744 infer::common_supertype(fcx.infcx(),
2745 infer::IfExpression(sp),
2751 infer::common_supertype(fcx.infcx(),
2752 infer::IfExpressionWithNoElse(sp),
2755 ty::mk_nil(fcx.tcx()))
2759 let cond_ty = fcx.expr_ty(cond_expr);
2760 let if_ty = if ty::type_is_error(cond_ty) {
2766 fcx.write_ty(id, if_ty);
2769 // Check field access expressions
2770 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2771 expr: &'tcx ast::Expr,
2772 lvalue_pref: LvaluePreference,
2773 base: &'tcx ast::Expr,
2774 field: &ast::SpannedIdent) {
2775 let tcx = fcx.ccx.tcx;
2776 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2777 let expr_t = structurally_resolved_type(fcx, expr.span,
2779 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2780 let (_, autoderefs, field_ty) = autoderef(fcx,
2784 UnresolvedTypeAction::Error,
2788 ty::ty_struct(base_id, substs) => {
2789 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2790 let fields = ty::lookup_struct_fields(tcx, base_id);
2791 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
2792 field.node.name, &(*substs))
2799 fcx.write_ty(expr.id, field_ty);
2800 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
2806 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
2807 fcx.type_error_message(
2810 format!("attempted to take value of method `{}` on type \
2811 `{}`", token::get_ident(field.node), actual)
2815 tcx.sess.fileline_help(field.span,
2816 "maybe a `()` to call it is missing? \
2817 If not, try an anonymous function");
2819 fcx.type_error_message(
2822 format!("attempted access of field `{}` on \
2823 type `{}`, but no field with that \
2825 token::get_ident(field.node),
2829 if let Some(t) = ty::ty_to_def_id(expr_t) {
2830 suggest_field_names(t, field, tcx, vec![]);
2834 fcx.write_error(expr.id);
2837 // displays hints about the closest matches in field names
2838 fn suggest_field_names<'tcx>(id : DefId,
2839 field : &ast::SpannedIdent,
2840 tcx : &ty::ctxt<'tcx>,
2842 let ident = token::get_ident(field.node);
2844 // only find fits with at least one matching letter
2845 let mut best_dist = name.len();
2846 let fields = ty::lookup_struct_fields(tcx, id);
2847 let mut best = None;
2848 for elem in &fields {
2849 let n = elem.name.as_str();
2850 // ignore already set fields
2851 if skip.iter().any(|&x| x == n) {
2854 // ignore private fields from non-local crates
2855 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
2858 let dist = lev_distance(n, name);
2859 if dist < best_dist {
2864 if let Some(n) = best {
2865 tcx.sess.span_help(field.span,
2866 &format!("did you mean `{}`?", n));
2870 // Check tuple index expressions
2871 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2872 expr: &'tcx ast::Expr,
2873 lvalue_pref: LvaluePreference,
2874 base: &'tcx ast::Expr,
2875 idx: codemap::Spanned<usize>) {
2876 let tcx = fcx.ccx.tcx;
2877 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2878 let expr_t = structurally_resolved_type(fcx, expr.span,
2880 let mut tuple_like = false;
2881 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2882 let (_, autoderefs, field_ty) = autoderef(fcx,
2886 UnresolvedTypeAction::Error,
2890 ty::ty_struct(base_id, substs) => {
2891 tuple_like = ty::is_tuple_struct(tcx, base_id);
2893 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
2894 let fields = ty::lookup_struct_fields(tcx, base_id);
2895 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
2896 idx.node, &(*substs))
2901 ty::ty_tup(ref v) => {
2903 if idx.node < v.len() { Some(v[idx.node]) } else { None }
2910 fcx.write_ty(expr.id, field_ty);
2911 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
2916 fcx.type_error_message(
2920 format!("attempted out-of-bounds tuple index `{}` on \
2925 format!("attempted tuple index `{}` on type `{}`, but the \
2926 type was not a tuple or tuple struct",
2933 fcx.write_error(expr.id);
2936 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2937 struct_ty: Ty<'tcx>,
2939 class_id: ast::DefId,
2940 node_id: ast::NodeId,
2941 substitutions: &'tcx subst::Substs<'tcx>,
2942 field_types: &[ty::field_ty],
2943 ast_fields: &'tcx [ast::Field],
2944 check_completeness: bool,
2945 enum_id_opt: Option<ast::DefId>) {
2946 let tcx = fcx.ccx.tcx;
2948 let mut class_field_map = FnvHashMap();
2949 let mut fields_found = 0;
2950 for field in field_types {
2951 class_field_map.insert(field.name, (field.id, false));
2954 let mut error_happened = false;
2956 // Typecheck each field.
2957 for field in ast_fields {
2958 let mut expected_field_type = tcx.types.err;
2960 let pair = class_field_map.get(&field.ident.node.name).cloned();
2963 fcx.type_error_message(
2965 |actual| match enum_id_opt {
2967 let variant_type = ty::enum_variant_with_id(tcx,
2970 format!("struct variant `{}::{}` has no field named `{}`",
2971 actual, variant_type.name.as_str(),
2972 token::get_ident(field.ident.node))
2975 format!("structure `{}` has no field named `{}`",
2977 token::get_ident(field.ident.node))
2982 // prevent all specified fields from being suggested
2983 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
2984 let actual_id = match enum_id_opt {
2985 Some(_) => class_id,
2986 None => ty::ty_to_def_id(struct_ty).unwrap()
2988 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
2989 error_happened = true;
2991 Some((_, true)) => {
2992 span_err!(fcx.tcx().sess, field.ident.span, E0062,
2993 "field `{}` specified more than once",
2994 token::get_ident(field.ident.node));
2995 error_happened = true;
2997 Some((field_id, false)) => {
2998 expected_field_type =
2999 ty::lookup_field_type(
3000 tcx, class_id, field_id, substitutions);
3001 expected_field_type =
3002 fcx.normalize_associated_types_in(
3003 field.span, &expected_field_type);
3004 class_field_map.insert(
3005 field.ident.node.name, (field_id, true));
3010 // Make sure to give a type to the field even if there's
3011 // an error, so we can continue typechecking
3012 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3016 fcx.write_error(node_id);
3019 if check_completeness && !error_happened {
3020 // Make sure the programmer specified all the fields.
3021 assert!(fields_found <= field_types.len());
3022 if fields_found < field_types.len() {
3023 let mut missing_fields = Vec::new();
3024 for class_field in field_types {
3025 let name = class_field.name;
3026 let (_, seen) = *class_field_map.get(&name).unwrap();
3028 missing_fields.push(
3029 format!("`{}`", &token::get_name(name)))
3033 span_err!(tcx.sess, span, E0063,
3034 "missing field{}: {}",
3035 if missing_fields.len() == 1 {""} else {"s"},
3036 missing_fields.connect(", "));
3040 if !error_happened {
3041 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3042 class_id, substitutions));
3046 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3048 span: codemap::Span,
3049 class_id: ast::DefId,
3050 fields: &'tcx [ast::Field],
3051 base_expr: Option<&'tcx ast::Expr>) {
3052 let tcx = fcx.ccx.tcx;
3054 // Generate the struct type.
3056 ty: mut struct_type,
3057 substs: struct_substs
3058 } = fcx.instantiate_type(span, class_id);
3060 // Look up and check the fields.
3061 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3062 check_struct_or_variant_fields(fcx,
3067 fcx.ccx.tcx.mk_substs(struct_substs),
3070 base_expr.is_none(),
3072 if ty::type_is_error(fcx.node_ty(id)) {
3073 struct_type = tcx.types.err;
3076 // Check the base expression if necessary.
3079 Some(base_expr) => {
3080 check_expr_has_type(fcx, &*base_expr, struct_type);
3084 // Write in the resulting type.
3085 fcx.write_ty(id, struct_type);
3088 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3090 span: codemap::Span,
3091 enum_id: ast::DefId,
3092 variant_id: ast::DefId,
3093 fields: &'tcx [ast::Field]) {
3094 let tcx = fcx.ccx.tcx;
3096 // Look up the number of type parameters and the raw type, and
3097 // determine whether the enum is region-parameterized.
3100 substs: substitutions
3101 } = fcx.instantiate_type(span, enum_id);
3103 // Look up and check the enum variant fields.
3104 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3105 check_struct_or_variant_fields(fcx,
3110 fcx.ccx.tcx.mk_substs(substitutions),
3111 &variant_fields[..],
3115 fcx.write_ty(id, enum_type);
3118 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3120 fields: &'tcx [ast::Field],
3121 base_expr: &'tcx Option<P<ast::Expr>>) {
3122 // Make sure to still write the types
3123 // otherwise we might ICE
3124 fcx.write_error(id);
3125 for field in fields {
3126 check_expr(fcx, &*field.expr);
3129 Some(ref base) => check_expr(fcx, &**base),
3134 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3136 let tcx = fcx.ccx.tcx;
3139 ast::ExprBox(ref opt_place, ref subexpr) => {
3140 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3141 check_expr(fcx, &**subexpr);
3143 let mut checked = false;
3144 opt_place.as_ref().map(|place| match place.node {
3145 ast::ExprPath(None, ref path) => {
3146 // FIXME(pcwalton): For now we hardcode the two permissible
3147 // places: the exchange heap and the managed heap.
3148 let definition = lookup_full_def(tcx, path.span, place.id);
3149 let def_id = definition.def_id();
3150 let referent_ty = fcx.expr_ty(&**subexpr);
3151 if tcx.lang_items.exchange_heap() == Some(def_id) {
3152 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3160 span_err!(tcx.sess, expr.span, E0066,
3161 "only the managed heap and exchange heap are currently supported");
3162 fcx.write_ty(id, tcx.types.err);
3166 ast::ExprLit(ref lit) => {
3167 let typ = check_lit(fcx, &**lit, expected);
3168 fcx.write_ty(id, typ);
3170 ast::ExprBinary(op, ref lhs, ref rhs) => {
3171 op::check_binop(fcx, expr, op, lhs, rhs);
3173 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3174 op::check_binop_assign(fcx, expr, op, lhs, rhs);
3176 ast::ExprUnary(unop, ref oprnd) => {
3177 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3179 ast::UnUniq => match ty.sty {
3180 ty::ty_uniq(ty) => {
3181 Expectation::rvalue_hint(ty)
3187 ast::UnNot | ast::UnNeg => {
3195 let lvalue_pref = match unop {
3196 ast::UnDeref => lvalue_pref,
3199 check_expr_with_expectation_and_lvalue_pref(
3200 fcx, &**oprnd, expected_inner, lvalue_pref);
3201 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3203 if !ty::type_is_error(oprnd_t) {
3206 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3209 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3210 oprnd_t = match ty::deref(oprnd_t, true) {
3212 None => match try_overloaded_deref(fcx, expr.span,
3213 Some(MethodCall::expr(expr.id)),
3214 Some(&**oprnd), oprnd_t, lvalue_pref) {
3217 let is_newtype = match oprnd_t.sty {
3218 ty::ty_struct(did, substs) => {
3219 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3221 && fields[0].name ==
3222 token::special_idents::unnamed_field.name
3227 // This is an obsolete struct deref
3228 span_err!(tcx.sess, expr.span, E0068,
3229 "single-field tuple-structs can \
3230 no longer be dereferenced");
3232 fcx.type_error_message(expr.span, |actual| {
3233 format!("type `{}` cannot be \
3234 dereferenced", actual)
3243 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3245 if !(ty::type_is_integral(oprnd_t) ||
3246 oprnd_t.sty == ty::ty_bool) {
3247 oprnd_t = op::check_user_unop(fcx, "!", "not",
3248 tcx.lang_items.not_trait(),
3249 expr, &**oprnd, oprnd_t, unop);
3253 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3255 if !(ty::type_is_integral(oprnd_t) ||
3256 ty::type_is_fp(oprnd_t)) {
3257 oprnd_t = op::check_user_unop(fcx, "-", "neg",
3258 tcx.lang_items.neg_trait(),
3259 expr, &**oprnd, oprnd_t, unop);
3264 fcx.write_ty(id, oprnd_t);
3266 ast::ExprAddrOf(mutbl, ref oprnd) => {
3267 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3269 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3270 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3271 // Lvalues may legitimately have unsized types.
3272 // For example, dereferences of a fat pointer and
3273 // the last field of a struct can be unsized.
3274 ExpectHasType(mt.ty)
3276 Expectation::rvalue_hint(mt.ty)
3282 let lvalue_pref = match mutbl {
3283 ast::MutMutable => PreferMutLvalue,
3284 ast::MutImmutable => NoPreference
3286 check_expr_with_expectation_and_lvalue_pref(fcx,
3291 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3292 let oprnd_t = if ty::type_is_error(tm.ty) {
3295 // Note: at this point, we cannot say what the best lifetime
3296 // is to use for resulting pointer. We want to use the
3297 // shortest lifetime possible so as to avoid spurious borrowck
3298 // errors. Moreover, the longest lifetime will depend on the
3299 // precise details of the value whose address is being taken
3300 // (and how long it is valid), which we don't know yet until type
3301 // inference is complete.
3303 // Therefore, here we simply generate a region variable. The
3304 // region inferencer will then select the ultimate value.
3305 // Finally, borrowck is charged with guaranteeing that the
3306 // value whose address was taken can actually be made to live
3307 // as long as it needs to live.
3308 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3309 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3311 fcx.write_ty(id, oprnd_t);
3313 ast::ExprPath(ref maybe_qself, ref path) => {
3314 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3315 fcx.to_ty(&qself.ty)
3318 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3320 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3321 // Create some fake resolution that can't possibly be a type.
3322 def::PathResolution {
3323 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3324 last_private: LastMod(AllPublic),
3325 depth: path.segments.len()
3328 tcx.sess.span_bug(expr.span,
3329 &format!("unbound path {}", expr.repr(tcx)))
3332 let def = path_res.base_def;
3333 if path_res.depth == 0 {
3334 let (scheme, predicates) =
3335 type_scheme_and_predicates_for_def(fcx, expr.span, def);
3336 instantiate_path(fcx, &path.segments,
3337 scheme, &predicates,
3338 opt_self_ty, def, expr.span, id);
3340 let ty_segments = path.segments.init();
3341 let base_ty_end = path.segments.len() - path_res.depth;
3342 let ty = astconv::finish_resolving_def_to_ty(fcx,
3345 PathParamMode::Optional,
3348 &ty_segments[..base_ty_end],
3349 &ty_segments[base_ty_end..]);
3350 let method_segment = path.segments.last().unwrap();
3351 let method_name = method_segment.identifier.name;
3352 match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
3354 // Write back the new resolution.
3355 tcx.def_map.borrow_mut().insert(id, def::PathResolution {
3357 last_private: path_res.last_private.or(lp),
3361 let (scheme, predicates) =
3362 type_scheme_and_predicates_for_def(fcx, expr.span, def);
3363 instantiate_path(fcx, slice::ref_slice(method_segment),
3364 scheme, &predicates,
3365 Some(ty), def, expr.span, id);
3368 method::report_error(fcx, expr.span, ty,
3369 method_name, None, error);
3370 fcx.write_error(id);
3375 // We always require that the type provided as the value for
3376 // a type parameter outlives the moment of instantiation.
3377 constrain_path_type_parameters(fcx, expr);
3379 ast::ExprInlineAsm(ref ia) => {
3380 for &(_, ref input) in &ia.inputs {
3381 check_expr(fcx, &**input);
3383 for &(_, ref out, _) in &ia.outputs {
3384 check_expr(fcx, &**out);
3388 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3389 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3390 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3391 ast::ExprRet(ref expr_opt) => {
3393 ty::FnConverging(result_type) => {
3396 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3397 result_type, ty::mk_nil(fcx.tcx())) {
3398 span_err!(tcx.sess, expr.span, E0069,
3399 "`return;` in function returning non-nil");
3402 check_expr_coercable_to_type(fcx, &**e, result_type);
3406 ty::FnDiverging => {
3407 if let Some(ref e) = *expr_opt {
3408 check_expr(fcx, &**e);
3410 span_err!(tcx.sess, expr.span, E0166,
3411 "`return` in a function declared as diverging");
3414 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3416 ast::ExprParen(ref a) => {
3417 check_expr_with_expectation_and_lvalue_pref(fcx,
3421 fcx.write_ty(id, fcx.expr_ty(&**a));
3423 ast::ExprAssign(ref lhs, ref rhs) => {
3424 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3426 let tcx = fcx.tcx();
3427 if !ty::expr_is_lval(tcx, &**lhs) {
3428 span_err!(tcx.sess, expr.span, E0070,
3429 "illegal left-hand side expression");
3432 let lhs_ty = fcx.expr_ty(&**lhs);
3433 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3434 let rhs_ty = fcx.expr_ty(&**rhs);
3436 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3438 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3439 fcx.write_error(id);
3444 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3445 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3446 id, expr.span, expected);
3448 ast::ExprIfLet(..) => {
3449 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3451 ast::ExprWhile(ref cond, ref body, _) => {
3452 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3453 check_block_no_value(fcx, &**body);
3454 let cond_ty = fcx.expr_ty(&**cond);
3455 let body_ty = fcx.node_ty(body.id);
3456 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3457 fcx.write_error(id);
3463 ast::ExprWhileLet(..) => {
3464 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3466 ast::ExprForLoop(..) => {
3467 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3469 ast::ExprLoop(ref body, _) => {
3470 check_block_no_value(fcx, &**body);
3471 if !may_break(tcx, expr.id, &**body) {
3472 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3477 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3478 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3480 ast::ExprClosure(capture, ref decl, ref body) => {
3481 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3483 ast::ExprBlock(ref b) => {
3484 check_block_with_expected(fcx, &**b, expected);
3485 fcx.write_ty(id, fcx.node_ty(b.id));
3487 ast::ExprCall(ref callee, ref args) => {
3488 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3490 ast::ExprMethodCall(ident, ref tps, ref args) => {
3491 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3492 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3493 let args_err = arg_tys.fold(false,
3495 rest_err || ty::type_is_error(a)});
3497 fcx.write_error(id);
3500 ast::ExprCast(ref e, ref t) => {
3501 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3502 check_expr_with_hint(fcx, &**count_expr, tcx.types.usize);
3505 // Find the type of `e`. Supply hints based on the type we are casting to,
3507 let t_1 = fcx.to_ty(t);
3508 let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
3509 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
3510 let t_e = fcx.expr_ty(e);
3512 // Eagerly check for some obvious errors.
3513 if ty::type_is_error(t_e) {
3514 fcx.write_error(id);
3515 } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
3516 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
3518 // Write a type for the whole expression, assuming everything is going
3520 fcx.write_ty(id, t_1);
3522 // Defer other checks until we're done type checking.
3523 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3524 deferred_cast_checks.push(CastCheck {
3525 expr: (**e).clone(),
3532 ast::ExprVec(ref args) => {
3533 let uty = expected.to_option(fcx).and_then(|uty| {
3535 ty::ty_vec(ty, _) => Some(ty),
3540 let typ = match uty {
3543 check_expr_coercable_to_type(fcx, &**e, uty);
3548 let t: Ty = fcx.infcx().next_ty_var();
3550 check_expr_has_type(fcx, &**e, t);
3555 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3556 fcx.write_ty(id, typ);
3558 ast::ExprRepeat(ref element, ref count_expr) => {
3559 check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
3560 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3562 let uty = match expected {
3563 ExpectHasType(uty) => {
3565 ty::ty_vec(ty, _) => Some(ty),
3572 let (element_ty, t) = match uty {
3574 check_expr_coercable_to_type(fcx, &**element, uty);
3578 let t: Ty = fcx.infcx().next_ty_var();
3579 check_expr_has_type(fcx, &**element, t);
3580 (fcx.expr_ty(&**element), t)
3585 // For [foo, ..n] where n > 1, `foo` must have
3587 fcx.require_type_meets(
3594 if ty::type_is_error(element_ty) {
3595 fcx.write_error(id);
3597 let t = ty::mk_vec(tcx, t, Some(count));
3598 fcx.write_ty(id, t);
3601 ast::ExprTup(ref elts) => {
3602 let flds = expected.only_has_type(fcx).and_then(|ty| {
3604 ty::ty_tup(ref flds) => Some(&flds[..]),
3608 let mut err_field = false;
3610 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3611 let t = match flds {
3612 Some(ref fs) if i < fs.len() => {
3614 check_expr_coercable_to_type(fcx, &**e, ety);
3618 check_expr_with_expectation(fcx, &**e, NoExpectation);
3622 err_field = err_field || ty::type_is_error(t);
3626 fcx.write_error(id);
3628 let typ = ty::mk_tup(tcx, elt_ts);
3629 fcx.write_ty(id, typ);
3632 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3633 // Resolve the path.
3634 let def = lookup_full_def(tcx, path.span, id);
3635 let struct_id = match def {
3636 def::DefVariant(enum_id, variant_id, true) => {
3637 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3638 variant_id, &fields[..]);
3641 def::DefTrait(def_id) => {
3642 span_err!(tcx.sess, path.span, E0159,
3643 "use of trait `{}` as a struct constructor",
3644 pprust::path_to_string(path));
3645 check_struct_fields_on_error(fcx,
3652 // Verify that this was actually a struct.
3653 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3655 ty::ty_struct(struct_did, _) => {
3656 check_struct_constructor(fcx,
3661 base_expr.as_ref().map(|e| &**e));
3664 span_err!(tcx.sess, path.span, E0071,
3665 "`{}` does not name a structure",
3666 pprust::path_to_string(path));
3667 check_struct_fields_on_error(fcx,
3678 // Turn the path into a type and verify that that type unifies with
3679 // the resulting structure type. This is needed to handle type
3680 // parameters correctly.
3681 let actual_structure_type = fcx.expr_ty(&*expr);
3682 if !ty::type_is_error(actual_structure_type) {
3683 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3684 match fcx.mk_subty(false,
3685 infer::Misc(path.span),
3686 actual_structure_type,
3687 type_and_substs.ty) {
3689 Err(type_error) => {
3690 let type_error_description =
3691 ty::type_err_to_str(tcx, &type_error);
3692 span_err!(fcx.tcx().sess, path.span, E0235,
3693 "structure constructor specifies a \
3694 structure of type `{}`, but this \
3695 structure has type `{}`: {}",
3697 .ty_to_string(type_and_substs.ty),
3700 actual_structure_type),
3701 type_error_description);
3702 ty::note_and_explain_type_err(tcx, &type_error);
3707 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3709 ast::ExprField(ref base, ref field) => {
3710 check_field(fcx, expr, lvalue_pref, &**base, field);
3712 ast::ExprTupField(ref base, idx) => {
3713 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3715 ast::ExprIndex(ref base, ref idx) => {
3716 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3717 let base_t = fcx.expr_ty(&**base);
3718 if ty::type_is_error(base_t) {
3719 fcx.write_ty(id, base_t);
3721 check_expr(fcx, &**idx);
3722 let idx_t = fcx.expr_ty(&**idx);
3723 if ty::type_is_error(idx_t) {
3724 fcx.write_ty(id, idx_t);
3726 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3729 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3731 MethodCall::expr(expr.id),
3741 Some((index_ty, element_ty)) => {
3742 let idx_expr_ty = fcx.expr_ty(idx);
3743 demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3744 fcx.write_ty(id, element_ty);
3747 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3748 fcx.type_error_message(
3751 format!("cannot index a value of type `{}`",
3756 fcx.write_ty(id, fcx.tcx().types.err);
3762 ast::ExprRange(ref start, ref end) => {
3763 let t_start = start.as_ref().map(|e| {
3764 check_expr(fcx, &**e);
3767 let t_end = end.as_ref().map(|e| {
3768 check_expr(fcx, &**e);
3772 let idx_type = match (t_start, t_end) {
3773 (Some(ty), None) | (None, Some(ty)) => {
3776 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3777 ty::type_is_error(t_end)) => {
3778 Some(fcx.tcx().types.err)
3780 (Some(t_start), Some(t_end)) => {
3781 Some(infer::common_supertype(fcx.infcx(),
3782 infer::RangeExpression(expr.span),
3790 // Note that we don't check the type of start/end satisfy any
3791 // bounds because right now the range structs do not have any. If we add
3792 // some bounds, then we'll need to check `t_start` against them here.
3794 let range_type = match idx_type {
3795 Some(idx_type) if ty::type_is_error(idx_type) => {
3799 // Find the did from the appropriate lang item.
3800 let did = match (start, end) {
3801 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3802 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3803 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3805 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3809 if let Some(did) = did {
3810 let predicates = ty::lookup_predicates(tcx, did);
3811 let substs = Substs::new_type(vec![idx_type], vec![]);
3812 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
3813 fcx.add_obligations_for_parameters(
3814 traits::ObligationCause::new(expr.span,
3816 traits::ItemObligation(did)),
3819 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3821 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
3826 // Neither start nor end => RangeFull
3827 if let Some(did) = tcx.lang_items.range_full_struct() {
3828 let substs = Substs::new_type(vec![], vec![]);
3829 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
3831 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
3837 fcx.write_ty(id, range_type);
3842 debug!("type of expr({}) {} is...", expr.id,
3843 syntax::print::pprust::expr_to_string(expr));
3844 debug!("... {}, expected is {}",
3845 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3846 expected.repr(tcx));
3851 fn constrain_path_type_parameters(fcx: &FnCtxt,
3854 fcx.opt_node_ty_substs(expr.id, |item_substs| {
3855 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
3859 impl<'tcx> Expectation<'tcx> {
3860 /// Provide an expectation for an rvalue expression given an *optional*
3861 /// hint, which is not required for type safety (the resulting type might
3862 /// be checked higher up, as is the case with `&expr` and `box expr`), but
3863 /// is useful in determining the concrete type.
3865 /// The primary use case is where the expected type is a fat pointer,
3866 /// like `&[isize]`. For example, consider the following statement:
3868 /// let x: &[isize] = &[1, 2, 3];
3870 /// In this case, the expected type for the `&[1, 2, 3]` expression is
3871 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
3872 /// expectation `ExpectHasType([isize])`, that would be too strong --
3873 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
3874 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
3875 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
3876 /// which still is useful, because it informs integer literals and the like.
3877 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
3878 /// for examples of where this comes up,.
3879 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
3881 ty::ty_vec(_, None) | ty::ty_trait(..) => {
3882 ExpectRvalueLikeUnsized(ty)
3884 _ => ExpectHasType(ty)
3888 // Resolves `expected` by a single level if it is a variable. If
3889 // there is no expected type or resolution is not possible (e.g.,
3890 // no constraints yet present), just returns `None`.
3891 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
3896 ExpectCastableToType(t) => {
3897 ExpectCastableToType(
3898 fcx.infcx().resolve_type_vars_if_possible(&t))
3900 ExpectHasType(t) => {
3902 fcx.infcx().resolve_type_vars_if_possible(&t))
3904 ExpectRvalueLikeUnsized(t) => {
3905 ExpectRvalueLikeUnsized(
3906 fcx.infcx().resolve_type_vars_if_possible(&t))
3911 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3912 match self.resolve(fcx) {
3913 NoExpectation => None,
3914 ExpectCastableToType(ty) |
3916 ExpectRvalueLikeUnsized(ty) => Some(ty),
3920 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
3921 match self.resolve(fcx) {
3922 ExpectHasType(ty) => Some(ty),
3928 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
3929 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
3931 NoExpectation => format!("NoExpectation"),
3932 ExpectHasType(t) => format!("ExpectHasType({})",
3934 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3936 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
3942 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3943 local: &'tcx ast::Local,
3944 init: &'tcx ast::Expr)
3946 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
3948 let local_ty = fcx.local_ty(init.span, local.id);
3950 check_expr_coercable_to_type(fcx, init, local_ty)
3952 // Somewhat subtle: if we have a `ref` binding in the pattern,
3953 // we want to avoid introducing coercions for the RHS. This is
3954 // both because it helps preserve sanity and, in the case of
3955 // ref mut, for soundness (issue #23116). In particular, in
3956 // the latter case, we need to be clear that the type of the
3957 // referent for the reference that results is *equal to* the
3958 // type of the lvalue it is referencing, and not some
3959 // supertype thereof.
3960 check_expr(fcx, init);
3961 let init_ty = fcx.expr_ty(init);
3962 demand::eqtype(fcx, init.span, init_ty, local_ty);
3966 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
3967 let tcx = fcx.ccx.tcx;
3969 let t = fcx.local_ty(local.span, local.id);
3970 fcx.write_ty(local.id, t);
3972 if let Some(ref init) = local.init {
3973 check_decl_initializer(fcx, local, &**init);
3974 let init_ty = fcx.expr_ty(&**init);
3975 if ty::type_is_error(init_ty) {
3976 fcx.write_ty(local.id, init_ty);
3980 let pcx = pat_ctxt {
3982 map: pat_id_map(&tcx.def_map, &*local.pat),
3984 _match::check_pat(&pcx, &*local.pat, t);
3985 let pat_ty = fcx.node_ty(local.pat.id);
3986 if ty::type_is_error(pat_ty) {
3987 fcx.write_ty(local.id, pat_ty);
3991 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
3993 let mut saw_bot = false;
3994 let mut saw_err = false;
3996 ast::StmtDecl(ref decl, id) => {
3999 ast::DeclLocal(ref l) => {
4000 check_decl_local(fcx, &**l);
4001 let l_t = fcx.node_ty(l.id);
4002 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4003 saw_err = saw_err || ty::type_is_error(l_t);
4005 ast::DeclItem(_) => {/* ignore for now */ }
4008 ast::StmtExpr(ref expr, id) => {
4010 // Check with expected type of ()
4011 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4012 let expr_ty = fcx.expr_ty(&**expr);
4013 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4014 saw_err = saw_err || ty::type_is_error(expr_ty);
4016 ast::StmtSemi(ref expr, id) => {
4018 check_expr(fcx, &**expr);
4019 let expr_ty = fcx.expr_ty(&**expr);
4020 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4021 saw_err |= ty::type_is_error(expr_ty);
4023 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4026 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4029 fcx.write_error(node_id);
4032 fcx.write_nil(node_id)
4036 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4037 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4038 let blkty = fcx.node_ty(blk.id);
4039 if ty::type_is_error(blkty) {
4040 fcx.write_error(blk.id);
4042 let nilty = ty::mk_nil(fcx.tcx());
4043 demand::suptype(fcx, blk.span, nilty, blkty);
4047 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4048 blk: &'tcx ast::Block,
4049 expected: Expectation<'tcx>) {
4051 let mut fcx_ps = fcx.ps.borrow_mut();
4052 let unsafety_state = fcx_ps.recurse(blk);
4053 replace(&mut *fcx_ps, unsafety_state)
4056 let mut warned = false;
4057 let mut any_diverges = false;
4058 let mut any_err = false;
4059 for s in &blk.stmts {
4060 check_stmt(fcx, &**s);
4061 let s_id = ast_util::stmt_id(&**s);
4062 let s_ty = fcx.node_ty(s_id);
4063 if any_diverges && !warned && match s.node {
4064 ast::StmtDecl(ref decl, _) => {
4066 ast::DeclLocal(_) => true,
4070 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4076 .add_lint(lint::builtin::UNREACHABLE_CODE,
4079 "unreachable statement".to_string());
4082 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4083 any_err = any_err || ty::type_is_error(s_ty);
4086 None => if any_err {
4087 fcx.write_error(blk.id);
4088 } else if any_diverges {
4089 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4091 fcx.write_nil(blk.id);
4094 if any_diverges && !warned {
4098 .add_lint(lint::builtin::UNREACHABLE_CODE,
4101 "unreachable expression".to_string());
4103 let ety = match expected {
4104 ExpectHasType(ety) => {
4105 check_expr_coercable_to_type(fcx, &**e, ety);
4109 check_expr_with_expectation(fcx, &**e, expected);
4115 fcx.write_error(blk.id);
4116 } else if any_diverges {
4117 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4119 fcx.write_ty(blk.id, ety);
4124 *fcx.ps.borrow_mut() = prev;
4127 /// Checks a constant appearing in a type. At the moment this is just the
4128 /// length expression in a fixed-length vector, but someday it might be
4129 /// extended to type-level numeric literals.
4130 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4131 expr: &'tcx ast::Expr,
4132 expected_type: Ty<'tcx>) {
4133 let inh = static_inherited_fields(ccx);
4134 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4135 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4138 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4142 let inh = static_inherited_fields(ccx);
4143 let rty = ty::node_id_to_type(ccx.tcx, id);
4144 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4145 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
4146 check_const_with_ty(&fcx, sp, e, declty);
4149 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4153 // Gather locals in statics (because of block expressions).
4154 // This is technically unnecessary because locals in static items are forbidden,
4155 // but prevents type checking from blowing up before const checking can properly
4157 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4159 check_expr_with_hint(fcx, e, declty);
4160 demand::coerce(fcx, e.span, declty, e);
4161 vtable::select_all_fcx_obligations_or_error(fcx);
4163 regionck::regionck_expr(fcx, e);
4164 writeback::resolve_type_vars_in_expr(fcx, e);
4167 /// Checks whether a type can be represented in memory. In particular, it
4168 /// identifies types that contain themselves without indirection through a
4169 /// pointer, which would mean their size is unbounded. This is different from
4170 /// the question of whether a type can be instantiated. See the definition of
4171 /// `check_instantiable`.
4172 pub fn check_representable(tcx: &ty::ctxt,
4174 item_id: ast::NodeId,
4175 designation: &str) -> bool {
4176 let rty = ty::node_id_to_type(tcx, item_id);
4178 // Check that it is possible to represent this type. This call identifies
4179 // (1) types that contain themselves and (2) types that contain a different
4180 // recursive type. It is only necessary to throw an error on those that
4181 // contain themselves. For case 2, there must be an inner type that will be
4182 // caught by case 1.
4183 match ty::is_type_representable(tcx, sp, rty) {
4184 ty::SelfRecursive => {
4185 span_err!(tcx.sess, sp, E0072,
4186 "illegal recursive {} type; \
4187 wrap the inner value in a box to make it representable",
4191 ty::Representable | ty::ContainsRecursive => (),
4196 /// Checks whether a type can be created without an instance of itself.
4197 /// This is similar but different from the question of whether a type
4198 /// can be represented. For example, the following type:
4200 /// enum foo { None, Some(foo) }
4202 /// is instantiable but is not representable. Similarly, the type
4204 /// enum foo { Some(@foo) }
4206 /// is representable, but not instantiable.
4207 pub fn check_instantiable(tcx: &ty::ctxt,
4209 item_id: ast::NodeId)
4211 let item_ty = ty::node_id_to_type(tcx, item_id);
4212 if !ty::is_instantiable(tcx, item_ty) {
4213 span_err!(tcx.sess, sp, E0073,
4214 "this type cannot be instantiated without an \
4215 instance of itself");
4216 fileline_help!(tcx.sess, sp, "consider using `Option<{}>`",
4217 ppaux::ty_to_string(tcx, item_ty));
4224 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4225 let t = ty::node_id_to_type(tcx, id);
4226 if ty::type_needs_subst(t) {
4227 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4231 ty::ty_struct(did, substs) => {
4232 let fields = ty::lookup_struct_fields(tcx, did);
4233 if fields.is_empty() {
4234 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4237 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4238 if !fields.iter().all(
4239 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4240 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4243 if !ty::type_is_machine(e) {
4244 span_err!(tcx.sess, sp, E0077,
4245 "SIMD vector element type should be machine type");
4253 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4255 vs: &'tcx [P<ast::Variant>],
4258 fn disr_in_range(ccx: &CrateCtxt,
4260 disr: ty::Disr) -> bool {
4261 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4263 ast::TyU8 => disr as u8 as Disr == disr,
4264 ast::TyU16 => disr as u16 as Disr == disr,
4265 ast::TyU32 => disr as u32 as Disr == disr,
4266 ast::TyU64 => disr as u64 as Disr == disr,
4267 ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4270 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4272 ast::TyI8 => disr as i8 as Disr == disr,
4273 ast::TyI16 => disr as i16 as Disr == disr,
4274 ast::TyI32 => disr as i32 as Disr == disr,
4275 ast::TyI64 => disr as i64 as Disr == disr,
4276 ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4280 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4281 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4285 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4286 vs: &'tcx [P<ast::Variant>],
4288 hint: attr::ReprAttr)
4289 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4290 #![allow(trivial_numeric_casts)]
4292 let rty = ty::node_id_to_type(ccx.tcx, id);
4293 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4294 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4295 let mut prev_disr_val: Option<ty::Disr> = None;
4299 // If the discriminant value is specified explicitly in the enum check whether the
4300 // initialization expression is valid, otherwise use the last value plus one.
4301 let mut current_disr_val = match prev_disr_val {
4302 Some(prev_disr_val) => {
4303 if let Some(v) = prev_disr_val.checked_add(1) {
4306 ty::INITIAL_DISCRIMINANT_VALUE
4309 None => ty::INITIAL_DISCRIMINANT_VALUE
4312 match v.node.disr_expr {
4314 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4316 let inh = static_inherited_fields(ccx);
4317 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4318 let declty = match hint {
4319 attr::ReprAny | attr::ReprPacked |
4320 attr::ReprExtern => fcx.tcx().types.isize,
4322 attr::ReprInt(_, attr::SignedInt(ity)) => {
4323 ty::mk_mach_int(fcx.tcx(), ity)
4325 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4326 ty::mk_mach_uint(fcx.tcx(), ity)
4329 check_const_with_ty(&fcx, e.span, &**e, declty);
4330 // check_expr (from check_const pass) doesn't guarantee
4331 // that the expression is in a form that eval_const_expr can
4332 // handle, so we may still get an internal compiler error
4334 match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
4335 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4336 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4338 span_err!(ccx.tcx.sess, e.span, E0079,
4339 "expected signed integer constant");
4342 span_err!(ccx.tcx.sess, err.span, E0080,
4343 "constant evaluation error: {}",
4351 // Check for duplicate discriminant values
4352 match disr_vals.iter().position(|&x| x == current_disr_val) {
4354 span_err!(ccx.tcx.sess, v.span, E0081,
4355 "discriminant value `{}` already exists", disr_vals[i]);
4356 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4357 "conflicting discriminant here")
4361 // Check for unrepresentable discriminant values
4363 attr::ReprAny | attr::ReprExtern => (),
4364 attr::ReprInt(sp, ity) => {
4365 if !disr_in_range(ccx, ity, current_disr_val) {
4366 span_err!(ccx.tcx.sess, v.span, E0082,
4367 "discriminant value outside specified type");
4368 span_note!(ccx.tcx.sess, sp,
4369 "discriminant type specified here");
4372 attr::ReprPacked => {
4373 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4376 disr_vals.push(current_disr_val);
4378 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4380 prev_disr_val = Some(current_disr_val);
4382 variants.push(variant_info);
4388 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4389 .get(0).unwrap_or(&attr::ReprAny);
4391 if hint != attr::ReprAny && vs.len() <= 1 {
4393 span_err!(ccx.tcx.sess, sp, E0083,
4394 "unsupported representation for univariant enum");
4396 span_err!(ccx.tcx.sess, sp, E0084,
4397 "unsupported representation for zero-variant enum");
4401 let variants = do_check(ccx, vs, id, hint);
4403 // cache so that ty::enum_variants won't repeat this work
4404 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4406 check_representable(ccx.tcx, sp, id, "enum");
4408 // Check that it is possible to instantiate this enum:
4410 // This *sounds* like the same that as representable, but it's
4411 // not. See def'n of `check_instantiable()` for details.
4412 check_instantiable(ccx.tcx, sp, id);
4415 // Returns the type parameter count and the type for the given definition.
4416 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4419 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4421 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4422 let typ = fcx.local_ty(sp, nid);
4423 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4424 ty::GenericPredicates::empty())
4426 def::DefFn(id, _) | def::DefMethod(id, _) |
4427 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4428 def::DefStruct(id) | def::DefConst(id) => {
4429 (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4433 def::DefAssociatedTy(..) |
4435 def::DefTyParam(..) |
4437 def::DefForeignMod(..) |
4439 def::DefRegion(..) |
4441 def::DefSelfTy(..) => {
4442 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4447 // Instantiates the given path, which must refer to an item with the given
4448 // number of type parameters and type.
4449 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4450 segments: &[ast::PathSegment],
4451 type_scheme: TypeScheme<'tcx>,
4452 type_predicates: &ty::GenericPredicates<'tcx>,
4453 opt_self_ty: Option<Ty<'tcx>>,
4456 node_id: ast::NodeId) {
4457 debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
4459 def.repr(fcx.tcx()),
4461 type_scheme.repr(fcx.tcx()));
4463 // We need to extract the type parameters supplied by the user in
4464 // the path `path`. Due to the current setup, this is a bit of a
4465 // tricky-process; the problem is that resolve only tells us the
4466 // end-point of the path resolution, and not the intermediate steps.
4467 // Luckily, we can (at least for now) deduce the intermediate steps
4468 // just from the end-point.
4470 // There are basically three cases to consider:
4472 // 1. Reference to a *type*, such as a struct or enum:
4474 // mod a { struct Foo<T> { ... } }
4476 // Because we don't allow types to be declared within one
4477 // another, a path that leads to a type will always look like
4478 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4479 // that only the final segment can have type parameters, and
4480 // they are located in the TypeSpace.
4482 // *Note:* Generally speaking, references to types don't
4483 // actually pass through this function, but rather the
4484 // `ast_ty_to_ty` function in `astconv`. However, in the case
4485 // of struct patterns (and maybe literals) we do invoke
4486 // `instantiate_path` to get the general type of an instance of
4487 // a struct. (In these cases, there are actually no type
4488 // parameters permitted at present, but perhaps we will allow
4489 // them in the future.)
4491 // 1b. Reference to a enum variant or tuple-like struct:
4493 // struct foo<T>(...)
4494 // enum E<T> { foo(...) }
4496 // In these cases, the parameters are declared in the type
4499 // 2. Reference to a *fn item*:
4503 // In this case, the path will again always have the form
4504 // `a::b::foo::<T>` where only the final segment should have
4505 // type parameters. However, in this case, those parameters are
4506 // declared on a value, and hence are in the `FnSpace`.
4508 // 3. Reference to a *method*:
4510 // impl<A> SomeStruct<A> {
4514 // Here we can have a path like
4515 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4516 // may appear in two places. The penultimate segment,
4517 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4518 // final segment, `foo::<B>` contains parameters in fn space.
4520 // The first step then is to categorize the segments appropriately.
4522 assert!(segments.len() >= 1);
4524 let mut ufcs_method = None;
4525 let mut segment_spaces: Vec<_>;
4527 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4528 def::DefSelfTy(..) |
4529 def::DefStruct(..) |
4530 def::DefVariant(..) |
4532 def::DefAssociatedTy(..) |
4534 def::DefPrimTy(..) |
4535 def::DefTyParam(..) => {
4536 // Everything but the final segment should have no
4537 // parameters at all.
4538 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4539 segment_spaces.push(Some(subst::TypeSpace));
4542 // Case 2. Reference to a top-level value.
4545 def::DefStatic(..) => {
4546 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4547 segment_spaces.push(Some(subst::FnSpace));
4550 // Case 3. Reference to a method.
4551 def::DefMethod(_, provenance) => {
4553 def::FromTrait(trait_did) => {
4554 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4556 def::FromImpl(_) => {}
4559 if segments.len() >= 2 {
4560 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4561 segment_spaces.push(Some(subst::TypeSpace));
4562 segment_spaces.push(Some(subst::FnSpace));
4564 // `<T>::method` will end up here, and so can `T::method`.
4565 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4566 segment_spaces = vec![Some(subst::FnSpace)];
4567 ufcs_method = Some((provenance, self_ty));
4571 // Other cases. Various nonsense that really shouldn't show up
4572 // here. If they do, an error will have been reported
4573 // elsewhere. (I hope)
4575 def::DefForeignMod(..) |
4578 def::DefRegion(..) |
4580 def::DefUpvar(..) => {
4581 segment_spaces = repeat(None).take(segments.len()).collect();
4584 assert_eq!(segment_spaces.len(), segments.len());
4586 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4587 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4588 // type parameters are not mandatory.
4589 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
4591 debug!("segment_spaces={:?}", segment_spaces);
4593 // Next, examine the definition, and determine how many type
4594 // parameters we expect from each space.
4595 let type_defs = &type_scheme.generics.types;
4596 let region_defs = &type_scheme.generics.regions;
4598 // Now that we have categorized what space the parameters for each
4599 // segment belong to, let's sort out the parameters that the user
4600 // provided (if any) into their appropriate spaces. We'll also report
4601 // errors if type parameters are provided in an inappropriate place.
4602 let mut substs = Substs::empty();
4603 for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
4606 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4607 NO_TPS | NO_REGIONS);
4611 push_explicit_parameters_from_segment_to_substs(fcx,
4621 if let Some(self_ty) = opt_self_ty {
4622 if type_defs.len(subst::SelfSpace) == 1 {
4623 substs.types.push(subst::SelfSpace, self_ty);
4627 // Now we have to compare the types that the user *actually*
4628 // provided against the types that were *expected*. If the user
4629 // did not provide any types, then we want to substitute inference
4630 // variables. If the user provided some types, we may still need
4631 // to add defaults. If the user provided *too many* types, that's
4633 for &space in &ParamSpace::all() {
4634 adjust_type_parameters(fcx, span, space, type_defs,
4635 require_type_space, &mut substs);
4636 assert_eq!(substs.types.len(space), type_defs.len(space));
4638 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4639 assert_eq!(substs.regions().len(space), region_defs.len(space));
4642 // The things we are substituting into the type should not contain
4643 // escaping late-bound regions, and nor should the base type scheme.
4644 assert!(!substs.has_regions_escaping_depth(0));
4645 assert!(!type_scheme.has_escaping_regions());
4647 // Add all the obligations that are required, substituting and
4648 // normalized appropriately.
4649 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4650 fcx.add_obligations_for_parameters(
4651 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4654 // Substitute the values for the type parameters into the type of
4655 // the referenced item.
4656 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4659 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4660 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4661 // is inherent, there is no `Self` parameter, instead, the impl needs
4662 // type parameters, which we can infer by unifying the provided `Self`
4663 // with the substituted impl type.
4664 let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
4665 assert_eq!(substs.types.len(subst::TypeSpace),
4666 impl_scheme.generics.types.len(subst::TypeSpace));
4667 assert_eq!(substs.regions().len(subst::TypeSpace),
4668 impl_scheme.generics.regions.len(subst::TypeSpace));
4670 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
4671 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
4672 fcx.tcx().sess.span_bug(span,
4674 "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
4675 self_ty.repr(fcx.tcx()),
4676 impl_ty.repr(fcx.tcx())));
4680 fcx.write_ty(node_id, ty_substituted);
4681 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4684 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4685 /// parameters are provided, then reports an error and clears the output vector.
4687 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4688 /// use inference variables. This seems less likely to lead to derived errors.
4690 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4691 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4692 /// here because we can easily use the precise span of the N+1'th parameter.
4693 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4694 fcx: &FnCtxt<'a, 'tcx>,
4695 space: subst::ParamSpace,
4697 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4698 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4699 segment: &ast::PathSegment,
4700 substs: &mut Substs<'tcx>)
4702 match segment.parameters {
4703 ast::AngleBracketedParameters(ref data) => {
4704 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4705 fcx, space, type_defs, region_defs, data, substs);
4708 ast::ParenthesizedParameters(ref data) => {
4709 span_err!(fcx.tcx().sess, span, E0238,
4710 "parenthesized parameters may only be used with a trait");
4711 push_explicit_parenthesized_parameters_from_segment_to_substs(
4712 fcx, space, span, type_defs, data, substs);
4717 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4718 fcx: &FnCtxt<'a, 'tcx>,
4719 space: subst::ParamSpace,
4720 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4721 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4722 data: &ast::AngleBracketedParameterData,
4723 substs: &mut Substs<'tcx>)
4726 let type_count = type_defs.len(space);
4727 assert_eq!(substs.types.len(space), 0);
4728 for (i, typ) in data.types.iter().enumerate() {
4729 let t = fcx.to_ty(&**typ);
4731 substs.types.push(space, t);
4732 } else if i == type_count {
4733 span_err!(fcx.tcx().sess, typ.span, E0087,
4734 "too many type parameters provided: \
4735 expected at most {} parameter(s), \
4736 found {} parameter(s)",
4737 type_count, data.types.len());
4738 substs.types.truncate(space, 0);
4744 if data.bindings.len() > 0 {
4745 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4746 "unexpected binding of associated item in expression path \
4747 (only allowed in type paths)");
4751 let region_count = region_defs.len(space);
4752 assert_eq!(substs.regions().len(space), 0);
4753 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4754 let r = ast_region_to_region(fcx.tcx(), lifetime);
4755 if i < region_count {
4756 substs.mut_regions().push(space, r);
4757 } else if i == region_count {
4758 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4759 "too many lifetime parameters provided: \
4760 expected {} parameter(s), found {} parameter(s)",
4762 data.lifetimes.len());
4763 substs.mut_regions().truncate(space, 0);
4771 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4772 /// but intended for `Foo(A,B) -> C` form. This expands to
4773 /// roughly the same thing as `Foo<(A,B),C>`. One important
4774 /// difference has to do with the treatment of anonymous
4775 /// regions, which are translated into bound regions (NYI).
4776 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4777 fcx: &FnCtxt<'a, 'tcx>,
4778 space: subst::ParamSpace,
4780 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4781 data: &ast::ParenthesizedParameterData,
4782 substs: &mut Substs<'tcx>)
4784 let type_count = type_defs.len(space);
4786 span_err!(fcx.tcx().sess, span, E0167,
4787 "parenthesized form always supplies 2 type parameters, \
4788 but only {} parameter(s) were expected",
4792 let input_tys: Vec<Ty> =
4793 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4796 ty::mk_tup(fcx.tcx(), input_tys);
4798 if type_count >= 1 {
4799 substs.types.push(space, tuple_ty);
4802 let output_ty: Option<Ty> =
4803 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4806 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4808 if type_count >= 2 {
4809 substs.types.push(space, output_ty);
4813 fn adjust_type_parameters<'a, 'tcx>(
4814 fcx: &FnCtxt<'a, 'tcx>,
4817 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4818 require_type_space: bool,
4819 substs: &mut Substs<'tcx>)
4821 let provided_len = substs.types.len(space);
4822 let desired = defs.get_slice(space);
4823 let required_len = desired.iter()
4824 .take_while(|d| d.default.is_none())
4827 debug!("adjust_type_parameters(space={:?}, \
4836 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4837 assert!(provided_len <= desired.len());
4839 // Nothing specified at all: supply inference variables for
4841 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
4842 substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
4846 // Too few parameters specified: report an error and use Err
4848 if provided_len < required_len {
4850 if desired.len() != required_len { "at least " } else { "" };
4851 span_err!(fcx.tcx().sess, span, E0089,
4852 "too few type parameters provided: expected {}{} parameter(s) \
4853 , found {} parameter(s)",
4854 qualifier, required_len, provided_len);
4855 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
4859 // Otherwise, add in any optional parameters that the user
4860 // omitted. The case of *too many* parameters is handled
4862 // push_explicit_parameters_from_segment_to_substs(). Note
4863 // that the *default* type are expressed in terms of all prior
4864 // parameters, so we have to substitute as we go with the
4865 // partial substitution that we have built up.
4866 for i in provided_len..desired.len() {
4867 let default = desired[i].default.unwrap();
4868 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4869 substs.types.push(space, default);
4871 assert_eq!(substs.types.len(space), desired.len());
4873 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4876 fn adjust_region_parameters(
4880 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4881 substs: &mut Substs)
4883 let provided_len = substs.mut_regions().len(space);
4884 let desired = defs.get_slice(space);
4886 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4887 assert!(provided_len <= desired.len());
4889 // If nothing was provided, just use inference variables.
4890 if provided_len == 0 {
4891 substs.mut_regions().replace(
4893 fcx.infcx().region_vars_for_defs(span, desired));
4897 // If just the right number were provided, everybody is happy.
4898 if provided_len == desired.len() {
4902 // Otherwise, too few were provided. Report an error and then
4903 // use inference variables.
4904 span_err!(fcx.tcx().sess, span, E0090,
4905 "too few lifetime parameters provided: expected {} parameter(s), \
4906 found {} parameter(s)",
4907 desired.len(), provided_len);
4909 substs.mut_regions().replace(
4911 fcx.infcx().region_vars_for_defs(span, desired));
4915 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4919 where F: Fn() -> Ty<'tcx>
4921 let mut ty = fcx.resolve_type_vars_if_possible(ty);
4923 if ty::type_is_ty_var(ty) {
4924 let alternative = f();
4927 if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
4928 fcx.type_error_message(sp, |_actual| {
4929 "the type of this value must be known in this context".to_string()
4931 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
4932 ty = fcx.tcx().types.err;
4934 demand::suptype(fcx, sp, alternative, ty);
4942 // Resolves `typ` by a single level if `typ` is a type variable. If no
4943 // resolution is possible, then an error is reported.
4944 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4949 structurally_resolve_type_or_else(fcx, sp, ty, || {
4954 // Returns true if b contains a break that can exit from b
4955 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
4956 // First: is there an unlabeled break immediately
4958 (loop_query(&*b, |e| {
4960 ast::ExprBreak(None) => true,
4964 // Second: is there a labeled break with label
4965 // <id> nested anywhere inside the loop?
4966 (block_query(b, |e| {
4967 if let ast::ExprBreak(Some(_)) = e.node {
4968 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
4975 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4977 tps: &OwnedSlice<ast::TyParam>,
4979 debug!("check_bounds_are_used(n_tps={}, ty={})",
4980 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4982 // make a vector of booleans initially false, set to true when used
4983 if tps.len() == 0 { return; }
4984 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
4986 ty::walk_ty(ty, |t| {
4988 ty::ty_param(ParamTy {idx, ..}) => {
4989 debug!("Found use of ty param num {}", idx);
4990 tps_used[idx as usize] = true;
4996 for (i, b) in tps_used.iter().enumerate() {
4998 span_err!(ccx.tcx.sess, span, E0091,
4999 "type parameter `{}` is unused",
5000 token::get_ident(tps[i].ident));
5005 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5006 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5007 let name = token::intern(&format!("P{}", n));
5008 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5012 let name = token::get_ident(it.ident);
5013 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5014 let split : Vec<&str> = name.split('_').collect();
5015 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5017 //We only care about the operation here
5018 let (n_tps, inputs, output) = match split[1] {
5019 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5023 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5025 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5028 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5029 "min" | "umax" | "umin" => {
5030 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5034 (0, Vec::new(), ty::mk_nil(tcx))
5037 span_err!(tcx.sess, it.span, E0092,
5038 "unrecognized atomic operation function: `{}`", op);
5042 (n_tps, inputs, ty::FnConverging(output))
5043 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5044 (0, Vec::new(), ty::FnDiverging)
5046 let (n_tps, inputs, output) = match &name[..] {
5047 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5049 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
5050 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
5051 "uninit" => (1, Vec::new(), param(ccx, 0)),
5052 "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5053 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5054 "move_val_init" => {
5057 ty::mk_mut_rptr(tcx,
5058 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5065 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5066 "owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
5068 "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
5069 ast::MutImmutable)),
5070 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5074 ty::mk_ptr(tcx, ty::mt {
5076 mutbl: ast::MutImmutable
5080 ty::mk_ptr(tcx, ty::mt {
5082 mutbl: ast::MutImmutable
5085 "copy" | "copy_nonoverlapping" => {
5088 ty::mk_ptr(tcx, ty::mt {
5090 mutbl: ast::MutImmutable
5092 ty::mk_ptr(tcx, ty::mt {
5094 mutbl: ast::MutMutable
5100 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5103 ty::mk_ptr(tcx, ty::mt {
5105 mutbl: ast::MutMutable
5107 ty::mk_ptr(tcx, ty::mt {
5109 mutbl: ast::MutImmutable
5115 "write_bytes" | "volatile_set_memory" => {
5118 ty::mk_ptr(tcx, ty::mt {
5120 mutbl: ast::MutMutable
5127 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5128 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5131 vec!( tcx.types.f32, tcx.types.i32 ),
5136 vec!( tcx.types.f64, tcx.types.i32 ),
5139 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5140 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5141 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5142 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5145 vec!( tcx.types.f32, tcx.types.f32 ),
5150 vec!( tcx.types.f64, tcx.types.f64 ),
5153 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5154 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5155 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5156 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5157 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5158 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5159 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5160 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5161 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5162 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5165 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5170 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5173 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5174 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5175 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5176 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5177 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5178 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5179 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5180 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5181 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5182 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5183 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5184 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5185 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5186 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5187 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5188 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5189 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5190 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5191 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5192 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5193 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5194 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5195 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5196 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5197 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5198 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5199 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5200 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5201 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5202 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5203 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5206 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5208 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5210 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5211 (0, vec!(tcx.types.i8, tcx.types.i8),
5212 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5214 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5215 (0, vec!(tcx.types.i16, tcx.types.i16),
5216 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5218 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5219 (0, vec!(tcx.types.i32, tcx.types.i32),
5220 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5222 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5223 (0, vec!(tcx.types.i64, tcx.types.i64),
5224 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5226 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5227 (0, vec!(tcx.types.u8, tcx.types.u8),
5228 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5230 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5231 (0, vec!(tcx.types.u16, tcx.types.u16),
5232 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5234 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5235 (0, vec!(tcx.types.u32, tcx.types.u32),
5236 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5238 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5239 (0, vec!(tcx.types.u64, tcx.types.u64),
5240 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5242 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5243 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5245 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5247 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5250 span_err!(tcx.sess, it.span, E0093,
5251 "unrecognized intrinsic function: `{}`", *other);
5255 (n_tps, inputs, ty::FnConverging(output))
5257 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5258 unsafety: ast::Unsafety::Unsafe,
5259 abi: abi::RustIntrinsic,
5260 sig: ty::Binder(FnSig {
5266 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5267 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5268 if i_n_tps != n_tps {
5269 span_err!(tcx.sess, it.span, E0094,
5270 "intrinsic has wrong number of type \
5271 parameters: found {}, expected {}",
5274 require_same_types(tcx,
5281 format!("intrinsic has wrong type: expected `{}`",
5282 ppaux::ty_to_string(ccx.tcx, fty))