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::IsBinopAssignment::*;
83 use self::TupleArgumentsFlag::*;
85 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
86 use check::_match::pat_ctxt;
87 use fmt_macros::{Parser, Piece, Position};
88 use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
89 use middle::{const_eval, def};
91 use middle::mem_categorization as mc;
92 use middle::mem_categorization::McResult;
93 use middle::pat_util::{self, pat_id_map};
94 use middle::privacy::{AllPublic, LastMod};
95 use middle::region::{self, CodeExtent};
96 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
98 use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
99 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
100 use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
101 use middle::ty::liberate_late_bound_regions;
102 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
103 use middle::ty_fold::{TypeFolder, TypeFoldable};
104 use rscope::RegionScope;
105 use session::Session;
106 use {CrateCtxt, lookup_full_def, require_same_types};
109 use util::common::{block_query, ErrorReported, indenter, loop_query};
110 use util::ppaux::{self, Repr};
111 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
112 use util::lev_distance::lev_distance;
114 use std::cell::{Cell, Ref, RefCell};
115 use std::mem::replace;
117 use std::iter::repeat;
119 use syntax::{self, abi, attr};
120 use syntax::attr::AttrMetaMethods;
121 use syntax::ast::{self, DefId, Visibility};
122 use syntax::ast_util::{self, local_def};
123 use syntax::codemap::{self, Span};
124 use syntax::owned_slice::OwnedSlice;
125 use syntax::parse::token;
126 use syntax::print::pprust;
128 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,
291 /// Whether `check_binop` is part of an assignment or not.
292 /// Used to know whether we allow user overloads and to print
293 /// better messages on error.
295 enum IsBinopAssignment{
301 pub struct FnCtxt<'a, 'tcx: 'a> {
302 body_id: ast::NodeId,
304 // This flag is set to true if, during the writeback phase, we encounter
305 // a type error in this function.
306 writeback_errors: Cell<bool>,
308 // Number of errors that had been reported when we started
309 // checking this function. On exit, if we find that *more* errors
310 // have been reported, we will skip regionck and other work that
311 // expects the types within the function to be consistent.
312 err_count_on_creation: uint,
314 ret_ty: ty::FnOutput<'tcx>,
316 ps: RefCell<UnsafetyState>,
318 inh: &'a Inherited<'a, 'tcx>,
320 ccx: &'a CrateCtxt<'a, 'tcx>,
323 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
324 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
325 let ty = self.node_ty(id);
326 self.resolve_type_vars_or_error(&ty)
328 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
329 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
330 self.resolve_type_vars_or_error(&ty)
332 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
333 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
334 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
336 fn node_method_ty(&self, method_call: ty::MethodCall)
337 -> Option<Ty<'tcx>> {
338 self.inh.method_map.borrow()
340 .map(|method| method.ty)
341 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
343 fn node_method_origin(&self, method_call: ty::MethodCall)
344 -> Option<ty::MethodOrigin<'tcx>>
346 self.inh.method_map.borrow()
348 .map(|method| method.origin.clone())
350 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
351 &self.inh.adjustments
353 fn is_method_call(&self, id: ast::NodeId) -> bool {
354 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
356 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
357 self.param_env().temporary_scope(rvalue_id)
359 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
360 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
364 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
365 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
369 fn closure_kind(&self,
371 -> Option<ty::ClosureKind>
373 self.inh.closure_kinds.borrow().get(&def_id).cloned()
376 fn closure_type(&self,
378 substs: &subst::Substs<'tcx>)
379 -> ty::ClosureTy<'tcx>
381 self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs)
384 fn closure_upvars(&self,
386 substs: &Substs<'tcx>)
387 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
389 ty::closure_upvars(self, def_id, substs)
393 impl<'a, 'tcx> Inherited<'a, 'tcx> {
394 fn new(tcx: &'a ty::ctxt<'tcx>,
395 param_env: ty::ParameterEnvironment<'a, 'tcx>)
396 -> Inherited<'a, 'tcx> {
398 infcx: infer::new_infer_ctxt(tcx),
399 locals: RefCell::new(NodeMap()),
400 param_env: param_env,
401 node_types: RefCell::new(NodeMap()),
402 item_substs: RefCell::new(NodeMap()),
403 adjustments: RefCell::new(NodeMap()),
404 method_map: RefCell::new(FnvHashMap()),
405 object_cast_map: RefCell::new(NodeMap()),
406 upvar_capture_map: RefCell::new(FnvHashMap()),
407 closure_tys: RefCell::new(DefIdMap()),
408 closure_kinds: RefCell::new(DefIdMap()),
409 fn_sig_map: RefCell::new(NodeMap()),
410 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
411 deferred_call_resolutions: RefCell::new(DefIdMap()),
412 deferred_cast_checks: RefCell::new(Vec::new()),
416 fn normalize_associated_types_in<T>(&self,
417 typer: &ty::ClosureTyper<'tcx>,
419 body_id: ast::NodeId,
422 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
424 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
425 assoc::normalize_associated_types_in(&self.infcx,
427 &mut *fulfillment_cx, span,
434 // Used by check_const and check_enum_variants
435 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
436 inh: &'a Inherited<'a, 'tcx>,
437 rty: ty::FnOutput<'tcx>,
438 body_id: ast::NodeId)
439 -> FnCtxt<'a, 'tcx> {
442 writeback_errors: Cell::new(false),
443 err_count_on_creation: ccx.tcx.sess.err_count(),
445 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
451 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
452 -> Inherited<'a, 'tcx> {
453 // It's kind of a kludge to manufacture a fake function context
454 // and statement context, but we might as well do write the code only once
455 let param_env = ty::empty_parameter_environment(ccx.tcx);
456 Inherited::new(ccx.tcx, param_env)
459 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
461 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
462 fn visit_item(&mut self, i: &'tcx ast::Item) {
463 check_item(self.ccx, i);
464 visit::walk_item(self, i);
467 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
469 ast::TyFixedLengthVec(_, ref expr) => {
470 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
475 visit::walk_ty(self, t);
479 pub fn check_item_types(ccx: &CrateCtxt) {
480 let krate = ccx.tcx.map.krate();
481 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
482 visit::walk_crate(&mut visit, krate);
484 // If types are not well-formed, it leads to all manner of errors
485 // downstream, so stop reporting errors at this point.
486 ccx.tcx.sess.abort_if_errors();
488 let mut visit = CheckItemTypesVisitor { ccx: ccx };
489 visit::walk_crate(&mut visit, krate);
491 ccx.tcx.sess.abort_if_errors();
493 for drop_method_did in ccx.tcx.destructors.borrow().iter() {
494 if drop_method_did.krate == ast::LOCAL_CRATE {
495 let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
496 match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
499 assert!(ccx.tcx.sess.has_errors());
505 ccx.tcx.sess.abort_if_errors();
508 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
509 decl: &'tcx ast::FnDecl,
510 body: &'tcx ast::Block,
514 param_env: ty::ParameterEnvironment<'a, 'tcx>)
517 ty::ty_bare_fn(_, ref fn_ty) => {
518 let inh = Inherited::new(ccx.tcx, param_env);
520 // Compute the fty from point of view of inside fn.
522 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
524 liberate_late_bound_regions(ccx.tcx,
525 region::DestructionScopeData::new(body.id),
528 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
530 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
531 decl, fn_id, body, &inh);
533 vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
534 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
535 vtable::select_all_fcx_obligations_or_error(&fcx);
537 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
538 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
540 _ => ccx.tcx.sess.impossible_case(body.span,
541 "check_bare_fn: function type expected")
545 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
546 fcx: &'a FnCtxt<'a, 'tcx>
549 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
550 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
553 // infer the variable's type
554 let var_ty = self.fcx.infcx().next_ty_var();
555 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
559 // take type that the user specified
560 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
567 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
568 // Add explicitly-declared locals.
569 fn visit_local(&mut self, local: &'tcx ast::Local) {
570 let o_ty = match local.ty {
571 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
574 self.assign(local.span, local.id, o_ty);
575 debug!("Local variable {} is assigned type {}",
576 self.fcx.pat_to_string(&*local.pat),
577 self.fcx.infcx().ty_to_string(
578 self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
579 visit::walk_local(self, local);
582 // Add pattern bindings.
583 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
584 if let ast::PatIdent(_, ref path1, _) = p.node {
585 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
586 let var_ty = self.assign(p.span, p.id, None);
588 self.fcx.require_type_is_sized(var_ty, p.span,
589 traits::VariableType(p.id));
591 debug!("Pattern binding {} is assigned to {} with type {}",
592 token::get_ident(path1.node),
593 self.fcx.infcx().ty_to_string(
594 self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
595 var_ty.repr(self.fcx.tcx()));
598 visit::walk_pat(self, p);
601 fn visit_block(&mut self, b: &'tcx ast::Block) {
602 // non-obvious: the `blk` variable maps to region lb, so
603 // we have to keep this up-to-date. This
604 // is... unfortunate. It'd be nice to not need this.
605 visit::walk_block(self, b);
608 // Since an expr occurs as part of the type fixed size arrays we
609 // need to record the type for that node
610 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
612 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
613 self.visit_ty(&**ty);
614 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
616 _ => visit::walk_ty(self, t)
620 // Don't descend into fns and items
621 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
622 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
623 fn visit_item(&mut self, _: &ast::Item) { }
627 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
628 /// body and returns the function context used for that purpose, since in the case of a fn item
629 /// there is still a bit more to do.
632 /// * inherited: other fields inherited from the enclosing fn (if any)
633 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
634 unsafety: ast::Unsafety,
635 unsafety_id: ast::NodeId,
636 fn_sig: &ty::FnSig<'tcx>,
637 decl: &'tcx ast::FnDecl,
639 body: &'tcx ast::Block,
640 inherited: &'a Inherited<'a, 'tcx>)
644 let err_count_on_creation = tcx.sess.err_count();
646 let arg_tys = &fn_sig.inputs;
647 let ret_ty = fn_sig.output;
649 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
654 // Create the function context. This is either derived from scratch or,
655 // in the case of function expressions, based on the outer context.
658 writeback_errors: Cell::new(false),
659 err_count_on_creation: err_count_on_creation,
661 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
666 // Remember return type so that regionck can access it later.
667 let mut fn_sig_tys: Vec<Ty> =
672 if let ty::FnConverging(ret_ty) = ret_ty {
673 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
674 fn_sig_tys.push(ret_ty);
677 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
679 fn_sig_tys.repr(tcx));
681 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
684 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
686 // Add formal parameters.
687 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
688 // Create type variables for each argument.
689 pat_util::pat_bindings(
692 |_bm, pat_id, sp, _path| {
693 let var_ty = visit.assign(sp, pat_id, None);
694 fcx.require_type_is_sized(var_ty, sp,
695 traits::VariableType(pat_id));
698 // Check the pattern.
701 map: pat_id_map(&tcx.def_map, &*input.pat),
703 _match::check_pat(&pcx, &*input.pat, *arg_ty);
706 visit.visit_block(body);
709 check_block_with_expected(&fcx, body, match ret_ty {
710 ty::FnConverging(result_type) => ExpectHasType(result_type),
711 ty::FnDiverging => NoExpectation
714 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
715 fcx.write_ty(input.id, *arg);
721 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
724 check_representable(tcx, span, id, "struct");
725 check_instantiable(tcx, span, id);
727 if ty::lookup_simd(tcx, local_def(id)) {
728 check_simd(tcx, span, id);
732 pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
733 debug!("check_item(it.id={}, it.ident={})",
735 ty::item_path_str(ccx.tcx, local_def(it.id)));
736 let _indenter = indenter();
739 ast::ItemStatic(_, _, ref e) |
740 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
741 ast::ItemEnum(ref enum_definition, _) => {
742 check_enum_variants(ccx,
744 &enum_definition.variants,
747 ast::ItemFn(ref decl, _, _, _, ref body) => {
748 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
749 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
750 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
752 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
753 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
755 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
757 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
758 Some(impl_trait_ref) => {
759 check_impl_items_against_trait(ccx,
767 for impl_item in impl_items {
768 match impl_item.node {
769 ast::MethodImplItem(ref sig, ref body) => {
770 check_method_body(ccx, &impl_pty.generics, sig, body,
771 impl_item.id, impl_item.span);
773 ast::TypeImplItem(_) |
774 ast::MacImplItem(_) => {
775 // Nothing to do here.
781 ast::ItemTrait(_, ref generics, _, ref trait_items) => {
782 check_trait_on_unimplemented(ccx, generics, it);
783 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
784 for trait_item in trait_items {
785 match trait_item.node {
786 ast::MethodTraitItem(_, None) => {
787 // Nothing to do, since required methods don't have
790 ast::MethodTraitItem(ref sig, Some(ref body)) => {
791 check_method_body(ccx, &trait_def.generics, sig, body,
792 trait_item.id, trait_item.span);
794 ast::TypeTraitItem(..) => {
800 ast::ItemStruct(..) => {
801 check_struct(ccx, it.id, it.span);
803 ast::ItemTy(ref t, ref generics) => {
804 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
805 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
807 ast::ItemForeignMod(ref m) => {
808 if m.abi == abi::RustIntrinsic {
809 for item in &m.items {
810 check_intrinsic_type(ccx, &**item);
813 for item in &m.items {
814 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
815 if !pty.generics.types.is_empty() {
816 span_err!(ccx.tcx.sess, item.span, E0044,
817 "foreign items may not have type parameters");
820 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
821 if fn_decl.variadic && m.abi != abi::C {
822 span_err!(ccx.tcx.sess, item.span, E0045,
823 "variadic function must have C calling convention");
829 _ => {/* nothing to do */ }
833 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
834 generics: &ast::Generics,
836 if let Some(ref attr) = item.attrs.iter().find(|a| {
837 a.check_name("rustc_on_unimplemented")
839 if let Some(ref istring) = attr.value_str() {
840 let parser = Parser::new(&istring);
841 let types = &*generics.ty_params;
842 for token in parser {
844 Piece::String(_) => (), // Normal string, no need to check it
845 Piece::NextArgument(a) => match a.position {
846 // `{Self}` is allowed
847 Position::ArgumentNamed(s) if s == "Self" => (),
848 // So is `{A}` if A is a type parameter
849 Position::ArgumentNamed(s) => match types.iter().find(|t| {
850 t.ident.as_str() == s
854 span_err!(ccx.tcx.sess, attr.span, E0230,
855 "there is no type parameter \
857 s, item.ident.as_str());
860 // `{:1}` and `{}` are not to be used
861 Position::ArgumentIs(_) | Position::ArgumentNext => {
862 span_err!(ccx.tcx.sess, attr.span, E0231,
863 "only named substitution \
864 parameters are allowed");
870 span_err!(ccx.tcx.sess, attr.span, E0232,
871 "this attribute must have a value, \
872 eg `#[rustc_on_unimplemented = \"foo\"]`")
877 /// Type checks a method body.
881 /// * `item_generics`: generics defined on the impl/trait that contains
883 /// * `self_bound`: bound for the `Self` type parameter, if any
884 /// * `method`: the method definition
885 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
886 item_generics: &ty::Generics<'tcx>,
887 sig: &'tcx ast::MethodSig,
888 body: &'tcx ast::Block,
889 id: ast::NodeId, span: Span) {
890 debug!("check_method_body(item_generics={}, id={})",
891 item_generics.repr(ccx.tcx), id);
892 let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
894 let fty = ty::node_id_to_type(ccx.tcx, id);
895 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
897 check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
900 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
902 impl_trait_ref: &ty::TraitRef<'tcx>,
903 impl_items: &[P<ast::ImplItem>]) {
904 // Locate trait methods
906 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
908 // Check existing impl methods to see if they are both present in trait
909 // and compatible with trait signature
910 for impl_item in impl_items {
911 match impl_item.node {
912 ast::MethodImplItem(_, ref body) => {
913 let impl_method_def_id = local_def(impl_item.id);
914 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
917 // If this is an impl of a trait method, find the
918 // corresponding method definition in the trait.
919 let opt_trait_method_ty =
921 .find(|ti| ti.name() == impl_item_ty.name());
922 match opt_trait_method_ty {
923 Some(trait_method_ty) => {
924 match (trait_method_ty, &impl_item_ty) {
925 (&ty::MethodTraitItem(ref trait_method_ty),
926 &ty::MethodTraitItem(ref impl_method_ty)) => {
927 compare_impl_method(ccx.tcx,
935 // This is span_bug as it should have already been
936 // caught in resolve.
939 &format!("item `{}` is of a different kind from its trait `{}`",
940 token::get_name(impl_item_ty.name()),
941 impl_trait_ref.repr(tcx)));
946 // This is span_bug as it should have already been
947 // caught in resolve.
950 &format!("method `{}` is not a member of trait `{}`",
951 token::get_name(impl_item_ty.name()),
952 impl_trait_ref.repr(tcx)));
956 ast::TypeImplItem(_) => {
957 let typedef_def_id = local_def(impl_item.id);
958 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
961 // If this is an impl of an associated type, find the
962 // corresponding type definition in the trait.
963 let opt_associated_type =
965 .find(|ti| ti.name() == typedef_ty.name());
966 match opt_associated_type {
967 Some(associated_type) => {
968 match (associated_type, &typedef_ty) {
969 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
971 // This is `span_bug` as it should have
972 // already been caught in resolve.
975 &format!("item `{}` is of a different kind from its trait `{}`",
976 token::get_name(typedef_ty.name()),
977 impl_trait_ref.repr(tcx)));
982 // This is `span_bug` as it should have already been
983 // caught in resolve.
987 "associated type `{}` is not a member of \
989 token::get_name(typedef_ty.name()),
990 impl_trait_ref.repr(tcx)));
994 ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span,
999 // Check for missing items from trait
1000 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
1001 let mut missing_methods = Vec::new();
1002 for trait_item in &*trait_items {
1004 ty::MethodTraitItem(ref trait_method) => {
1005 let is_implemented =
1006 impl_items.iter().any(|ii| {
1008 ast::MethodImplItem(..) => {
1009 ii.ident.name == trait_method.name
1011 ast::TypeImplItem(_) |
1012 ast::MacImplItem(_) => false,
1016 provided_methods.iter().any(|m| m.name == trait_method.name);
1017 if !is_implemented && !is_provided {
1018 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
1021 ty::TypeTraitItem(ref associated_type) => {
1022 let is_implemented = impl_items.iter().any(|ii| {
1024 ast::TypeImplItem(_) => {
1025 ii.ident.name == associated_type.name
1027 ast::MethodImplItem(..) |
1028 ast::MacImplItem(_) => false,
1031 if !is_implemented {
1032 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1038 if !missing_methods.is_empty() {
1039 span_err!(tcx.sess, impl_span, E0046,
1040 "not all trait items implemented, missing: {}",
1041 missing_methods.connect(", "));
1045 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1052 let tstr = fcx.infcx().ty_to_string(t_1);
1053 fcx.type_error_message(span, |actual| {
1054 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1057 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1058 let mtstr = match mt {
1059 ast::MutMutable => "mut ",
1060 ast::MutImmutable => ""
1062 if ty::type_is_trait(t_1) {
1063 span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
1065 span_help!(fcx.tcx().sess, span,
1066 "consider using an implicit coercion to `&{}{}` instead",
1070 ty::ty_uniq(..) => {
1071 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
1074 span_help!(fcx.tcx().sess, e_span,
1075 "consider using a box or reference as appropriate");
1078 fcx.write_error(id);
1082 fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
1083 fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1087 fcx.type_error_message(span, |actual| {
1088 format!("illegal cast; cast through an \
1089 integer first: `{}` as `{}`",
1091 fcx.infcx().ty_to_string(t_1))
1095 let span = cast.span;
1097 let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
1098 let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
1100 // Check for trivial casts.
1101 if !ty::type_has_ty_infer(t_1) {
1102 if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
1103 if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
1104 fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
1107 format!("trivial numeric 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)));
1113 fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
1116 format!("trivial cast: `{}` as `{}`. Cast can be \
1117 replaced by coercion, this might require type \
1118 ascription or a temporary variable",
1119 fcx.infcx().ty_to_string(t_e),
1120 fcx.infcx().ty_to_string(t_1)));
1126 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1127 let t_e_is_scalar = ty::type_is_scalar(t_e);
1128 let t_e_is_integral = ty::type_is_integral(t_e);
1129 let t_e_is_float = ty::type_is_floating_point(t_e);
1130 let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
1132 let t_1_is_scalar = ty::type_is_scalar(t_1);
1133 let t_1_is_char = ty::type_is_char(t_1);
1134 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1135 let t_1_is_float = ty::type_is_floating_point(t_1);
1137 // casts to scalars other than `char` and `bare fn` are trivial
1138 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1140 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1141 demand::coerce(fcx, e.span, t_1, &e);
1142 } else if t_1_is_char {
1143 let t_e = fcx.infcx().shallow_resolve(t_e);
1144 if t_e.sty != ty::ty_uint(ast::TyU8) {
1145 fcx.type_error_message(span, |actual| {
1146 format!("only `u8` can be cast as `char`, not `{}`", actual)
1149 } else if t_1.sty == ty::ty_bool {
1150 span_err!(fcx.tcx().sess, span, E0054,
1151 "cannot cast as `bool`, compare with zero instead");
1152 } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
1153 t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
1154 // Casts to float must go through an integer or boolean
1155 cast_through_integer_err(fcx, span, t_1, t_e)
1156 } else if t_e_is_c_enum && t_1_is_trivial {
1157 if ty::type_is_unsafe_ptr(t_1) {
1158 // ... and likewise with C enum -> *T
1159 cast_through_integer_err(fcx, span, t_1, t_e)
1161 // casts from C-like enums are allowed
1162 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1163 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1164 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1166 ty::ty_vec(_, Some(_)) => {}
1169 if ty::type_needs_infer(t2) {
1170 // This prevents this special case from going off when casting
1171 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1176 let el = ty::sequence_element_type(fcx.tcx(), t1);
1177 infer::mk_eqty(fcx.infcx(),
1184 // Due to the limitations of LLVM global constants,
1185 // region pointers end up pointing at copies of
1186 // vector elements instead of the original values.
1187 // To allow unsafe pointers to work correctly, we
1188 // need to special-case obtaining an unsafe pointer
1189 // from a region pointer to a vector.
1191 /* this cast is only allowed from &[T, ..n] to *T or
1193 match (&t_e.sty, &t_1.sty) {
1194 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1195 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1196 if types_compatible(fcx, e.span, mt1, mt2) => {
1197 /* this case is allowed */
1200 demand::coerce(fcx, e.span, t_1, &e);
1203 } else if !(t_e_is_scalar && t_1_is_trivial) {
1205 If more type combinations should be supported than are
1206 supported here, then file an enhancement issue and
1207 record the issue number in this comment.
1209 fcx.type_error_message(span, |actual| {
1210 format!("non-scalar cast: `{}` as `{}`",
1212 fcx.infcx().ty_to_string(t_1))
1217 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1218 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1220 fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
1221 -> Result<ty::TypeScheme<'tcx>, ErrorReported>
1223 Ok(ty::lookup_item_type(self.tcx(), id))
1226 fn get_trait_def(&self, _: Span, id: ast::DefId)
1227 -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
1229 Ok(ty::lookup_trait_def(self.tcx(), id))
1232 fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
1233 // all super predicates are ensured during collect pass
1237 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1238 Some(&self.inh.param_env.free_substs)
1241 fn get_type_parameter_bounds(&self,
1243 node_id: ast::NodeId)
1244 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
1246 let def = self.tcx().type_parameter_def(node_id);
1247 let r = self.inh.param_env.caller_bounds
1249 .filter_map(|predicate| {
1251 ty::Predicate::Trait(ref data) => {
1252 if data.0.self_ty().is_param(def.space, def.index) {
1253 Some(data.to_poly_trait_ref())
1267 fn trait_defines_associated_type_named(&self,
1268 trait_def_id: ast::DefId,
1269 assoc_name: ast::Name)
1272 let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
1273 trait_def.associated_type_names.contains(&assoc_name)
1276 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1277 self.infcx().next_ty_var()
1280 fn projected_ty_from_poly_trait_ref(&self,
1282 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1283 item_name: ast::Name)
1286 let (trait_ref, _) =
1287 self.infcx().replace_late_bound_regions_with_fresh_var(
1289 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1292 self.normalize_associated_type(span, trait_ref, item_name)
1295 fn projected_ty(&self,
1297 trait_ref: Rc<ty::TraitRef<'tcx>>,
1298 item_name: ast::Name)
1301 self.normalize_associated_type(span, trait_ref, item_name)
1305 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1306 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1308 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1312 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1316 pub fn sess(&self) -> &Session {
1320 pub fn err_count_since_creation(&self) -> uint {
1321 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1324 /// Resolves type variables in `ty` if possible. Unlike the infcx
1325 /// version, this version will also select obligations if it seems
1326 /// useful, in an effort to get more type information.
1327 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1328 // No ty::infer()? Nothing needs doing.
1329 if !ty::type_has_ty_infer(ty) {
1333 // If `ty` is a type variable, see whether we already know what it is.
1334 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1335 if !ty::type_has_ty_infer(ty) {
1339 // If not, try resolving any new fcx obligations that have cropped up.
1340 vtable::select_new_fcx_obligations(self);
1341 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1342 if !ty::type_has_ty_infer(ty) {
1346 // If not, try resolving *all* pending obligations as much as
1347 // possible. This can help substantially when there are
1348 // indirect dependencies that don't seem worth tracking
1350 vtable::select_fcx_obligations_where_possible(self);
1351 self.infcx().resolve_type_vars_if_possible(&ty)
1354 /// Resolves all type variables in `t` and then, if any were left
1355 /// unresolved, substitutes an error type. This is used after the
1356 /// main checking when doing a second pass before writeback. The
1357 /// justification is that writeback will produce an error for
1358 /// these unconstrained type variables.
1359 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1360 let t = self.infcx().resolve_type_vars_if_possible(t);
1361 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1364 fn record_deferred_call_resolution(&self,
1365 closure_def_id: ast::DefId,
1366 r: DeferredCallResolutionHandler<'tcx>) {
1367 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1368 deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
1371 fn remove_deferred_call_resolutions(&self,
1372 closure_def_id: ast::DefId)
1373 -> Vec<DeferredCallResolutionHandler<'tcx>>
1375 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1376 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1379 pub fn tag(&self) -> String {
1380 let self_ptr: *const FnCtxt = self;
1381 format!("{:?}", self_ptr)
1384 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1385 match self.inh.locals.borrow().get(&nid) {
1388 self.tcx().sess.span_err(
1390 &format!("no type for local variable {}", nid));
1391 self.tcx().types.err
1396 /// Apply "fallbacks" to some types
1397 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1398 pub fn default_type_parameters(&self) {
1399 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1400 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1401 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1402 if self.infcx().type_var_diverges(resolved) {
1403 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1405 match self.infcx().type_is_unconstrained_numeric(resolved) {
1406 UnconstrainedInt => {
1407 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1409 UnconstrainedFloat => {
1410 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1419 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1420 debug!("write_ty({}, {}) in fcx {}",
1421 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1422 self.inh.node_types.borrow_mut().insert(node_id, ty);
1425 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1426 if !substs.substs.is_noop() {
1427 debug!("write_substs({}, {}) in fcx {}",
1429 substs.repr(self.tcx()),
1432 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1436 pub fn write_autoderef_adjustment(&self,
1437 node_id: ast::NodeId,
1440 if derefs == 0 { return; }
1441 self.write_adjustment(
1444 ty::AdjustDerefRef(ty::AutoDerefRef {
1450 pub fn write_adjustment(&self,
1451 node_id: ast::NodeId,
1453 adj: ty::AutoAdjustment<'tcx>) {
1454 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1456 if adj.is_identity() {
1460 // Careful: adjustments can imply trait obligations if we are
1461 // casting from a concrete type to an object type. I think
1462 // it'd probably be nicer to move the logic that creates the
1463 // obligation into the code that creates the adjustment, but
1464 // that's a bit awkward, so instead we go digging and pull the
1465 // obligation out here.
1466 self.register_adjustment_obligations(span, &adj);
1467 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1470 /// Basically whenever we are converting from a type scheme into
1471 /// the fn body space, we always want to normalize associated
1472 /// types as well. This function combines the two.
1473 fn instantiate_type_scheme<T>(&self,
1475 substs: &Substs<'tcx>,
1478 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1480 let value = value.subst(self.tcx(), substs);
1481 let result = self.normalize_associated_types_in(span, &value);
1482 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1483 value.repr(self.tcx()),
1484 substs.repr(self.tcx()),
1485 result.repr(self.tcx()));
1489 /// As `instantiate_type_scheme`, but for the bounds found in a
1490 /// generic type scheme.
1491 fn instantiate_bounds(&self,
1493 substs: &Substs<'tcx>,
1494 bounds: &ty::GenericPredicates<'tcx>)
1495 -> ty::InstantiatedPredicates<'tcx>
1497 ty::InstantiatedPredicates {
1498 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1503 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1504 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1506 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1509 fn normalize_associated_type(&self,
1511 trait_ref: Rc<ty::TraitRef<'tcx>>,
1512 item_name: ast::Name)
1515 let cause = traits::ObligationCause::new(span,
1517 traits::ObligationCauseCode::MiscObligation);
1518 self.inh.fulfillment_cx
1520 .normalize_projection_type(self.infcx(),
1523 trait_ref: trait_ref,
1524 item_name: item_name,
1529 fn register_adjustment_obligations(&self,
1531 adj: &ty::AutoAdjustment<'tcx>) {
1533 ty::AdjustReifyFnPointer(..) => { }
1534 ty::AdjustUnsafeFnPointer => { }
1535 ty::AdjustDerefRef(ref d_r) => {
1538 self.register_autoref_obligations(span, a_r);
1546 fn register_autoref_obligations(&self,
1548 autoref: &ty::AutoRef<'tcx>) {
1550 ty::AutoUnsize(ref unsize) => {
1551 self.register_unsize_obligations(span, unsize);
1553 ty::AutoPtr(_, _, None) |
1554 ty::AutoUnsafe(_, None) => {
1556 ty::AutoPtr(_, _, Some(ref a_r)) |
1557 ty::AutoUnsafe(_, Some(ref a_r)) => {
1558 self.register_autoref_obligations(span, &**a_r)
1560 ty::AutoUnsizeUniq(ref unsize) => {
1561 self.register_unsize_obligations(span, unsize);
1566 fn register_unsize_obligations(&self,
1568 unsize: &ty::UnsizeKind<'tcx>) {
1569 debug!("register_unsize_obligations: unsize={:?}", unsize);
1572 ty::UnsizeLength(..) => {}
1573 ty::UnsizeStruct(ref u, _) => {
1574 self.register_unsize_obligations(span, &**u)
1576 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1577 vtable::check_object_safety(self.tcx(), ty_trait, span);
1579 // If the type is `Foo+'a`, ensures that the type
1580 // being cast to `Foo+'a` implements `Foo`:
1581 vtable::register_object_cast_obligations(self,
1586 // If the type is `Foo+'a`, ensures that the type
1587 // being cast to `Foo+'a` outlives `'a`:
1588 let cause = traits::ObligationCause { span: span,
1589 body_id: self.body_id,
1590 code: traits::ObjectCastObligation(self_ty) };
1591 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1593 ty::UnsizeUpcast(_) => { }
1597 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1598 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1599 /// Registers any trait obligations specified on `def_id` at the same time.
1601 /// Note that function is only intended to be used with types (notably, not fns). This is
1602 /// because it doesn't do any instantiation of late-bound regions.
1603 pub fn instantiate_type(&self,
1606 -> TypeAndSubsts<'tcx>
1609 ty::lookup_item_type(self.tcx(), def_id);
1610 let type_predicates =
1611 ty::lookup_predicates(self.tcx(), def_id);
1613 self.infcx().fresh_substs_for_generics(
1615 &type_scheme.generics);
1617 self.instantiate_bounds(span, &substs, &type_predicates);
1618 self.add_obligations_for_parameters(
1619 traits::ObligationCause::new(
1622 traits::ItemObligation(def_id)),
1625 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1633 /// Returns the type that this AST path refers to. If the path has no type
1634 /// parameters and the corresponding type has type parameters, fresh type
1635 /// and/or region variables are substituted.
1637 /// This is used when checking the constructor in struct literals.
1638 fn instantiate_struct_literal_ty(&self,
1641 -> TypeAndSubsts<'tcx>
1643 let tcx = self.tcx();
1645 let ty::TypeScheme { generics, ty: decl_ty } =
1646 ty::lookup_item_type(tcx, did);
1648 let substs = astconv::ast_path_substs_for_ty(self, self,
1650 PathParamMode::Optional,
1652 path.segments.last().unwrap());
1654 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1656 TypeAndSubsts { substs: substs, ty: ty }
1659 pub fn write_nil(&self, node_id: ast::NodeId) {
1660 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1662 pub fn write_error(&self, node_id: ast::NodeId) {
1663 self.write_ty(node_id, self.tcx().types.err);
1666 pub fn require_type_meets(&self,
1669 code: traits::ObligationCauseCode<'tcx>,
1670 bound: ty::BuiltinBound)
1672 self.register_builtin_bound(
1675 traits::ObligationCause::new(span, self.body_id, code));
1678 pub fn require_type_is_sized(&self,
1681 code: traits::ObligationCauseCode<'tcx>)
1683 self.require_type_meets(ty, span, code, ty::BoundSized);
1686 pub fn require_expr_have_sized_type(&self,
1688 code: traits::ObligationCauseCode<'tcx>)
1690 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1693 pub fn type_is_known_to_be_sized(&self,
1698 traits::type_known_to_meet_builtin_bound(self.infcx(),
1705 pub fn register_builtin_bound(&self,
1707 builtin_bound: ty::BuiltinBound,
1708 cause: traits::ObligationCause<'tcx>)
1710 self.inh.fulfillment_cx.borrow_mut()
1711 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1714 pub fn register_predicate(&self,
1715 obligation: traits::PredicateObligation<'tcx>)
1717 debug!("register_predicate({})",
1718 obligation.repr(self.tcx()));
1719 self.inh.fulfillment_cx
1721 .register_predicate_obligation(self.infcx(), obligation);
1724 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1725 let t = ast_ty_to_ty(self, self, ast_t);
1727 let mut bounds_checker = wf::BoundsChecker::new(self,
1731 bounds_checker.check_ty(t);
1736 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1737 pat.repr(self.tcx())
1740 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1741 match self.inh.node_types.borrow().get(&ex.id) {
1744 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1750 /// Apply `adjustment` to the type of `expr`
1751 pub fn adjust_expr_ty(&self,
1753 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1756 let raw_ty = self.expr_ty(expr);
1757 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1758 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1759 ty::adjust_ty(self.tcx(),
1764 |method_call| self.inh.method_map.borrow()
1766 .map(|method| resolve_ty(method.ty)))
1769 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1770 match self.inh.node_types.borrow().get(&id) {
1772 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1774 self.tcx().sess.bug(
1775 &format!("no type for node {}: {} in fcx {}",
1776 id, self.tcx().map.node_to_string(id),
1782 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1783 self.inh.item_substs.borrow()
1786 pub fn opt_node_ty_substs<F>(&self,
1789 F: FnOnce(&ty::ItemSubsts<'tcx>),
1791 match self.inh.item_substs.borrow().get(&id) {
1797 pub fn mk_subty(&self,
1798 a_is_expected: bool,
1799 origin: infer::TypeOrigin,
1802 -> Result<(), ty::type_err<'tcx>> {
1803 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1806 pub fn mk_eqty(&self,
1807 a_is_expected: bool,
1808 origin: infer::TypeOrigin,
1811 -> Result<(), ty::type_err<'tcx>> {
1812 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1815 pub fn mk_subr(&self,
1816 origin: infer::SubregionOrigin<'tcx>,
1819 infer::mk_subr(self.infcx(), origin, sub, sup)
1822 pub fn type_error_message<M>(&self,
1825 actual_ty: Ty<'tcx>,
1826 err: Option<&ty::type_err<'tcx>>) where
1827 M: FnOnce(String) -> String,
1829 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1832 pub fn report_mismatched_types(&self,
1836 err: &ty::type_err<'tcx>) {
1837 self.infcx().report_mismatched_types(sp, e, a, err)
1840 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1841 /// outlive the region `r`.
1842 pub fn register_region_obligation(&self,
1845 cause: traits::ObligationCause<'tcx>)
1847 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1848 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1851 pub fn add_default_region_param_bounds(&self,
1852 substs: &Substs<'tcx>,
1855 for &ty in substs.types.iter() {
1856 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1857 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1858 traits::MiscObligation);
1859 self.register_region_obligation(ty, default_bound, cause);
1863 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1864 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1865 /// trait/region obligations.
1867 /// For example, if there is a function:
1870 /// fn foo<'a,T:'a>(...)
1873 /// and a reference:
1879 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1880 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1881 pub fn add_obligations_for_parameters(&self,
1882 cause: traits::ObligationCause<'tcx>,
1883 predicates: &ty::InstantiatedPredicates<'tcx>)
1885 assert!(!predicates.has_escaping_regions());
1887 debug!("add_obligations_for_parameters(predicates={})",
1888 predicates.repr(self.tcx()));
1890 let obligations = traits::predicates_for_generics(self.tcx(),
1894 obligations.map_move(|o| self.register_predicate(o));
1897 // Only for fields! Returns <none> for methods>
1898 // Indifferent to privacy flags
1899 pub fn lookup_field_ty(&self,
1901 class_id: ast::DefId,
1902 items: &[ty::field_ty],
1903 fieldname: ast::Name,
1904 substs: &subst::Substs<'tcx>)
1907 let o_field = items.iter().find(|f| f.name == fieldname);
1908 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1909 .map(|t| self.normalize_associated_types_in(span, &t))
1912 pub fn lookup_tup_field_ty(&self,
1914 class_id: ast::DefId,
1915 items: &[ty::field_ty],
1917 substs: &subst::Substs<'tcx>)
1920 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1921 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1922 .map(|t| self.normalize_associated_types_in(span, &t))
1925 fn check_casts(&self) {
1926 let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
1927 for check in deferred_cast_checks.iter() {
1928 check_cast(self, check);
1931 deferred_cast_checks.clear();
1935 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1936 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1937 // RFC #599 specifies that object lifetime defaults take
1938 // precedence over other defaults. But within a fn body we
1939 // don't have a *default* region, rather we use inference to
1940 // find the *correct* region, which is strictly more general
1941 // (and anyway, within a fn body the right region may not even
1942 // be something the user can write explicitly, since it might
1943 // be some expression).
1944 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1947 fn anon_regions(&self, span: Span, count: uint)
1948 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1949 Ok((0..count).map(|_| {
1950 self.infcx().next_region_var(infer::MiscVariable(span))
1955 #[derive(Copy, Debug, PartialEq, Eq)]
1956 pub enum LvaluePreference {
1961 /// Whether `autoderef` requires types to resolve.
1962 #[derive(Copy, Debug, PartialEq, Eq)]
1963 pub enum UnresolvedTypeAction {
1964 /// Produce an error and return `ty_err` whenever a type cannot
1965 /// be resolved (i.e. it is `ty_infer`).
1967 /// Go on without emitting any errors, and return the unresolved
1968 /// type. Useful for probing, e.g. in coercions.
1972 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1973 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1975 /// Note: this method does not modify the adjustments table. The caller is responsible for
1976 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1977 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1980 opt_expr: Option<&ast::Expr>,
1981 unresolved_type_action: UnresolvedTypeAction,
1982 mut lvalue_pref: LvaluePreference,
1984 -> (Ty<'tcx>, uint, Option<T>)
1985 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1987 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1988 base_ty.repr(fcx.tcx()),
1989 opt_expr.repr(fcx.tcx()),
1992 let mut t = base_ty;
1993 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1994 let resolved_t = match unresolved_type_action {
1995 UnresolvedTypeAction::Error => {
1996 let resolved_t = structurally_resolved_type(fcx, sp, t);
1997 if ty::type_is_error(resolved_t) {
1998 return (resolved_t, autoderefs, None);
2002 UnresolvedTypeAction::Ignore => {
2003 // We can continue even when the type cannot be resolved
2004 // (i.e. it is an inference variable) because `ty::deref`
2005 // and `try_overloaded_deref` both simply return `None`
2006 // in such a case without producing spurious errors.
2007 fcx.resolve_type_vars_if_possible(t)
2011 match should_stop(resolved_t, autoderefs) {
2012 Some(x) => return (resolved_t, autoderefs, Some(x)),
2016 // Otherwise, deref if type is derefable:
2017 let mt = match ty::deref(resolved_t, false) {
2018 Some(mt) => Some(mt),
2020 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
2022 // Super subtle: it might seem as though we should
2023 // pass `opt_expr` to `try_overloaded_deref`, so that
2024 // the (implicit) autoref of using an overloaded deref
2025 // would get added to the adjustment table. However we
2026 // do not do that, because it's kind of a
2027 // "meta-adjustment" -- instead, we just leave it
2028 // unrecorded and know that there "will be" an
2029 // autoref. regionck and other bits of the code base,
2030 // when they encounter an overloaded autoderef, have
2031 // to do some reconstructive surgery. This is a pretty
2032 // complex mess that is begging for a proper MIR.
2033 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2039 if mt.mutbl == ast::MutImmutable {
2040 lvalue_pref = NoPreference;
2043 None => return (resolved_t, autoderefs, None)
2047 // We've reached the recursion limit, error gracefully.
2048 span_err!(fcx.tcx().sess, sp, E0055,
2049 "reached the recursion limit while auto-dereferencing {}",
2050 base_ty.repr(fcx.tcx()));
2051 (fcx.tcx().types.err, 0, None)
2054 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2056 method_call: Option<MethodCall>,
2057 base_expr: Option<&ast::Expr>,
2059 lvalue_pref: LvaluePreference)
2060 -> Option<ty::mt<'tcx>>
2062 // Try DerefMut first, if preferred.
2063 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2064 (PreferMutLvalue, Some(trait_did)) => {
2065 method::lookup_in_trait(fcx, span, base_expr,
2066 token::intern("deref_mut"), trait_did,
2072 // Otherwise, fall back to Deref.
2073 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2074 (None, Some(trait_did)) => {
2075 method::lookup_in_trait(fcx, span, base_expr,
2076 token::intern("deref"), trait_did,
2079 (method, _) => method
2082 make_overloaded_lvalue_return_type(fcx, method_call, method)
2085 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2086 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2087 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2088 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2089 method_call: Option<MethodCall>,
2090 method: Option<MethodCallee<'tcx>>)
2091 -> Option<ty::mt<'tcx>>
2095 let ref_ty = // invoked methods have all LB regions instantiated
2096 ty::no_late_bound_regions(
2097 fcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
2099 Some(method_call) => {
2100 fcx.inh.method_map.borrow_mut().insert(method_call,
2106 ty::FnConverging(ref_ty) => {
2107 ty::deref(ref_ty, true)
2109 ty::FnDiverging => {
2110 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2118 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2119 base_expr: &ast::Expr,
2121 lvalue_pref: LvaluePreference,
2124 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2126 // FIXME(#18741) -- this is almost but not quite the same as the
2127 // autoderef that normal method probing does. They could likely be
2130 let (ty, autoderefs, final_mt) = autoderef(fcx,
2134 UnresolvedTypeAction::Error,
2137 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2138 step(adj_ty, autoderefref)
2141 if final_mt.is_some() {
2145 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2146 // do a final unsized coercion to yield [T].
2148 ty::ty_vec(element_ty, Some(n)) => {
2149 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2150 let autoderefref = ty::AutoDerefRef {
2151 autoderefs: autoderefs,
2152 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2154 step(adjusted_ty, autoderefref)
2162 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2163 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2164 /// This loop implements one step in that search; the autoderef loop is implemented by
2165 /// `autoderef_for_index`.
2166 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2167 method_call: MethodCall,
2169 base_expr: &'tcx ast::Expr,
2170 adjusted_ty: Ty<'tcx>,
2171 adjustment: ty::AutoDerefRef<'tcx>,
2172 lvalue_pref: LvaluePreference,
2174 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2176 let tcx = fcx.tcx();
2177 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2179 base_expr.repr(tcx),
2180 adjusted_ty.repr(tcx),
2182 index_ty.repr(tcx));
2184 let input_ty = fcx.infcx().next_ty_var();
2186 // First, try built-in indexing.
2187 match (ty::index(adjusted_ty), &index_ty.sty) {
2188 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2189 debug!("try_index_step: success, using built-in indexing");
2190 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2191 return Some((tcx.types.uint, ty));
2196 // Try `IndexMut` first, if preferred.
2197 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2198 (PreferMutLvalue, Some(trait_did)) => {
2199 method::lookup_in_trait_adjusted(fcx,
2202 token::intern("index_mut"),
2206 Some(vec![input_ty]))
2211 // Otherwise, fall back to `Index`.
2212 let method = match (method, tcx.lang_items.index_trait()) {
2213 (None, Some(trait_did)) => {
2214 method::lookup_in_trait_adjusted(fcx,
2217 token::intern("index"),
2221 Some(vec![input_ty]))
2223 (method, _) => method,
2226 // If some lookup succeeds, write callee into table and extract index/element
2227 // type from the method signature.
2228 // If some lookup succeeded, install method in table
2229 method.and_then(|method| {
2230 debug!("try_index_step: success, using overloaded indexing");
2231 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2232 map(|ret| (input_ty, ret.ty))
2236 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2238 method_fn_ty: Ty<'tcx>,
2239 callee_expr: &'tcx ast::Expr,
2240 args_no_rcvr: &'tcx [P<ast::Expr>],
2241 autoref_args: AutorefArgs,
2242 tuple_arguments: TupleArgumentsFlag,
2243 expected: Expectation<'tcx>)
2244 -> ty::FnOutput<'tcx> {
2245 if ty::type_is_error(method_fn_ty) {
2246 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2248 let err_inputs = match tuple_arguments {
2249 DontTupleArguments => err_inputs,
2250 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2253 check_argument_types(fcx,
2261 ty::FnConverging(fcx.tcx().types.err)
2263 match method_fn_ty.sty {
2264 ty::ty_bare_fn(_, ref fty) => {
2265 // HACK(eddyb) ignore self in the definition (see above).
2266 let expected_arg_tys = expected_types_for_fn_args(fcx,
2270 &fty.sig.0.inputs[1..]);
2271 check_argument_types(fcx,
2273 &fty.sig.0.inputs[1..],
2274 &expected_arg_tys[..],
2282 fcx.tcx().sess.span_bug(callee_expr.span,
2283 "method without bare fn type");
2289 /// Generic function that factors out common logic from function calls, method calls and overloaded
2291 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2293 fn_inputs: &[Ty<'tcx>],
2294 expected_arg_tys: &[Ty<'tcx>],
2295 args: &'tcx [P<ast::Expr>],
2296 autoref_args: AutorefArgs,
2298 tuple_arguments: TupleArgumentsFlag) {
2299 let tcx = fcx.ccx.tcx;
2301 // Grab the argument types, supplying fresh type variables
2302 // if the wrong number of arguments were supplied
2303 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2309 let mut expected_arg_tys = expected_arg_tys;
2310 let expected_arg_count = fn_inputs.len();
2311 let formal_tys = if tuple_arguments == TupleArguments {
2312 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2313 match tuple_type.sty {
2314 ty::ty_tup(ref arg_types) => {
2315 if arg_types.len() != args.len() {
2316 span_err!(tcx.sess, sp, E0057,
2317 "this function takes {} parameter{} but {} parameter{} supplied",
2319 if arg_types.len() == 1 {""} else {"s"},
2321 if args.len() == 1 {" was"} else {"s were"});
2322 expected_arg_tys = &[];
2323 err_args(fcx.tcx(), args.len())
2325 expected_arg_tys = match expected_arg_tys.get(0) {
2326 Some(&ty) => match ty.sty {
2327 ty::ty_tup(ref tys) => &**tys,
2332 (*arg_types).clone()
2336 span_err!(tcx.sess, sp, E0059,
2337 "cannot use call notation; the first type parameter \
2338 for the function trait is neither a tuple nor unit");
2339 expected_arg_tys = &[];
2340 err_args(fcx.tcx(), args.len())
2343 } else if expected_arg_count == supplied_arg_count {
2345 } else if variadic {
2346 if supplied_arg_count >= expected_arg_count {
2349 span_err!(tcx.sess, sp, E0060,
2350 "this function takes at least {} parameter{} \
2351 but {} parameter{} supplied",
2353 if expected_arg_count == 1 {""} else {"s"},
2355 if supplied_arg_count == 1 {" was"} else {"s were"});
2356 expected_arg_tys = &[];
2357 err_args(fcx.tcx(), supplied_arg_count)
2360 span_err!(tcx.sess, sp, E0061,
2361 "this function takes {} parameter{} but {} parameter{} supplied",
2363 if expected_arg_count == 1 {""} else {"s"},
2365 if supplied_arg_count == 1 {" was"} else {"s were"});
2366 expected_arg_tys = &[];
2367 err_args(fcx.tcx(), supplied_arg_count)
2370 debug!("check_argument_types: formal_tys={:?}",
2371 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2373 // Check the arguments.
2374 // We do this in a pretty awful way: first we typecheck any arguments
2375 // that are not anonymous functions, then we typecheck the anonymous
2376 // functions. This is so that we have more information about the types
2377 // of arguments when we typecheck the functions. This isn't really the
2378 // right way to do this.
2379 let xs = [false, true];
2380 for check_blocks in &xs {
2381 let check_blocks = *check_blocks;
2382 debug!("check_blocks={}", check_blocks);
2384 // More awful hacks: before we check argument types, try to do
2385 // an "opportunistic" vtable resolution of any trait bounds on
2386 // the call. This helps coercions.
2388 vtable::select_new_fcx_obligations(fcx);
2391 // For variadic functions, we don't have a declared type for all of
2392 // the arguments hence we only do our usual type checking with
2393 // the arguments who's types we do know.
2394 let t = if variadic {
2396 } else if tuple_arguments == TupleArguments {
2401 for (i, arg) in args.iter().take(t).enumerate() {
2402 let is_block = match arg.node {
2403 ast::ExprClosure(..) => true,
2407 if is_block == check_blocks {
2408 debug!("checking the argument");
2409 let mut formal_ty = formal_tys[i];
2411 match autoref_args {
2412 AutorefArgs::Yes => {
2413 match formal_ty.sty {
2414 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2417 // So we hit this case when one implements the
2418 // operator traits but leaves an argument as
2419 // just T instead of &T. We'll catch it in the
2420 // mismatch impl/trait method phase no need to
2423 formal_ty = tcx.types.err;
2427 AutorefArgs::No => {}
2430 // The special-cased logic below has three functions:
2431 // 1. Provide as good of an expected type as possible.
2432 let expected = expected_arg_tys.get(i).map(|&ty| {
2433 Expectation::rvalue_hint(ty)
2436 check_expr_with_unifier(fcx, &**arg,
2437 expected.unwrap_or(ExpectHasType(formal_ty)),
2439 // 2. Coerce to the most detailed type that could be coerced
2440 // to, which is `expected_ty` if `rvalue_hint` returns an
2441 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2442 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2443 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2445 // 3. Relate the expected type and the formal one,
2446 // if the expected type was used for the coercion.
2447 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2453 // We also need to make sure we at least write the ty of the other
2454 // arguments which we skipped above.
2456 for arg in args.iter().skip(expected_arg_count) {
2457 check_expr(fcx, &**arg);
2459 // There are a few types which get autopromoted when passed via varargs
2460 // in C but we just error out instead and require explicit casts.
2461 let arg_ty = structurally_resolved_type(fcx, arg.span,
2462 fcx.expr_ty(&**arg));
2464 ty::ty_float(ast::TyF32) => {
2465 fcx.type_error_message(arg.span,
2467 format!("can't pass an {} to variadic \
2468 function, cast to c_double", t)
2471 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2472 fcx.type_error_message(arg.span, |t| {
2473 format!("can't pass {} to variadic \
2474 function, cast to c_int",
2478 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2479 fcx.type_error_message(arg.span, |t| {
2480 format!("can't pass {} to variadic \
2481 function, cast to c_uint",
2491 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2492 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2493 (0..len).map(|_| tcx.types.err).collect()
2496 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2497 call_expr: &ast::Expr,
2498 output: ty::FnOutput<'tcx>) {
2499 fcx.write_ty(call_expr.id, match output {
2500 ty::FnConverging(output_ty) => output_ty,
2501 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2505 // AST fragment checking
2506 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2508 expected: Expectation<'tcx>)
2511 let tcx = fcx.ccx.tcx;
2514 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2515 ast::LitBinary(ref v) => {
2516 ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
2517 ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
2518 mutbl: ast::MutImmutable,
2521 ast::LitByte(_) => tcx.types.u8,
2522 ast::LitChar(_) => tcx.types.char,
2523 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2524 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2525 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2526 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2528 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2529 ty::ty_char => Some(tcx.types.u8),
2530 ty::ty_ptr(..) => Some(tcx.types.uint),
2531 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2535 opt_ty.unwrap_or_else(
2536 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2538 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2539 ast::LitFloatUnsuffixed(_) => {
2540 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2542 ty::ty_float(_) => Some(ty),
2546 opt_ty.unwrap_or_else(
2547 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2549 ast::LitBool(_) => tcx.types.bool
2553 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2554 expr: &'tcx ast::Expr,
2555 expected: Ty<'tcx>) {
2556 check_expr_with_unifier(
2557 fcx, expr, ExpectHasType(expected), NoPreference,
2558 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2561 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2562 expr: &'tcx ast::Expr,
2563 expected: Ty<'tcx>) {
2564 check_expr_with_unifier(
2565 fcx, expr, ExpectHasType(expected), NoPreference,
2566 || demand::coerce(fcx, expr.span, expected, expr));
2569 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2570 expected: Ty<'tcx>) {
2571 check_expr_with_unifier(
2572 fcx, expr, ExpectHasType(expected), NoPreference,
2576 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2577 expr: &'tcx ast::Expr,
2578 expected: Expectation<'tcx>) {
2579 check_expr_with_unifier(
2580 fcx, expr, expected, NoPreference,
2584 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2585 expr: &'tcx ast::Expr,
2586 expected: Expectation<'tcx>,
2587 lvalue_pref: LvaluePreference)
2589 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2592 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2593 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2596 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2597 lvalue_pref: LvaluePreference) {
2598 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2601 // determine the `self` type, using fresh variables for all variables
2602 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2603 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2605 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2606 span: Span, // (potential) receiver for this impl
2608 -> TypeAndSubsts<'tcx> {
2609 let tcx = fcx.tcx();
2611 let ity = ty::lookup_item_type(tcx, did);
2612 let (n_tps, rps, raw_ty) =
2613 (ity.generics.types.len(subst::TypeSpace),
2614 ity.generics.regions.get_slice(subst::TypeSpace),
2617 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2618 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2619 let substs = subst::Substs::new_type(tps, rps);
2620 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2622 TypeAndSubsts { substs: substs, ty: substd_ty }
2625 // Controls whether the arguments are automatically referenced. This is useful
2626 // for overloaded binary and unary operators.
2627 #[derive(Copy, PartialEq)]
2628 pub enum AutorefArgs {
2633 /// Controls whether the arguments are tupled. This is used for the call
2636 /// Tupling means that all call-side arguments are packed into a tuple and
2637 /// passed as a single parameter. For example, if tupling is enabled, this
2640 /// fn f(x: (int, int))
2642 /// Can be called as:
2649 #[derive(Clone, Eq, PartialEq)]
2650 enum TupleArgumentsFlag {
2655 /// Unifies the return type with the expected type early, for more coercions
2656 /// and forward type information on the argument expressions.
2657 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2659 expected_ret: Expectation<'tcx>,
2660 formal_ret: ty::FnOutput<'tcx>,
2661 formal_args: &[Ty<'tcx>])
2663 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2664 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2665 fcx.infcx().commit_regions_if_ok(|| {
2666 // Attempt to apply a subtyping relationship between the formal
2667 // return type (likely containing type variables if the function
2668 // is polymorphic) and the expected return type.
2669 // No argument expectations are produced if unification fails.
2670 let origin = infer::Misc(call_span);
2671 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2672 // FIXME(#15760) can't use try! here, FromError doesn't default
2673 // to identity so the resulting type is not constrained.
2674 if let Err(e) = ures {
2678 // Record all the argument types, with the substitutions
2679 // produced from the above subtyping unification.
2680 Ok(formal_args.iter().map(|ty| {
2681 fcx.infcx().resolve_type_vars_if_possible(ty)
2687 }).unwrap_or(vec![]);
2688 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2689 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2690 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2695 /// If an expression has any sub-expressions that result in a type error,
2696 /// inspecting that expression's type with `ty::type_is_error` will return
2697 /// true. Likewise, if an expression is known to diverge, inspecting its
2698 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2699 /// strict, _|_ can appear in the type of an expression that does not,
2700 /// itself, diverge: for example, fn() -> _|_.)
2701 /// Note that inspecting a type's structure *directly* may expose the fact
2702 /// that there are actually multiple representations for `ty_err`, so avoid
2703 /// that when err needs to be handled differently.
2704 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2705 expr: &'tcx ast::Expr,
2706 expected: Expectation<'tcx>,
2707 lvalue_pref: LvaluePreference,
2711 debug!(">> typechecking: expr={} expected={}",
2712 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2714 // Checks a method call.
2715 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2716 expr: &'tcx ast::Expr,
2717 method_name: ast::SpannedIdent,
2718 args: &'tcx [P<ast::Expr>],
2720 expected: Expectation<'tcx>,
2721 lvalue_pref: LvaluePreference) {
2722 let rcvr = &*args[0];
2723 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2725 // no need to check for bot/err -- callee does that
2726 let expr_t = structurally_resolved_type(fcx,
2728 fcx.expr_ty(&*rcvr));
2730 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2731 let fn_ty = match method::lookup(fcx,
2733 method_name.node.name,
2739 let method_ty = method.ty;
2740 let method_call = MethodCall::expr(expr.id);
2741 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2745 method::report_error(fcx, method_name.span, expr_t,
2746 method_name.node.name, Some(rcvr), error);
2747 fcx.write_error(expr.id);
2752 // Call the generic checker.
2753 let ret_ty = check_method_argument_types(fcx,
2762 write_call(fcx, expr, ret_ty);
2765 // A generic function for checking the then and else in an if
2767 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2768 cond_expr: &'tcx ast::Expr,
2769 then_blk: &'tcx ast::Block,
2770 opt_else_expr: Option<&'tcx ast::Expr>,
2773 expected: Expectation<'tcx>) {
2774 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2776 let expected = expected.adjust_for_branches(fcx);
2777 check_block_with_expected(fcx, then_blk, expected);
2778 let then_ty = fcx.node_ty(then_blk.id);
2780 let branches_ty = match opt_else_expr {
2781 Some(ref else_expr) => {
2782 check_expr_with_expectation(fcx, &**else_expr, expected);
2783 let else_ty = fcx.expr_ty(&**else_expr);
2784 infer::common_supertype(fcx.infcx(),
2785 infer::IfExpression(sp),
2791 infer::common_supertype(fcx.infcx(),
2792 infer::IfExpressionWithNoElse(sp),
2795 ty::mk_nil(fcx.tcx()))
2799 let cond_ty = fcx.expr_ty(cond_expr);
2800 let if_ty = if ty::type_is_error(cond_ty) {
2806 fcx.write_ty(id, if_ty);
2809 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2810 op_ex: &'tcx ast::Expr,
2813 trait_did: Option<ast::DefId>,
2815 rhs: Option<&'tcx P<ast::Expr>>,
2817 autoref_args: AutorefArgs) -> Ty<'tcx> where
2820 let method = match trait_did {
2821 Some(trait_did) => {
2822 // We do eager coercions to make using operators
2825 // - If the input is of type &'a T (resp. &'a mut T),
2826 // then reborrow it to &'b T (resp. &'b mut T) where
2827 // 'b <= 'a. This makes things like `x == y`, where
2828 // `x` and `y` are both region pointers, work. We
2829 // could also solve this with variance or different
2830 // traits that don't force left and right to have same
2832 let (adj_ty, adjustment) = match lhs_ty.sty {
2833 ty::ty_rptr(r_in, mt) => {
2834 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2835 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2836 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2837 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2838 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2839 (adjusted_ty, adjustment)
2842 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2846 debug!("adjusted_ty={} adjustment={:?}",
2847 adj_ty.repr(fcx.tcx()),
2850 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2851 trait_did, adjustment, adj_ty, None)
2855 let args = match rhs {
2856 Some(rhs) => slice::ref_slice(rhs),
2861 let method_ty = method.ty;
2862 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2863 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2864 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2865 match check_method_argument_types(fcx,
2873 ty::FnConverging(result_type) => result_type,
2874 ty::FnDiverging => fcx.tcx().types.err
2879 // Check the args anyway
2880 // so we get all the error messages
2881 let expected_ty = fcx.tcx().types.err;
2882 check_method_argument_types(fcx,
2895 // could be either an expr_binop or an expr_assign_binop
2896 fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2897 expr: &'tcx ast::Expr,
2899 lhs: &'tcx ast::Expr,
2900 rhs: &'tcx P<ast::Expr>,
2901 is_binop_assignment: IsBinopAssignment) {
2902 let tcx = fcx.ccx.tcx;
2904 let lvalue_pref = match is_binop_assignment {
2905 BinopAssignment => PreferMutLvalue,
2906 SimpleBinop => NoPreference
2908 check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
2910 // Callee does bot / err checking
2912 structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || {
2913 if ast_util::is_symmetric_binop(op.node) {
2915 check_expr(fcx, &**rhs);
2922 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
2923 // Shift is a special case: rhs must be uint, no matter what lhs is
2924 check_expr(fcx, &**rhs);
2925 let rhs_ty = fcx.expr_ty(&**rhs);
2926 let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty);
2927 if ty::type_is_integral(rhs_ty) {
2928 fcx.write_ty(expr.id, lhs_t);
2930 fcx.type_error_message(
2934 "right-hand-side of a shift operation must have integral type, \
2940 fcx.write_ty(expr.id, fcx.tcx().types.err);
2945 if ty::is_binopable(tcx, lhs_t, op) {
2946 let tvar = fcx.infcx().next_ty_var();
2947 demand::suptype(fcx, expr.span, tvar, lhs_t);
2948 check_expr_has_type(fcx, &**rhs, tvar);
2950 let result_t = match op.node {
2951 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2953 if ty::type_is_simd(tcx, lhs_t) {
2954 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2955 fcx.type_error_message(expr.span,
2957 format!("binary comparison \
2958 operation `{}` not \
2959 supported for floating \
2960 point SIMD vector `{}`",
2961 ast_util::binop_to_string(op.node),
2972 fcx.tcx().types.bool
2978 fcx.write_ty(expr.id, result_t);
2982 if op.node == ast::BiOr || op.node == ast::BiAnd {
2983 // This is an error; one of the operands must have the wrong
2985 fcx.write_error(expr.id);
2986 fcx.write_error(rhs.id);
2987 fcx.type_error_message(expr.span,
2989 format!("binary operation `{}` cannot be applied \
2991 ast_util::binop_to_string(op.node),
2998 // Check for overloaded operators if not an assignment.
2999 let result_t = if is_binop_assignment == SimpleBinop {
3000 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3002 fcx.type_error_message(expr.span,
3004 format!("binary assignment \
3006 cannot be applied to \
3008 ast_util::binop_to_string(op.node),
3013 check_expr(fcx, &**rhs);
3017 fcx.write_ty(expr.id, result_t);
3018 if ty::type_is_error(result_t) {
3019 fcx.write_ty(rhs.id, result_t);
3023 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3024 ex: &'tcx ast::Expr,
3025 lhs_expr: &'tcx ast::Expr,
3026 lhs_resolved_t: Ty<'tcx>,
3028 rhs: &'tcx P<ast::Expr>) -> Ty<'tcx> {
3029 let tcx = fcx.ccx.tcx;
3030 let lang = &tcx.lang_items;
3031 let (name, trait_did) = match op.node {
3032 ast::BiAdd => ("add", lang.add_trait()),
3033 ast::BiSub => ("sub", lang.sub_trait()),
3034 ast::BiMul => ("mul", lang.mul_trait()),
3035 ast::BiDiv => ("div", lang.div_trait()),
3036 ast::BiRem => ("rem", lang.rem_trait()),
3037 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3038 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3039 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3040 ast::BiShl => ("shl", lang.shl_trait()),
3041 ast::BiShr => ("shr", lang.shr_trait()),
3042 ast::BiLt => ("lt", lang.ord_trait()),
3043 ast::BiLe => ("le", lang.ord_trait()),
3044 ast::BiGe => ("ge", lang.ord_trait()),
3045 ast::BiGt => ("gt", lang.ord_trait()),
3046 ast::BiEq => ("eq", lang.eq_trait()),
3047 ast::BiNe => ("ne", lang.eq_trait()),
3048 ast::BiAnd | ast::BiOr => {
3049 check_expr(fcx, &**rhs);
3050 return tcx.types.err;
3053 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3054 trait_did, lhs_expr, Some(rhs), || {
3055 fcx.type_error_message(ex.span, |actual| {
3056 format!("binary operation `{}` cannot be applied to type `{}`",
3057 ast_util::binop_to_string(op.node),
3059 }, lhs_resolved_t, None)
3060 }, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes })
3063 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3066 trait_did: Option<ast::DefId>,
3067 ex: &'tcx ast::Expr,
3068 rhs_expr: &'tcx ast::Expr,
3070 op: ast::UnOp) -> Ty<'tcx> {
3071 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3072 trait_did, rhs_expr, None, || {
3073 fcx.type_error_message(ex.span, |actual| {
3074 format!("cannot apply unary operator `{}` to type `{}`",
3077 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3080 // Check field access expressions
3081 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3082 expr: &'tcx ast::Expr,
3083 lvalue_pref: LvaluePreference,
3084 base: &'tcx ast::Expr,
3085 field: &ast::SpannedIdent) {
3086 let tcx = fcx.ccx.tcx;
3087 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3088 let expr_t = structurally_resolved_type(fcx, expr.span,
3090 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3091 let (_, autoderefs, field_ty) = autoderef(fcx,
3095 UnresolvedTypeAction::Error,
3099 ty::ty_struct(base_id, substs) => {
3100 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3101 let fields = ty::lookup_struct_fields(tcx, base_id);
3102 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
3103 field.node.name, &(*substs))
3110 fcx.write_ty(expr.id, field_ty);
3111 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3117 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3118 fcx.type_error_message(
3121 format!("attempted to take value of method `{}` on type \
3122 `{}`", token::get_ident(field.node), actual)
3126 tcx.sess.fileline_help(field.span,
3127 "maybe a `()` to call it is missing? \
3128 If not, try an anonymous function");
3130 fcx.type_error_message(
3133 format!("attempted access of field `{}` on \
3134 type `{}`, but no field with that \
3136 token::get_ident(field.node),
3140 if let Some(t) = ty::ty_to_def_id(expr_t) {
3141 suggest_field_names(t, field, tcx, vec![]);
3145 fcx.write_error(expr.id);
3148 // displays hints about the closest matches in field names
3149 fn suggest_field_names<'tcx>(id : DefId,
3150 field : &ast::SpannedIdent,
3151 tcx : &ty::ctxt<'tcx>,
3153 let ident = token::get_ident(field.node);
3155 // only find fits with at least one matching letter
3156 let mut best_dist = name.len();
3157 let fields = ty::lookup_struct_fields(tcx, id);
3158 let mut best = None;
3159 for elem in &fields {
3160 let n = elem.name.as_str();
3161 // ignore already set fields
3162 if skip.iter().any(|&x| x == n) {
3165 // ignore private fields from non-local crates
3166 if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
3169 let dist = lev_distance(n, name);
3170 if dist < best_dist {
3175 if let Some(n) = best {
3176 tcx.sess.span_help(field.span,
3177 &format!("did you mean `{}`?", n));
3181 // Check tuple index expressions
3182 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3183 expr: &'tcx ast::Expr,
3184 lvalue_pref: LvaluePreference,
3185 base: &'tcx ast::Expr,
3186 idx: codemap::Spanned<uint>) {
3187 let tcx = fcx.ccx.tcx;
3188 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3189 let expr_t = structurally_resolved_type(fcx, expr.span,
3191 let mut tuple_like = false;
3192 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3193 let (_, autoderefs, field_ty) = autoderef(fcx,
3197 UnresolvedTypeAction::Error,
3201 ty::ty_struct(base_id, substs) => {
3202 tuple_like = ty::is_tuple_struct(tcx, base_id);
3204 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3205 let fields = ty::lookup_struct_fields(tcx, base_id);
3206 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
3207 idx.node, &(*substs))
3212 ty::ty_tup(ref v) => {
3214 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3221 fcx.write_ty(expr.id, field_ty);
3222 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3227 fcx.type_error_message(
3231 format!("attempted out-of-bounds tuple index `{}` on \
3236 format!("attempted tuple index `{}` on type `{}`, but the \
3237 type was not a tuple or tuple struct",
3244 fcx.write_error(expr.id);
3247 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3248 struct_ty: Ty<'tcx>,
3250 class_id: ast::DefId,
3251 node_id: ast::NodeId,
3252 substitutions: &'tcx subst::Substs<'tcx>,
3253 field_types: &[ty::field_ty],
3254 ast_fields: &'tcx [ast::Field],
3255 check_completeness: bool,
3256 enum_id_opt: Option<ast::DefId>) {
3257 let tcx = fcx.ccx.tcx;
3259 let mut class_field_map = FnvHashMap();
3260 let mut fields_found = 0;
3261 for field in field_types {
3262 class_field_map.insert(field.name, (field.id, false));
3265 let mut error_happened = false;
3267 // Typecheck each field.
3268 for field in ast_fields {
3269 let mut expected_field_type = tcx.types.err;
3271 let pair = class_field_map.get(&field.ident.node.name).cloned();
3274 fcx.type_error_message(
3276 |actual| match enum_id_opt {
3278 let variant_type = ty::enum_variant_with_id(tcx,
3281 format!("struct variant `{}::{}` has no field named `{}`",
3282 actual, variant_type.name.as_str(),
3283 token::get_ident(field.ident.node))
3286 format!("structure `{}` has no field named `{}`",
3288 token::get_ident(field.ident.node))
3293 // prevent all specified fields from being suggested
3294 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
3295 let actual_id = match enum_id_opt {
3296 Some(_) => class_id,
3297 None => ty::ty_to_def_id(struct_ty).unwrap()
3299 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3300 error_happened = true;
3302 Some((_, true)) => {
3303 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3304 "field `{}` specified more than once",
3305 token::get_ident(field.ident.node));
3306 error_happened = true;
3308 Some((field_id, false)) => {
3309 expected_field_type =
3310 ty::lookup_field_type(
3311 tcx, class_id, field_id, substitutions);
3312 expected_field_type =
3313 fcx.normalize_associated_types_in(
3314 field.span, &expected_field_type);
3315 class_field_map.insert(
3316 field.ident.node.name, (field_id, true));
3321 // Make sure to give a type to the field even if there's
3322 // an error, so we can continue typechecking
3323 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3327 fcx.write_error(node_id);
3330 if check_completeness && !error_happened {
3331 // Make sure the programmer specified all the fields.
3332 assert!(fields_found <= field_types.len());
3333 if fields_found < field_types.len() {
3334 let mut missing_fields = Vec::new();
3335 for class_field in field_types {
3336 let name = class_field.name;
3337 let (_, seen) = *class_field_map.get(&name).unwrap();
3339 missing_fields.push(
3340 format!("`{}`", &token::get_name(name)))
3344 span_err!(tcx.sess, span, E0063,
3345 "missing field{}: {}",
3346 if missing_fields.len() == 1 {""} else {"s"},
3347 missing_fields.connect(", "));
3351 if !error_happened {
3352 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3353 class_id, substitutions));
3357 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3359 span: codemap::Span,
3360 class_id: ast::DefId,
3361 fields: &'tcx [ast::Field],
3362 base_expr: Option<&'tcx ast::Expr>) {
3363 let tcx = fcx.ccx.tcx;
3365 // Generate the struct type.
3367 ty: mut struct_type,
3368 substs: struct_substs
3369 } = fcx.instantiate_type(span, class_id);
3371 // Look up and check the fields.
3372 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3373 check_struct_or_variant_fields(fcx,
3378 fcx.ccx.tcx.mk_substs(struct_substs),
3381 base_expr.is_none(),
3383 if ty::type_is_error(fcx.node_ty(id)) {
3384 struct_type = tcx.types.err;
3387 // Check the base expression if necessary.
3390 Some(base_expr) => {
3391 check_expr_has_type(fcx, &*base_expr, struct_type);
3395 // Write in the resulting type.
3396 fcx.write_ty(id, struct_type);
3399 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3401 span: codemap::Span,
3402 enum_id: ast::DefId,
3403 variant_id: ast::DefId,
3404 fields: &'tcx [ast::Field]) {
3405 let tcx = fcx.ccx.tcx;
3407 // Look up the number of type parameters and the raw type, and
3408 // determine whether the enum is region-parameterized.
3411 substs: substitutions
3412 } = fcx.instantiate_type(span, enum_id);
3414 // Look up and check the enum variant fields.
3415 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3416 check_struct_or_variant_fields(fcx,
3421 fcx.ccx.tcx.mk_substs(substitutions),
3422 &variant_fields[..],
3426 fcx.write_ty(id, enum_type);
3429 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3431 fields: &'tcx [ast::Field],
3432 base_expr: &'tcx Option<P<ast::Expr>>) {
3433 // Make sure to still write the types
3434 // otherwise we might ICE
3435 fcx.write_error(id);
3436 for field in fields {
3437 check_expr(fcx, &*field.expr);
3440 Some(ref base) => check_expr(fcx, &**base),
3445 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3447 let tcx = fcx.ccx.tcx;
3450 ast::ExprBox(ref opt_place, ref subexpr) => {
3451 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3452 check_expr(fcx, &**subexpr);
3454 let mut checked = false;
3455 opt_place.as_ref().map(|place| match place.node {
3456 ast::ExprPath(None, ref path) => {
3457 // FIXME(pcwalton): For now we hardcode the two permissible
3458 // places: the exchange heap and the managed heap.
3459 let definition = lookup_full_def(tcx, path.span, place.id);
3460 let def_id = definition.def_id();
3461 let referent_ty = fcx.expr_ty(&**subexpr);
3462 if tcx.lang_items.exchange_heap() == Some(def_id) {
3463 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3471 span_err!(tcx.sess, expr.span, E0066,
3472 "only the managed heap and exchange heap are currently supported");
3473 fcx.write_ty(id, tcx.types.err);
3477 ast::ExprLit(ref lit) => {
3478 let typ = check_lit(fcx, &**lit, expected);
3479 fcx.write_ty(id, typ);
3481 ast::ExprBinary(op, ref lhs, ref rhs) => {
3482 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3484 let lhs_ty = fcx.expr_ty(&**lhs);
3485 let rhs_ty = fcx.expr_ty(&**rhs);
3486 if ty::type_is_error(lhs_ty) ||
3487 ty::type_is_error(rhs_ty) {
3488 fcx.write_error(id);
3491 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3492 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3494 let lhs_t = fcx.expr_ty(&**lhs);
3495 let result_t = fcx.expr_ty(expr);
3496 demand::suptype(fcx, expr.span, result_t, lhs_t);
3498 let tcx = fcx.tcx();
3499 if !ty::expr_is_lval(tcx, &**lhs) {
3500 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3503 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3505 // Overwrite result of check_binop...this preserves existing behavior
3506 // but seems quite dubious with regard to user-defined methods
3507 // and so forth. - Niko
3508 if !ty::type_is_error(result_t) {
3509 fcx.write_nil(expr.id);
3512 ast::ExprUnary(unop, ref oprnd) => {
3513 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3515 ast::UnUniq => match ty.sty {
3516 ty::ty_uniq(ty) => {
3517 Expectation::rvalue_hint(ty)
3523 ast::UnNot | ast::UnNeg => {
3531 let lvalue_pref = match unop {
3532 ast::UnDeref => lvalue_pref,
3535 check_expr_with_expectation_and_lvalue_pref(
3536 fcx, &**oprnd, expected_inner, lvalue_pref);
3537 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3539 if !ty::type_is_error(oprnd_t) {
3542 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3545 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3546 oprnd_t = match ty::deref(oprnd_t, true) {
3548 None => match try_overloaded_deref(fcx, expr.span,
3549 Some(MethodCall::expr(expr.id)),
3550 Some(&**oprnd), oprnd_t, lvalue_pref) {
3553 let is_newtype = match oprnd_t.sty {
3554 ty::ty_struct(did, substs) => {
3555 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3557 && fields[0].name ==
3558 token::special_idents::unnamed_field.name
3563 // This is an obsolete struct deref
3564 span_err!(tcx.sess, expr.span, E0068,
3565 "single-field tuple-structs can \
3566 no longer be dereferenced");
3568 fcx.type_error_message(expr.span, |actual| {
3569 format!("type `{}` cannot be \
3570 dereferenced", actual)
3579 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3581 if !(ty::type_is_integral(oprnd_t) ||
3582 oprnd_t.sty == ty::ty_bool) {
3583 oprnd_t = check_user_unop(fcx, "!", "not",
3584 tcx.lang_items.not_trait(),
3585 expr, &**oprnd, oprnd_t, unop);
3589 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3591 if !(ty::type_is_integral(oprnd_t) ||
3592 ty::type_is_fp(oprnd_t)) {
3593 oprnd_t = check_user_unop(fcx, "-", "neg",
3594 tcx.lang_items.neg_trait(),
3595 expr, &**oprnd, oprnd_t, unop);
3600 fcx.write_ty(id, oprnd_t);
3602 ast::ExprAddrOf(mutbl, ref oprnd) => {
3603 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3605 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3606 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3607 // Lvalues may legitimately have unsized types.
3608 // For example, dereferences of a fat pointer and
3609 // the last field of a struct can be unsized.
3610 ExpectHasType(mt.ty)
3612 Expectation::rvalue_hint(mt.ty)
3618 let lvalue_pref = match mutbl {
3619 ast::MutMutable => PreferMutLvalue,
3620 ast::MutImmutable => NoPreference
3622 check_expr_with_expectation_and_lvalue_pref(fcx,
3627 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3628 let oprnd_t = if ty::type_is_error(tm.ty) {
3631 // Note: at this point, we cannot say what the best lifetime
3632 // is to use for resulting pointer. We want to use the
3633 // shortest lifetime possible so as to avoid spurious borrowck
3634 // errors. Moreover, the longest lifetime will depend on the
3635 // precise details of the value whose address is being taken
3636 // (and how long it is valid), which we don't know yet until type
3637 // inference is complete.
3639 // Therefore, here we simply generate a region variable. The
3640 // region inferencer will then select the ultimate value.
3641 // Finally, borrowck is charged with guaranteeing that the
3642 // value whose address was taken can actually be made to live
3643 // as long as it needs to live.
3644 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3645 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3647 fcx.write_ty(id, oprnd_t);
3649 ast::ExprPath(ref maybe_qself, ref path) => {
3650 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
3651 fcx.to_ty(&qself.ty)
3654 let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
3656 } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
3657 // Create some fake resolution that can't possibly be a type.
3658 def::PathResolution {
3659 base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
3660 last_private: LastMod(AllPublic),
3661 depth: path.segments.len()
3664 tcx.sess.span_bug(expr.span,
3665 &format!("unbound path {}", expr.repr(tcx)))
3668 let mut def = path_res.base_def;
3669 if path_res.depth == 0 {
3670 let (scheme, predicates) =
3671 type_scheme_and_predicates_for_def(fcx, expr.span, def);
3672 instantiate_path(fcx, &path.segments,
3673 scheme, &predicates,
3674 opt_self_ty, def, expr.span, id);
3676 let ty_segments = path.segments.init();
3677 let base_ty_end = path.segments.len() - path_res.depth;
3678 let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
3679 PathParamMode::Optional,
3682 &ty_segments[..base_ty_end],
3683 &ty_segments[base_ty_end..]);
3684 let method_segment = path.segments.last().unwrap();
3685 let method_name = method_segment.identifier.name;
3686 match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
3688 // Write back the new resolution.
3689 tcx.def_map.borrow_mut().insert(id, def::PathResolution {
3691 last_private: path_res.last_private.or(lp),
3695 let (scheme, predicates) =
3696 type_scheme_and_predicates_for_def(fcx, expr.span, def);
3697 instantiate_path(fcx, slice::ref_slice(method_segment),
3698 scheme, &predicates,
3699 Some(ty), def, expr.span, id);
3702 method::report_error(fcx, expr.span, ty,
3703 method_name, None, error);
3704 fcx.write_error(id);
3709 // We always require that the type provided as the value for
3710 // a type parameter outlives the moment of instantiation.
3711 constrain_path_type_parameters(fcx, expr);
3713 ast::ExprInlineAsm(ref ia) => {
3714 for &(_, ref input) in &ia.inputs {
3715 check_expr(fcx, &**input);
3717 for &(_, ref out, _) in &ia.outputs {
3718 check_expr(fcx, &**out);
3722 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3723 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3724 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3725 ast::ExprRet(ref expr_opt) => {
3727 ty::FnConverging(result_type) => {
3730 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3731 result_type, ty::mk_nil(fcx.tcx())) {
3732 span_err!(tcx.sess, expr.span, E0069,
3733 "`return;` in function returning non-nil");
3736 check_expr_coercable_to_type(fcx, &**e, result_type);
3740 ty::FnDiverging => {
3741 if let Some(ref e) = *expr_opt {
3742 check_expr(fcx, &**e);
3744 span_err!(tcx.sess, expr.span, E0166,
3745 "`return` in a function declared as diverging");
3748 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3750 ast::ExprParen(ref a) => {
3751 check_expr_with_expectation_and_lvalue_pref(fcx,
3755 fcx.write_ty(id, fcx.expr_ty(&**a));
3757 ast::ExprAssign(ref lhs, ref rhs) => {
3758 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3760 let tcx = fcx.tcx();
3761 if !ty::expr_is_lval(tcx, &**lhs) {
3762 span_err!(tcx.sess, expr.span, E0070,
3763 "illegal left-hand side expression");
3766 let lhs_ty = fcx.expr_ty(&**lhs);
3767 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3768 let rhs_ty = fcx.expr_ty(&**rhs);
3770 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3772 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3773 fcx.write_error(id);
3778 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3779 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3780 id, expr.span, expected);
3782 ast::ExprIfLet(..) => {
3783 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3785 ast::ExprWhile(ref cond, ref body, _) => {
3786 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3787 check_block_no_value(fcx, &**body);
3788 let cond_ty = fcx.expr_ty(&**cond);
3789 let body_ty = fcx.node_ty(body.id);
3790 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3791 fcx.write_error(id);
3797 ast::ExprWhileLet(..) => {
3798 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3800 ast::ExprForLoop(..) => {
3801 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3803 ast::ExprLoop(ref body, _) => {
3804 check_block_no_value(fcx, &**body);
3805 if !may_break(tcx, expr.id, &**body) {
3806 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3811 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3812 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3814 ast::ExprClosure(capture, ref decl, ref body) => {
3815 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3817 ast::ExprBlock(ref b) => {
3818 check_block_with_expected(fcx, &**b, expected);
3819 fcx.write_ty(id, fcx.node_ty(b.id));
3821 ast::ExprCall(ref callee, ref args) => {
3822 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3824 ast::ExprMethodCall(ident, ref tps, ref args) => {
3825 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3826 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3827 let args_err = arg_tys.fold(false,
3829 rest_err || ty::type_is_error(a)});
3831 fcx.write_error(id);
3834 ast::ExprCast(ref e, ref t) => {
3835 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3836 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3839 // Find the type of `e`. Supply hints based on the type we are casting to,
3841 let t_1 = fcx.to_ty(t);
3842 let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
3843 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
3844 let t_e = fcx.expr_ty(e);
3846 // Eagerly check for some obvious errors.
3847 if ty::type_is_error(t_e) {
3848 fcx.write_error(id);
3849 } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
3850 report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
3852 // Write a type for the whole expression, assuming everything is going
3854 fcx.write_ty(id, t_1);
3856 // Defer other checks until we're done type checking.
3857 let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
3858 deferred_cast_checks.push(CastCheck {
3859 expr: (**e).clone(),
3866 ast::ExprVec(ref args) => {
3867 let uty = expected.to_option(fcx).and_then(|uty| {
3869 ty::ty_vec(ty, _) => Some(ty),
3874 let typ = match uty {
3877 check_expr_coercable_to_type(fcx, &**e, uty);
3882 let t: Ty = fcx.infcx().next_ty_var();
3884 check_expr_has_type(fcx, &**e, t);
3889 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3890 fcx.write_ty(id, typ);
3892 ast::ExprRepeat(ref element, ref count_expr) => {
3893 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3894 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3896 let uty = match expected {
3897 ExpectHasType(uty) => {
3899 ty::ty_vec(ty, _) => Some(ty),
3906 let (element_ty, t) = match uty {
3908 check_expr_coercable_to_type(fcx, &**element, uty);
3912 let t: Ty = fcx.infcx().next_ty_var();
3913 check_expr_has_type(fcx, &**element, t);
3914 (fcx.expr_ty(&**element), t)
3919 // For [foo, ..n] where n > 1, `foo` must have
3921 fcx.require_type_meets(
3928 if ty::type_is_error(element_ty) {
3929 fcx.write_error(id);
3931 let t = ty::mk_vec(tcx, t, Some(count));
3932 fcx.write_ty(id, t);
3935 ast::ExprTup(ref elts) => {
3936 let flds = expected.only_has_type(fcx).and_then(|ty| {
3938 ty::ty_tup(ref flds) => Some(&flds[..]),
3942 let mut err_field = false;
3944 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3945 let t = match flds {
3946 Some(ref fs) if i < fs.len() => {
3948 check_expr_coercable_to_type(fcx, &**e, ety);
3952 check_expr_with_expectation(fcx, &**e, NoExpectation);
3956 err_field = err_field || ty::type_is_error(t);
3960 fcx.write_error(id);
3962 let typ = ty::mk_tup(tcx, elt_ts);
3963 fcx.write_ty(id, typ);
3966 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3967 // Resolve the path.
3968 let def = lookup_full_def(tcx, path.span, id);
3969 let struct_id = match def {
3970 def::DefVariant(enum_id, variant_id, true) => {
3971 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3972 variant_id, &fields[..]);
3975 def::DefTrait(def_id) => {
3976 span_err!(tcx.sess, path.span, E0159,
3977 "use of trait `{}` as a struct constructor",
3978 pprust::path_to_string(path));
3979 check_struct_fields_on_error(fcx,
3986 // Verify that this was actually a struct.
3987 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3989 ty::ty_struct(struct_did, _) => {
3990 check_struct_constructor(fcx,
3995 base_expr.as_ref().map(|e| &**e));
3998 span_err!(tcx.sess, path.span, E0071,
3999 "`{}` does not name a structure",
4000 pprust::path_to_string(path));
4001 check_struct_fields_on_error(fcx,
4012 // Turn the path into a type and verify that that type unifies with
4013 // the resulting structure type. This is needed to handle type
4014 // parameters correctly.
4015 let actual_structure_type = fcx.expr_ty(&*expr);
4016 if !ty::type_is_error(actual_structure_type) {
4017 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
4018 match fcx.mk_subty(false,
4019 infer::Misc(path.span),
4020 actual_structure_type,
4021 type_and_substs.ty) {
4023 Err(type_error) => {
4024 let type_error_description =
4025 ty::type_err_to_str(tcx, &type_error);
4026 span_err!(fcx.tcx().sess, path.span, E0235,
4027 "structure constructor specifies a \
4028 structure of type `{}`, but this \
4029 structure has type `{}`: {}",
4031 .ty_to_string(type_and_substs.ty),
4034 actual_structure_type),
4035 type_error_description);
4036 ty::note_and_explain_type_err(tcx, &type_error);
4041 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4043 ast::ExprField(ref base, ref field) => {
4044 check_field(fcx, expr, lvalue_pref, &**base, field);
4046 ast::ExprTupField(ref base, idx) => {
4047 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
4049 ast::ExprIndex(ref base, ref idx) => {
4050 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4051 let base_t = fcx.expr_ty(&**base);
4052 if ty::type_is_error(base_t) {
4053 fcx.write_ty(id, base_t);
4055 check_expr(fcx, &**idx);
4056 let idx_t = fcx.expr_ty(&**idx);
4057 if ty::type_is_error(idx_t) {
4058 fcx.write_ty(id, idx_t);
4060 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
4063 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
4065 MethodCall::expr(expr.id),
4075 Some((index_ty, element_ty)) => {
4076 // FIXME: we've already checked idx above, we should
4077 // probably just demand subtype or something here.
4078 check_expr_has_type(fcx, &**idx, index_ty);
4079 fcx.write_ty(id, element_ty);
4082 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
4083 fcx.type_error_message(
4086 format!("cannot index a value of type `{}`",
4091 fcx.write_ty(id, fcx.tcx().types.err);
4097 ast::ExprRange(ref start, ref end) => {
4098 let t_start = start.as_ref().map(|e| {
4099 check_expr(fcx, &**e);
4102 let t_end = end.as_ref().map(|e| {
4103 check_expr(fcx, &**e);
4107 let idx_type = match (t_start, t_end) {
4108 (Some(ty), None) | (None, Some(ty)) => {
4111 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
4112 ty::type_is_error(t_end)) => {
4113 Some(fcx.tcx().types.err)
4115 (Some(t_start), Some(t_end)) => {
4116 Some(infer::common_supertype(fcx.infcx(),
4117 infer::RangeExpression(expr.span),
4125 // Note that we don't check the type of start/end satisfy any
4126 // bounds because right now the range structs do not have any. If we add
4127 // some bounds, then we'll need to check `t_start` against them here.
4129 let range_type = match idx_type {
4130 Some(idx_type) if ty::type_is_error(idx_type) => {
4134 // Find the did from the appropriate lang item.
4135 let did = match (start, end) {
4136 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
4137 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
4138 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4140 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4144 if let Some(did) = did {
4145 let predicates = ty::lookup_predicates(tcx, did);
4146 let substs = Substs::new_type(vec![idx_type], vec![]);
4147 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
4148 fcx.add_obligations_for_parameters(
4149 traits::ObligationCause::new(expr.span,
4151 traits::ItemObligation(did)),
4154 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4156 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
4161 // Neither start nor end => RangeFull
4162 if let Some(did) = tcx.lang_items.range_full_struct() {
4163 let substs = Substs::new_type(vec![], vec![]);
4164 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4166 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
4172 fcx.write_ty(id, range_type);
4177 debug!("type of expr({}) {} is...", expr.id,
4178 syntax::print::pprust::expr_to_string(expr));
4179 debug!("... {}, expected is {}",
4180 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4181 expected.repr(tcx));
4186 fn constrain_path_type_parameters(fcx: &FnCtxt,
4189 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4190 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4194 impl<'tcx> Expectation<'tcx> {
4195 /// Provide an expectation for an rvalue expression given an *optional*
4196 /// hint, which is not required for type safety (the resulting type might
4197 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4198 /// is useful in determining the concrete type.
4200 /// The primary use case is where the expected type is a fat pointer,
4201 /// like `&[int]`. For example, consider the following statement:
4203 /// let x: &[int] = &[1, 2, 3];
4205 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4206 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4207 /// expectation `ExpectHasType([int])`, that would be too strong --
4208 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4209 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4210 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4211 /// which still is useful, because it informs integer literals and the like.
4212 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4213 /// for examples of where this comes up,.
4214 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4216 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4217 ExpectRvalueLikeUnsized(ty)
4219 _ => ExpectHasType(ty)
4223 // Resolves `expected` by a single level if it is a variable. If
4224 // there is no expected type or resolution is not possible (e.g.,
4225 // no constraints yet present), just returns `None`.
4226 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4231 ExpectCastableToType(t) => {
4232 ExpectCastableToType(
4233 fcx.infcx().resolve_type_vars_if_possible(&t))
4235 ExpectHasType(t) => {
4237 fcx.infcx().resolve_type_vars_if_possible(&t))
4239 ExpectRvalueLikeUnsized(t) => {
4240 ExpectRvalueLikeUnsized(
4241 fcx.infcx().resolve_type_vars_if_possible(&t))
4246 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4247 match self.resolve(fcx) {
4248 NoExpectation => None,
4249 ExpectCastableToType(ty) |
4251 ExpectRvalueLikeUnsized(ty) => Some(ty),
4255 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4256 match self.resolve(fcx) {
4257 ExpectHasType(ty) => Some(ty),
4263 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4264 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4266 NoExpectation => format!("NoExpectation"),
4267 ExpectHasType(t) => format!("ExpectHasType({})",
4269 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4271 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4277 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
4278 local: &'tcx ast::Local,
4279 init: &'tcx ast::Expr)
4281 let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
4283 let local_ty = fcx.local_ty(init.span, local.id);
4285 check_expr_coercable_to_type(fcx, init, local_ty)
4287 // Somewhat subtle: if we have a `ref` binding in the pattern,
4288 // we want to avoid introducing coercions for the RHS. This is
4289 // both because it helps preserve sanity and, in the case of
4290 // ref mut, for soundness (issue #23116). In particular, in
4291 // the latter case, we need to be clear that the type of the
4292 // referent for the reference that results is *equal to* the
4293 // type of the lvalue it is referencing, and not some
4294 // supertype thereof.
4295 check_expr(fcx, init);
4296 let init_ty = fcx.expr_ty(init);
4297 demand::eqtype(fcx, init.span, init_ty, local_ty);
4301 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
4302 let tcx = fcx.ccx.tcx;
4304 let t = fcx.local_ty(local.span, local.id);
4305 fcx.write_ty(local.id, t);
4307 if let Some(ref init) = local.init {
4308 check_decl_initializer(fcx, local, &**init);
4309 let init_ty = fcx.expr_ty(&**init);
4310 if ty::type_is_error(init_ty) {
4311 fcx.write_ty(local.id, init_ty);
4315 let pcx = pat_ctxt {
4317 map: pat_id_map(&tcx.def_map, &*local.pat),
4319 _match::check_pat(&pcx, &*local.pat, t);
4320 let pat_ty = fcx.node_ty(local.pat.id);
4321 if ty::type_is_error(pat_ty) {
4322 fcx.write_ty(local.id, pat_ty);
4326 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4328 let mut saw_bot = false;
4329 let mut saw_err = false;
4331 ast::StmtDecl(ref decl, id) => {
4334 ast::DeclLocal(ref l) => {
4335 check_decl_local(fcx, &**l);
4336 let l_t = fcx.node_ty(l.id);
4337 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4338 saw_err = saw_err || ty::type_is_error(l_t);
4340 ast::DeclItem(_) => {/* ignore for now */ }
4343 ast::StmtExpr(ref expr, id) => {
4345 // Check with expected type of ()
4346 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4347 let expr_ty = fcx.expr_ty(&**expr);
4348 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4349 saw_err = saw_err || ty::type_is_error(expr_ty);
4351 ast::StmtSemi(ref expr, id) => {
4353 check_expr(fcx, &**expr);
4354 let expr_ty = fcx.expr_ty(&**expr);
4355 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4356 saw_err |= ty::type_is_error(expr_ty);
4358 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4361 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4364 fcx.write_error(node_id);
4367 fcx.write_nil(node_id)
4371 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4372 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4373 let blkty = fcx.node_ty(blk.id);
4374 if ty::type_is_error(blkty) {
4375 fcx.write_error(blk.id);
4377 let nilty = ty::mk_nil(fcx.tcx());
4378 demand::suptype(fcx, blk.span, nilty, blkty);
4382 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4383 blk: &'tcx ast::Block,
4384 expected: Expectation<'tcx>) {
4386 let mut fcx_ps = fcx.ps.borrow_mut();
4387 let unsafety_state = fcx_ps.recurse(blk);
4388 replace(&mut *fcx_ps, unsafety_state)
4391 let mut warned = false;
4392 let mut any_diverges = false;
4393 let mut any_err = false;
4394 for s in &blk.stmts {
4395 check_stmt(fcx, &**s);
4396 let s_id = ast_util::stmt_id(&**s);
4397 let s_ty = fcx.node_ty(s_id);
4398 if any_diverges && !warned && match s.node {
4399 ast::StmtDecl(ref decl, _) => {
4401 ast::DeclLocal(_) => true,
4405 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4411 .add_lint(lint::builtin::UNREACHABLE_CODE,
4414 "unreachable statement".to_string());
4417 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4418 any_err = any_err || ty::type_is_error(s_ty);
4421 None => if any_err {
4422 fcx.write_error(blk.id);
4423 } else if any_diverges {
4424 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4426 fcx.write_nil(blk.id);
4429 if any_diverges && !warned {
4433 .add_lint(lint::builtin::UNREACHABLE_CODE,
4436 "unreachable expression".to_string());
4438 let ety = match expected {
4439 ExpectHasType(ety) => {
4440 check_expr_coercable_to_type(fcx, &**e, ety);
4444 check_expr_with_expectation(fcx, &**e, expected);
4450 fcx.write_error(blk.id);
4451 } else if any_diverges {
4452 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4454 fcx.write_ty(blk.id, ety);
4459 *fcx.ps.borrow_mut() = prev;
4462 /// Checks a constant appearing in a type. At the moment this is just the
4463 /// length expression in a fixed-length vector, but someday it might be
4464 /// extended to type-level numeric literals.
4465 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4466 expr: &'tcx ast::Expr,
4467 expected_type: Ty<'tcx>) {
4468 let inh = static_inherited_fields(ccx);
4469 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4470 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4473 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4477 let inh = static_inherited_fields(ccx);
4478 let rty = ty::node_id_to_type(ccx.tcx, id);
4479 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4480 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
4481 check_const_with_ty(&fcx, sp, e, declty);
4484 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4488 // Gather locals in statics (because of block expressions).
4489 // This is technically unnecessary because locals in static items are forbidden,
4490 // but prevents type checking from blowing up before const checking can properly
4492 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4494 check_expr_with_hint(fcx, e, declty);
4495 demand::coerce(fcx, e.span, declty, e);
4496 vtable::select_all_fcx_obligations_or_error(fcx);
4498 regionck::regionck_expr(fcx, e);
4499 writeback::resolve_type_vars_in_expr(fcx, e);
4502 /// Checks whether a type can be represented in memory. In particular, it
4503 /// identifies types that contain themselves without indirection through a
4504 /// pointer, which would mean their size is unbounded. This is different from
4505 /// the question of whether a type can be instantiated. See the definition of
4506 /// `check_instantiable`.
4507 pub fn check_representable(tcx: &ty::ctxt,
4509 item_id: ast::NodeId,
4510 designation: &str) -> bool {
4511 let rty = ty::node_id_to_type(tcx, item_id);
4513 // Check that it is possible to represent this type. This call identifies
4514 // (1) types that contain themselves and (2) types that contain a different
4515 // recursive type. It is only necessary to throw an error on those that
4516 // contain themselves. For case 2, there must be an inner type that will be
4517 // caught by case 1.
4518 match ty::is_type_representable(tcx, sp, rty) {
4519 ty::SelfRecursive => {
4520 span_err!(tcx.sess, sp, E0072,
4521 "illegal recursive {} type; \
4522 wrap the inner value in a box to make it representable",
4526 ty::Representable | ty::ContainsRecursive => (),
4531 /// Checks whether a type can be created without an instance of itself.
4532 /// This is similar but different from the question of whether a type
4533 /// can be represented. For example, the following type:
4535 /// enum foo { None, Some(foo) }
4537 /// is instantiable but is not representable. Similarly, the type
4539 /// enum foo { Some(@foo) }
4541 /// is representable, but not instantiable.
4542 pub fn check_instantiable(tcx: &ty::ctxt,
4544 item_id: ast::NodeId)
4546 let item_ty = ty::node_id_to_type(tcx, item_id);
4547 if !ty::is_instantiable(tcx, item_ty) {
4548 span_err!(tcx.sess, sp, E0073,
4549 "this type cannot be instantiated without an \
4550 instance of itself");
4551 fileline_help!(tcx.sess, sp, "consider using `Option<{}>`",
4552 ppaux::ty_to_string(tcx, item_ty));
4559 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4560 let t = ty::node_id_to_type(tcx, id);
4561 if ty::type_needs_subst(t) {
4562 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4566 ty::ty_struct(did, substs) => {
4567 let fields = ty::lookup_struct_fields(tcx, did);
4568 if fields.is_empty() {
4569 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4572 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4573 if !fields.iter().all(
4574 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4575 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4578 if !ty::type_is_machine(e) {
4579 span_err!(tcx.sess, sp, E0077,
4580 "SIMD vector element type should be machine type");
4588 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4590 vs: &'tcx [P<ast::Variant>],
4593 fn disr_in_range(ccx: &CrateCtxt,
4595 disr: ty::Disr) -> bool {
4596 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4598 ast::TyU8 => disr as u8 as Disr == disr,
4599 ast::TyU16 => disr as u16 as Disr == disr,
4600 ast::TyU32 => disr as u32 as Disr == disr,
4601 ast::TyU64 => disr as u64 as Disr == disr,
4602 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4605 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4607 ast::TyI8 => disr as i8 as Disr == disr,
4608 ast::TyI16 => disr as i16 as Disr == disr,
4609 ast::TyI32 => disr as i32 as Disr == disr,
4610 ast::TyI64 => disr as i64 as Disr == disr,
4611 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4615 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4616 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4620 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4621 vs: &'tcx [P<ast::Variant>],
4623 hint: attr::ReprAttr)
4624 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4627 let rty = ty::node_id_to_type(ccx.tcx, id);
4628 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4629 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4630 let mut prev_disr_val: Option<ty::Disr> = None;
4634 // If the discriminant value is specified explicitly in the enum check whether the
4635 // initialization expression is valid, otherwise use the last value plus one.
4636 let mut current_disr_val = match prev_disr_val {
4637 Some(prev_disr_val) => {
4638 if let Some(v) = prev_disr_val.checked_add(1) {
4641 ty::INITIAL_DISCRIMINANT_VALUE
4644 None => ty::INITIAL_DISCRIMINANT_VALUE
4647 match v.node.disr_expr {
4649 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4651 let inh = static_inherited_fields(ccx);
4652 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4653 let declty = match hint {
4654 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4655 attr::ReprInt(_, attr::SignedInt(ity)) => {
4656 ty::mk_mach_int(fcx.tcx(), ity)
4658 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4659 ty::mk_mach_uint(fcx.tcx(), ity)
4662 check_const_with_ty(&fcx, e.span, &**e, declty);
4663 // check_expr (from check_const pass) doesn't guarantee
4664 // that the expression is in a form that eval_const_expr can
4665 // handle, so we may still get an internal compiler error
4667 match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
4668 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4669 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4671 span_err!(ccx.tcx.sess, e.span, E0079,
4672 "expected signed integer constant");
4675 span_err!(ccx.tcx.sess, err.span, E0080,
4676 "constant evaluation error: {}",
4684 // Check for duplicate discriminant values
4685 match disr_vals.iter().position(|&x| x == current_disr_val) {
4687 span_err!(ccx.tcx.sess, v.span, E0081,
4688 "discriminant value `{}` already exists", disr_vals[i]);
4689 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4690 "conflicting discriminant here")
4694 // Check for unrepresentable discriminant values
4696 attr::ReprAny | attr::ReprExtern => (),
4697 attr::ReprInt(sp, ity) => {
4698 if !disr_in_range(ccx, ity, current_disr_val) {
4699 span_err!(ccx.tcx.sess, v.span, E0082,
4700 "discriminant value outside specified type");
4701 span_note!(ccx.tcx.sess, sp,
4702 "discriminant type specified here");
4705 attr::ReprPacked => {
4706 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4709 disr_vals.push(current_disr_val);
4711 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4713 prev_disr_val = Some(current_disr_val);
4715 variants.push(variant_info);
4721 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4722 .get(0).unwrap_or(&attr::ReprAny);
4724 if hint != attr::ReprAny && vs.len() <= 1 {
4726 span_err!(ccx.tcx.sess, sp, E0083,
4727 "unsupported representation for univariant enum");
4729 span_err!(ccx.tcx.sess, sp, E0084,
4730 "unsupported representation for zero-variant enum");
4734 let variants = do_check(ccx, vs, id, hint);
4736 // cache so that ty::enum_variants won't repeat this work
4737 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4739 check_representable(ccx.tcx, sp, id, "enum");
4741 // Check that it is possible to instantiate this enum:
4743 // This *sounds* like the same that as representable, but it's
4744 // not. See def'n of `check_instantiable()` for details.
4745 check_instantiable(ccx.tcx, sp, id);
4748 // Returns the type parameter count and the type for the given definition.
4749 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4752 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4754 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4755 let typ = fcx.local_ty(sp, nid);
4756 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4757 ty::GenericPredicates::empty())
4759 def::DefFn(id, _) | def::DefMethod(id, _) |
4760 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4761 def::DefStruct(id) | def::DefConst(id) => {
4762 (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4766 def::DefAssociatedTy(..) |
4768 def::DefTyParam(..) |
4770 def::DefForeignMod(..) |
4772 def::DefRegion(..) |
4774 def::DefSelfTy(..) => {
4775 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4780 // Instantiates the given path, which must refer to an item with the given
4781 // number of type parameters and type.
4782 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4783 segments: &[ast::PathSegment],
4784 type_scheme: TypeScheme<'tcx>,
4785 type_predicates: &ty::GenericPredicates<'tcx>,
4786 opt_self_ty: Option<Ty<'tcx>>,
4789 node_id: ast::NodeId) {
4790 debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
4792 def.repr(fcx.tcx()),
4794 type_scheme.repr(fcx.tcx()));
4796 // We need to extract the type parameters supplied by the user in
4797 // the path `path`. Due to the current setup, this is a bit of a
4798 // tricky-process; the problem is that resolve only tells us the
4799 // end-point of the path resolution, and not the intermediate steps.
4800 // Luckily, we can (at least for now) deduce the intermediate steps
4801 // just from the end-point.
4803 // There are basically three cases to consider:
4805 // 1. Reference to a *type*, such as a struct or enum:
4807 // mod a { struct Foo<T> { ... } }
4809 // Because we don't allow types to be declared within one
4810 // another, a path that leads to a type will always look like
4811 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4812 // that only the final segment can have type parameters, and
4813 // they are located in the TypeSpace.
4815 // *Note:* Generally speaking, references to types don't
4816 // actually pass through this function, but rather the
4817 // `ast_ty_to_ty` function in `astconv`. However, in the case
4818 // of struct patterns (and maybe literals) we do invoke
4819 // `instantiate_path` to get the general type of an instance of
4820 // a struct. (In these cases, there are actually no type
4821 // parameters permitted at present, but perhaps we will allow
4822 // them in the future.)
4824 // 1b. Reference to a enum variant or tuple-like struct:
4826 // struct foo<T>(...)
4827 // enum E<T> { foo(...) }
4829 // In these cases, the parameters are declared in the type
4832 // 2. Reference to a *fn item*:
4836 // In this case, the path will again always have the form
4837 // `a::b::foo::<T>` where only the final segment should have
4838 // type parameters. However, in this case, those parameters are
4839 // declared on a value, and hence are in the `FnSpace`.
4841 // 3. Reference to a *method*:
4843 // impl<A> SomeStruct<A> {
4847 // Here we can have a path like
4848 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4849 // may appear in two places. The penultimate segment,
4850 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4851 // final segment, `foo::<B>` contains parameters in fn space.
4853 // The first step then is to categorize the segments appropriately.
4855 assert!(segments.len() >= 1);
4857 let mut ufcs_method = None;
4858 let mut segment_spaces: Vec<_>;
4860 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4861 def::DefSelfTy(..) |
4862 def::DefStruct(..) |
4863 def::DefVariant(..) |
4865 def::DefAssociatedTy(..) |
4867 def::DefPrimTy(..) |
4868 def::DefTyParam(..) => {
4869 // Everything but the final segment should have no
4870 // parameters at all.
4871 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4872 segment_spaces.push(Some(subst::TypeSpace));
4875 // Case 2. Reference to a top-level value.
4878 def::DefStatic(..) => {
4879 segment_spaces = repeat(None).take(segments.len() - 1).collect();
4880 segment_spaces.push(Some(subst::FnSpace));
4883 // Case 3. Reference to a method.
4884 def::DefMethod(_, provenance) => {
4886 def::FromTrait(trait_did) => {
4887 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4889 def::FromImpl(_) => {}
4892 if segments.len() >= 2 {
4893 segment_spaces = repeat(None).take(segments.len() - 2).collect();
4894 segment_spaces.push(Some(subst::TypeSpace));
4895 segment_spaces.push(Some(subst::FnSpace));
4897 // `<T>::method` will end up here, and so can `T::method`.
4898 let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
4899 segment_spaces = vec![Some(subst::FnSpace)];
4900 ufcs_method = Some((provenance, self_ty));
4904 // Other cases. Various nonsense that really shouldn't show up
4905 // here. If they do, an error will have been reported
4906 // elsewhere. (I hope)
4908 def::DefForeignMod(..) |
4911 def::DefRegion(..) |
4913 def::DefUpvar(..) => {
4914 segment_spaces = repeat(None).take(segments.len()).collect();
4917 assert_eq!(segment_spaces.len(), segments.len());
4919 // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
4920 // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
4921 // type parameters are not mandatory.
4922 let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
4924 debug!("segment_spaces={:?}", segment_spaces);
4926 // Next, examine the definition, and determine how many type
4927 // parameters we expect from each space.
4928 let type_defs = &type_scheme.generics.types;
4929 let region_defs = &type_scheme.generics.regions;
4931 // Now that we have categorized what space the parameters for each
4932 // segment belong to, let's sort out the parameters that the user
4933 // provided (if any) into their appropriate spaces. We'll also report
4934 // errors if type parameters are provided in an inappropriate place.
4935 let mut substs = Substs::empty();
4936 for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
4939 check_path_args(fcx.tcx(), slice::ref_slice(segment),
4940 NO_TPS | NO_REGIONS);
4944 push_explicit_parameters_from_segment_to_substs(fcx,
4954 if let Some(self_ty) = opt_self_ty {
4955 if type_defs.len(subst::SelfSpace) == 1 {
4956 substs.types.push(subst::SelfSpace, self_ty);
4960 // Now we have to compare the types that the user *actually*
4961 // provided against the types that were *expected*. If the user
4962 // did not provide any types, then we want to substitute inference
4963 // variables. If the user provided some types, we may still need
4964 // to add defaults. If the user provided *too many* types, that's
4966 for &space in &ParamSpace::all() {
4967 adjust_type_parameters(fcx, span, space, type_defs,
4968 require_type_space, &mut substs);
4969 assert_eq!(substs.types.len(space), type_defs.len(space));
4971 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4972 assert_eq!(substs.regions().len(space), region_defs.len(space));
4975 // The things we are substituting into the type should not contain
4976 // escaping late-bound regions, and nor should the base type scheme.
4977 assert!(!substs.has_regions_escaping_depth(0));
4978 assert!(!type_scheme.has_escaping_regions());
4980 // Add all the obligations that are required, substituting and
4981 // normalized appropriately.
4982 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4983 fcx.add_obligations_for_parameters(
4984 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4987 // Substitute the values for the type parameters into the type of
4988 // the referenced item.
4989 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4992 if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
4993 // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
4994 // is inherent, there is no `Self` parameter, instead, the impl needs
4995 // type parameters, which we can infer by unifying the provided `Self`
4996 // with the substituted impl type.
4997 let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
4998 assert_eq!(substs.types.len(subst::TypeSpace),
4999 impl_scheme.generics.types.len(subst::TypeSpace));
5000 assert_eq!(substs.regions().len(subst::TypeSpace),
5001 impl_scheme.generics.regions.len(subst::TypeSpace));
5003 let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
5004 if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
5005 fcx.tcx().sess.span_bug(span,
5007 "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
5008 self_ty.repr(fcx.tcx()),
5009 impl_ty.repr(fcx.tcx())));
5013 fcx.write_ty(node_id, ty_substituted);
5014 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
5017 /// Finds the parameters that the user provided and adds them to `substs`. If too many
5018 /// parameters are provided, then reports an error and clears the output vector.
5020 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
5021 /// use inference variables. This seems less likely to lead to derived errors.
5023 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
5024 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
5025 /// here because we can easily use the precise span of the N+1'th parameter.
5026 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
5027 fcx: &FnCtxt<'a, 'tcx>,
5028 space: subst::ParamSpace,
5030 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5031 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5032 segment: &ast::PathSegment,
5033 substs: &mut Substs<'tcx>)
5035 match segment.parameters {
5036 ast::AngleBracketedParameters(ref data) => {
5037 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
5038 fcx, space, type_defs, region_defs, data, substs);
5041 ast::ParenthesizedParameters(ref data) => {
5042 span_err!(fcx.tcx().sess, span, E0238,
5043 "parenthesized parameters may only be used with a trait");
5044 push_explicit_parenthesized_parameters_from_segment_to_substs(
5045 fcx, space, span, type_defs, data, substs);
5050 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
5051 fcx: &FnCtxt<'a, 'tcx>,
5052 space: subst::ParamSpace,
5053 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5054 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5055 data: &ast::AngleBracketedParameterData,
5056 substs: &mut Substs<'tcx>)
5059 let type_count = type_defs.len(space);
5060 assert_eq!(substs.types.len(space), 0);
5061 for (i, typ) in data.types.iter().enumerate() {
5062 let t = fcx.to_ty(&**typ);
5064 substs.types.push(space, t);
5065 } else if i == type_count {
5066 span_err!(fcx.tcx().sess, typ.span, E0087,
5067 "too many type parameters provided: \
5068 expected at most {} parameter(s), \
5069 found {} parameter(s)",
5070 type_count, data.types.len());
5071 substs.types.truncate(space, 0);
5077 if data.bindings.len() > 0 {
5078 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
5079 "unexpected binding of associated item in expression path \
5080 (only allowed in type paths)");
5084 let region_count = region_defs.len(space);
5085 assert_eq!(substs.regions().len(space), 0);
5086 for (i, lifetime) in data.lifetimes.iter().enumerate() {
5087 let r = ast_region_to_region(fcx.tcx(), lifetime);
5088 if i < region_count {
5089 substs.mut_regions().push(space, r);
5090 } else if i == region_count {
5091 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5092 "too many lifetime parameters provided: \
5093 expected {} parameter(s), found {} parameter(s)",
5095 data.lifetimes.len());
5096 substs.mut_regions().truncate(space, 0);
5104 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
5105 /// but intended for `Foo(A,B) -> C` form. This expands to
5106 /// roughly the same thing as `Foo<(A,B),C>`. One important
5107 /// difference has to do with the treatment of anonymous
5108 /// regions, which are translated into bound regions (NYI).
5109 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
5110 fcx: &FnCtxt<'a, 'tcx>,
5111 space: subst::ParamSpace,
5113 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5114 data: &ast::ParenthesizedParameterData,
5115 substs: &mut Substs<'tcx>)
5117 let type_count = type_defs.len(space);
5119 span_err!(fcx.tcx().sess, span, E0167,
5120 "parenthesized form always supplies 2 type parameters, \
5121 but only {} parameter(s) were expected",
5125 let input_tys: Vec<Ty> =
5126 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
5129 ty::mk_tup(fcx.tcx(), input_tys);
5131 if type_count >= 1 {
5132 substs.types.push(space, tuple_ty);
5135 let output_ty: Option<Ty> =
5136 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
5139 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
5141 if type_count >= 2 {
5142 substs.types.push(space, output_ty);
5146 fn adjust_type_parameters<'a, 'tcx>(
5147 fcx: &FnCtxt<'a, 'tcx>,
5150 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5151 require_type_space: bool,
5152 substs: &mut Substs<'tcx>)
5154 let provided_len = substs.types.len(space);
5155 let desired = defs.get_slice(space);
5156 let required_len = desired.iter()
5157 .take_while(|d| d.default.is_none())
5160 debug!("adjust_type_parameters(space={:?}, \
5169 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5170 assert!(provided_len <= desired.len());
5172 // Nothing specified at all: supply inference variables for
5174 if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
5175 substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
5179 // Too few parameters specified: report an error and use Err
5181 if provided_len < required_len {
5183 if desired.len() != required_len { "at least " } else { "" };
5184 span_err!(fcx.tcx().sess, span, E0089,
5185 "too few type parameters provided: expected {}{} parameter(s) \
5186 , found {} parameter(s)",
5187 qualifier, required_len, provided_len);
5188 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5192 // Otherwise, add in any optional parameters that the user
5193 // omitted. The case of *too many* parameters is handled
5195 // push_explicit_parameters_from_segment_to_substs(). Note
5196 // that the *default* type are expressed in terms of all prior
5197 // parameters, so we have to substitute as we go with the
5198 // partial substitution that we have built up.
5199 for i in provided_len..desired.len() {
5200 let default = desired[i].default.unwrap();
5201 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5202 substs.types.push(space, default);
5204 assert_eq!(substs.types.len(space), desired.len());
5206 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5209 fn adjust_region_parameters(
5213 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5214 substs: &mut Substs)
5216 let provided_len = substs.mut_regions().len(space);
5217 let desired = defs.get_slice(space);
5219 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5220 assert!(provided_len <= desired.len());
5222 // If nothing was provided, just use inference variables.
5223 if provided_len == 0 {
5224 substs.mut_regions().replace(
5226 fcx.infcx().region_vars_for_defs(span, desired));
5230 // If just the right number were provided, everybody is happy.
5231 if provided_len == desired.len() {
5235 // Otherwise, too few were provided. Report an error and then
5236 // use inference variables.
5237 span_err!(fcx.tcx().sess, span, E0090,
5238 "too few lifetime parameters provided: expected {} parameter(s), \
5239 found {} parameter(s)",
5240 desired.len(), provided_len);
5242 substs.mut_regions().replace(
5244 fcx.infcx().region_vars_for_defs(span, desired));
5248 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
5252 where F: Fn() -> Ty<'tcx>
5254 let mut ty = fcx.resolve_type_vars_if_possible(ty);
5256 if ty::type_is_ty_var(ty) {
5257 let alternative = f();
5260 if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
5261 fcx.type_error_message(sp, |_actual| {
5262 "the type of this value must be known in this context".to_string()
5264 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5265 ty = fcx.tcx().types.err;
5267 demand::suptype(fcx, sp, alternative, ty);
5275 // Resolves `typ` by a single level if `typ` is a type variable. If no
5276 // resolution is possible, then an error is reported.
5277 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5282 structurally_resolve_type_or_else(fcx, sp, ty, || {
5287 // Returns true if b contains a break that can exit from b
5288 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5289 // First: is there an unlabeled break immediately
5291 (loop_query(&*b, |e| {
5293 ast::ExprBreak(None) => true,
5297 // Second: is there a labeled break with label
5298 // <id> nested anywhere inside the loop?
5299 (block_query(b, |e| {
5300 if let ast::ExprBreak(Some(_)) = e.node {
5301 lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
5308 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5310 tps: &OwnedSlice<ast::TyParam>,
5312 debug!("check_bounds_are_used(n_tps={}, ty={})",
5313 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5315 // make a vector of booleans initially false, set to true when used
5316 if tps.len() == 0 { return; }
5317 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5319 ty::walk_ty(ty, |t| {
5321 ty::ty_param(ParamTy {idx, ..}) => {
5322 debug!("Found use of ty param num {}", idx);
5323 tps_used[idx as uint] = true;
5329 for (i, b) in tps_used.iter().enumerate() {
5331 span_err!(ccx.tcx.sess, span, E0091,
5332 "type parameter `{}` is unused",
5333 token::get_ident(tps[i].ident));
5338 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5339 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5340 let name = token::intern(&format!("P{}", n));
5341 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5345 let name = token::get_ident(it.ident);
5346 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5347 let split : Vec<&str> = name.split('_').collect();
5348 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5350 //We only care about the operation here
5351 let (n_tps, inputs, output) = match split[1] {
5352 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5356 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5358 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5361 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5362 "min" | "umax" | "umin" => {
5363 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5367 (0, Vec::new(), ty::mk_nil(tcx))
5370 span_err!(tcx.sess, it.span, E0092,
5371 "unrecognized atomic operation function: `{}`", op);
5375 (n_tps, inputs, ty::FnConverging(output))
5376 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5377 (0, Vec::new(), ty::FnDiverging)
5379 let (n_tps, inputs, output) = match &name[..] {
5380 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5382 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.uint),
5383 "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
5384 "uninit" => (1, Vec::new(), param(ccx, 0)),
5385 "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5386 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5387 "move_val_init" => {
5390 ty::mk_mut_rptr(tcx,
5391 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5398 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5399 "owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
5401 "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
5402 ast::MutImmutable)),
5403 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5407 ty::mk_ptr(tcx, ty::mt {
5409 mutbl: ast::MutImmutable
5413 ty::mk_ptr(tcx, ty::mt {
5415 mutbl: ast::MutImmutable
5418 "copy" | "copy_nonoverlapping" |
5419 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5422 ty::mk_ptr(tcx, ty::mt {
5424 mutbl: ast::MutMutable
5426 ty::mk_ptr(tcx, ty::mt {
5428 mutbl: ast::MutImmutable
5434 "write_bytes" | "volatile_set_memory" => {
5437 ty::mk_ptr(tcx, ty::mt {
5439 mutbl: ast::MutMutable
5446 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5447 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5450 vec!( tcx.types.f32, tcx.types.i32 ),
5455 vec!( tcx.types.f64, tcx.types.i32 ),
5458 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5459 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5460 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5461 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5464 vec!( tcx.types.f32, tcx.types.f32 ),
5469 vec!( tcx.types.f64, tcx.types.f64 ),
5472 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5473 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5474 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5475 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5476 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5477 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5478 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5479 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5480 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5481 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5484 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5489 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5492 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5493 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5494 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5495 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5496 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5497 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5498 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5499 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5500 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5501 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5502 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5503 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5504 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5505 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5506 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5507 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5508 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5509 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5510 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5511 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5512 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5513 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5514 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5515 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5516 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5517 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5518 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5519 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5520 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5521 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5522 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5525 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5527 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5529 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5530 (0, vec!(tcx.types.i8, tcx.types.i8),
5531 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5533 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5534 (0, vec!(tcx.types.i16, tcx.types.i16),
5535 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5537 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5538 (0, vec!(tcx.types.i32, tcx.types.i32),
5539 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5541 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5542 (0, vec!(tcx.types.i64, tcx.types.i64),
5543 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5545 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5546 (0, vec!(tcx.types.u8, tcx.types.u8),
5547 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5549 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5550 (0, vec!(tcx.types.u16, tcx.types.u16),
5551 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5553 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5554 (0, vec!(tcx.types.u32, tcx.types.u32),
5555 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5557 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5558 (0, vec!(tcx.types.u64, tcx.types.u64),
5559 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5561 "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
5562 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
5564 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5566 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5569 span_err!(tcx.sess, it.span, E0093,
5570 "unrecognized intrinsic function: `{}`", *other);
5574 (n_tps, inputs, ty::FnConverging(output))
5576 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5577 unsafety: ast::Unsafety::Unsafe,
5578 abi: abi::RustIntrinsic,
5579 sig: ty::Binder(FnSig {
5585 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5586 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5587 if i_n_tps != n_tps {
5588 span_err!(tcx.sess, it.span, E0094,
5589 "intrinsic has wrong number of type \
5590 parameters: found {}, expected {}",
5593 require_same_types(tcx,
5600 format!("intrinsic has wrong type: expected `{}`",
5601 ppaux::ty_to_string(ccx.tcx, fty))