1 // Copyright 2012-2014 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 use self::IsBinopAssignment::*;
82 use self::TupleArgumentsFlag::*;
84 use astconv::{mod, ast_region_to_region, ast_ty_to_ty, AstConv};
85 use check::_match::pat_ctxt;
86 use middle::{const_eval, def};
88 use middle::lang_items::IteratorItem;
89 use middle::mem_categorization as mc;
90 use middle::mem_categorization::McResult;
91 use middle::pat_util::{mod, pat_id_map};
92 use middle::region::CodeExtent;
93 use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace};
95 use middle::ty::{FnSig, VariantInfo, TypeScheme};
96 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
97 use middle::ty::{mod, HasProjectionTypes, RegionEscape, Ty};
98 use middle::ty::liberate_late_bound_regions;
99 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
100 use middle::ty_fold::{TypeFolder, TypeFoldable};
101 use rscope::RegionScope;
102 use session::Session;
103 use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
105 use middle::lang_items::TypeIdLangItem;
107 use util::common::{block_query, indenter, loop_query};
108 use util::ppaux::{mod, UserString, Repr};
109 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
111 use std::cell::{Cell, Ref, RefCell};
112 use std::mem::replace;
114 use std::iter::repeat;
115 use syntax::{mod, abi, attr};
116 use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
117 use syntax::ast_util::{mod, local_def, PostExpansionMethod};
118 use syntax::codemap::{mod, Span};
119 use syntax::owned_slice::OwnedSlice;
120 use syntax::parse::token;
121 use syntax::print::pprust;
123 use syntax::visit::{mod, Visitor};
138 /// Fields that are part of a `FnCtxt` which are inherited by
139 /// closures defined within the function. For example:
142 /// bar(move|| { ... })
145 /// Here, the function `foo()` and the closure passed to
146 /// `bar()` will each have their own `FnCtxt`, but they will
147 /// share the inherited fields.
148 pub struct Inherited<'a, 'tcx: 'a> {
149 infcx: infer::InferCtxt<'a, 'tcx>,
150 locals: RefCell<NodeMap<Ty<'tcx>>>,
151 param_env: ty::ParameterEnvironment<'a, 'tcx>,
154 node_types: RefCell<NodeMap<Ty<'tcx>>>,
155 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
156 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
157 method_map: MethodMap<'tcx>,
158 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
159 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
160 object_cast_map: ObjectCastMap<'tcx>,
162 // A mapping from each fn's id to its signature, with all bound
163 // regions replaced with free ones. Unlike the other tables, this
164 // one is never copied into the tcx: it is only used by regionck.
165 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
167 // Tracks trait obligations incurred during this function body.
168 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
171 /// When type-checking an expression, we propagate downward
172 /// whatever type hint we are able in the form of an `Expectation`.
174 enum Expectation<'tcx> {
175 /// We know nothing about what type this expression should have.
178 /// This expression should have the type given (or some subtype)
179 ExpectHasType(Ty<'tcx>),
181 /// This expression will be cast to the `Ty`
182 ExpectCastableToType(Ty<'tcx>),
184 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
185 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
186 ExpectRvalueLikeUnsized(Ty<'tcx>),
189 impl<'tcx> Expectation<'tcx> {
190 // Disregard "castable to" expectations because they
191 // can lead us astray. Consider for example `if cond
192 // {22} else {c} as u8` -- if we propagate the
193 // "castable to u8" constraint to 22, it will pick the
194 // type 22u8, which is overly constrained (c might not
195 // be a u8). In effect, the problem is that the
196 // "castable to" expectation is not the tightest thing
197 // we can say, so we want to drop it in this case.
198 // The tightest thing we can say is "must unify with
199 // else branch". Note that in the case of a "has type"
200 // constraint, this limitation does not hold.
202 // If the expected type is just a type variable, then don't use
203 // an expected type. Otherwise, we might write parts of the type
204 // when checking the 'then' block which are incompatible with the
206 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
208 ExpectHasType(ety) => {
209 let ety = fcx.infcx().shallow_resolve(ety);
210 if !ty::type_is_ty_var(ety) {
216 ExpectRvalueLikeUnsized(ety) => {
217 ExpectRvalueLikeUnsized(ety)
224 #[deriving(Copy, Clone)]
225 pub struct UnsafetyState {
226 pub def: ast::NodeId,
227 pub unsafety: ast::Unsafety,
232 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
233 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
236 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
237 match self.unsafety {
238 // If this unsafe, then if the outer function was already marked as
239 // unsafe we shouldn't attribute the unsafe'ness to the block. This
240 // way the block can be warned about instead of ignoring this
241 // extraneous block (functions are never warned about).
242 ast::Unsafety::Unsafe if self.from_fn => *self,
245 let (unsafety, def) = match blk.rules {
246 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
247 ast::DefaultBlock => (unsafety, self.def),
249 UnsafetyState{ def: def,
257 /// Whether `check_binop` is part of an assignment or not.
258 /// Used to know whether we allow user overloads and to print
259 /// better messages on error.
260 #[deriving(PartialEq)]
261 enum IsBinopAssignment{
267 pub struct FnCtxt<'a, 'tcx: 'a> {
268 body_id: ast::NodeId,
270 // This flag is set to true if, during the writeback phase, we encounter
271 // a type error in this function.
272 writeback_errors: Cell<bool>,
274 // Number of errors that had been reported when we started
275 // checking this function. On exit, if we find that *more* errors
276 // have been reported, we will skip regionck and other work that
277 // expects the types within the function to be consistent.
278 err_count_on_creation: uint,
280 ret_ty: ty::FnOutput<'tcx>,
282 ps: RefCell<UnsafetyState>,
284 inh: &'a Inherited<'a, 'tcx>,
286 ccx: &'a CrateCtxt<'a, 'tcx>,
289 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
290 fn tcx(&self) -> &ty::ctxt<'tcx> {
293 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
294 let ty = self.node_ty(id);
295 self.resolve_type_vars_or_error(&ty)
297 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
298 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
299 self.resolve_type_vars_or_error(&ty)
301 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
302 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
303 traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
305 fn node_method_ty(&self, method_call: ty::MethodCall)
306 -> Option<Ty<'tcx>> {
307 self.inh.method_map.borrow()
309 .map(|method| method.ty)
310 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
312 fn node_method_origin(&self, method_call: ty::MethodCall)
313 -> Option<ty::MethodOrigin<'tcx>>
315 self.inh.method_map.borrow()
317 .map(|method| method.origin.clone())
319 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
320 &self.inh.adjustments
322 fn is_method_call(&self, id: ast::NodeId) -> bool {
323 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
325 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
326 self.param_env().temporary_scope(rvalue_id)
328 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
329 self.inh.upvar_borrow_map.borrow().get(&upvar_id).cloned()
331 fn capture_mode(&self, closure_expr_id: ast::NodeId)
332 -> ast::CaptureClause {
333 self.ccx.tcx.capture_mode(closure_expr_id)
337 impl<'a, 'tcx> ty::UnboxedClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
338 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
342 fn unboxed_closure_kind(&self,
344 -> ty::UnboxedClosureKind
346 self.inh.unboxed_closures.borrow()[def_id].kind
349 fn unboxed_closure_type(&self,
351 substs: &subst::Substs<'tcx>)
352 -> ty::ClosureTy<'tcx>
354 self.inh.unboxed_closures.borrow()[def_id].closure_type.subst(self.tcx(), substs)
357 fn unboxed_closure_upvars(&self,
359 substs: &Substs<'tcx>)
360 -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
362 ty::unboxed_closure_upvars(self, def_id, substs)
366 impl<'a, 'tcx> Inherited<'a, 'tcx> {
367 fn new(tcx: &'a ty::ctxt<'tcx>,
368 param_env: ty::ParameterEnvironment<'a, 'tcx>)
369 -> Inherited<'a, 'tcx> {
371 infcx: infer::new_infer_ctxt(tcx),
372 locals: RefCell::new(NodeMap::new()),
373 param_env: param_env,
374 node_types: RefCell::new(NodeMap::new()),
375 item_substs: RefCell::new(NodeMap::new()),
376 adjustments: RefCell::new(NodeMap::new()),
377 method_map: RefCell::new(FnvHashMap::new()),
378 object_cast_map: RefCell::new(NodeMap::new()),
379 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
380 unboxed_closures: RefCell::new(DefIdMap::new()),
381 fn_sig_map: RefCell::new(NodeMap::new()),
382 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
386 fn normalize_associated_types_in<T>(&self,
387 typer: &ty::UnboxedClosureTyper<'tcx>,
389 body_id: ast::NodeId,
392 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
394 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
395 assoc::normalize_associated_types_in(&self.infcx,
397 &mut *fulfillment_cx, span,
404 // Used by check_const and check_enum_variants
405 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
406 inh: &'a Inherited<'a, 'tcx>,
407 rty: ty::FnOutput<'tcx>,
408 body_id: ast::NodeId)
409 -> FnCtxt<'a, 'tcx> {
412 writeback_errors: Cell::new(false),
413 err_count_on_creation: ccx.tcx.sess.err_count(),
415 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
421 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
422 -> Inherited<'a, 'tcx> {
423 // It's kind of a kludge to manufacture a fake function context
424 // and statement context, but we might as well do write the code only once
425 let param_env = ty::empty_parameter_environment(ccx.tcx);
426 Inherited::new(ccx.tcx, param_env)
429 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
431 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
432 fn visit_item(&mut self, i: &ast::Item) {
433 check_item(self.ccx, i);
434 visit::walk_item(self, i);
437 fn visit_ty(&mut self, t: &ast::Ty) {
439 ast::TyFixedLengthVec(_, ref expr) => {
440 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
445 visit::walk_ty(self, t);
449 pub fn check_item_types(ccx: &CrateCtxt) {
450 let krate = ccx.tcx.map.krate();
451 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
452 visit::walk_crate(&mut visit, krate);
454 // If types are not well-formed, it leads to all manner of errors
455 // downstream, so stop reporting errors at this point.
456 ccx.tcx.sess.abort_if_errors();
458 let mut visit = CheckItemTypesVisitor { ccx: ccx };
459 visit::walk_crate(&mut visit, krate);
461 ccx.tcx.sess.abort_if_errors();
464 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
469 param_env: ty::ParameterEnvironment<'a, 'tcx>) {
471 ty::ty_bare_fn(_, ref fn_ty) => {
472 let inh = Inherited::new(ccx.tcx, param_env);
474 // Compute the fty from point of view of inside fn.
476 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
478 liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig);
480 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
482 let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
483 decl, id, body, &inh);
485 vtable::select_all_fcx_obligations_or_error(&fcx);
486 upvar::closure_analyze_fn(&fcx, id, decl, body);
487 regionck::regionck_fn(&fcx, id, decl, body);
488 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
490 _ => ccx.tcx.sess.impossible_case(body.span,
491 "check_bare_fn: function type expected")
495 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
496 fcx: &'a FnCtxt<'a, 'tcx>
499 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
500 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
503 // infer the variable's type
504 let var_ty = self.fcx.infcx().next_ty_var();
505 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
509 // take type that the user specified
510 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
517 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
518 // Add explicitly-declared locals.
519 fn visit_local(&mut self, local: &ast::Local) {
520 let o_ty = match local.ty {
521 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
524 self.assign(local.span, local.id, o_ty);
525 debug!("Local variable {} is assigned type {}",
526 self.fcx.pat_to_string(&*local.pat),
527 self.fcx.infcx().ty_to_string(
528 self.fcx.inh.locals.borrow()[local.id].clone()));
529 visit::walk_local(self, local);
532 // Add pattern bindings.
533 fn visit_pat(&mut self, p: &ast::Pat) {
534 if let ast::PatIdent(_, ref path1, _) = p.node {
535 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
536 let var_ty = self.assign(p.span, p.id, None);
538 self.fcx.require_type_is_sized(var_ty, p.span,
539 traits::VariableType(p.id));
541 debug!("Pattern binding {} is assigned to {} with type {}",
542 token::get_ident(path1.node),
543 self.fcx.infcx().ty_to_string(
544 self.fcx.inh.locals.borrow()[p.id].clone()),
545 var_ty.repr(self.fcx.tcx()));
548 visit::walk_pat(self, p);
551 fn visit_block(&mut self, b: &ast::Block) {
552 // non-obvious: the `blk` variable maps to region lb, so
553 // we have to keep this up-to-date. This
554 // is... unfortunate. It'd be nice to not need this.
555 visit::walk_block(self, b);
558 // Since an expr occurs as part of the type fixed size arrays we
559 // need to record the type for that node
560 fn visit_ty(&mut self, t: &ast::Ty) {
562 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
563 self.visit_ty(&**ty);
564 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
566 _ => visit::walk_ty(self, t)
570 // Don't descend into fns and items
571 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
572 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
573 fn visit_item(&mut self, _: &ast::Item) { }
577 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
578 /// body and returns the function context used for that purpose, since in the case of a fn item
579 /// there is still a bit more to do.
582 /// * inherited: other fields inherited from the enclosing fn (if any)
583 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
584 unsafety: ast::Unsafety,
585 unsafety_id: ast::NodeId,
586 fn_sig: &ty::FnSig<'tcx>,
590 inherited: &'a Inherited<'a, 'tcx>)
594 let err_count_on_creation = tcx.sess.err_count();
596 let arg_tys = fn_sig.inputs[];
597 let ret_ty = fn_sig.output;
599 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
604 // Create the function context. This is either derived from scratch or,
605 // in the case of function expressions, based on the outer context.
608 writeback_errors: Cell::new(false),
609 err_count_on_creation: err_count_on_creation,
611 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
616 // Remember return type so that regionck can access it later.
617 let mut fn_sig_tys: Vec<Ty> =
622 if let ty::FnConverging(ret_ty) = ret_ty {
623 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
624 fn_sig_tys.push(ret_ty);
627 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
629 fn_sig_tys.repr(tcx));
631 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
634 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
636 // Add formal parameters.
637 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
638 // Create type variables for each argument.
639 pat_util::pat_bindings(
642 |_bm, pat_id, sp, _path| {
643 let var_ty = visit.assign(sp, pat_id, None);
644 fcx.require_type_is_sized(var_ty, sp,
645 traits::VariableType(pat_id));
648 // Check the pattern.
651 map: pat_id_map(&tcx.def_map, &*input.pat),
653 _match::check_pat(&pcx, &*input.pat, *arg_ty);
656 visit.visit_block(body);
659 check_block_with_expected(&fcx, body, match ret_ty {
660 ty::FnConverging(result_type) => ExpectHasType(result_type),
661 ty::FnDiverging => NoExpectation
664 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
665 fcx.write_ty(input.id, *arg);
671 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
674 check_representable(tcx, span, id, "struct");
675 check_instantiable(tcx, span, id);
677 if ty::lookup_simd(tcx, local_def(id)) {
678 check_simd(tcx, span, id);
682 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
683 debug!("check_item(it.id={}, it.ident={})",
685 ty::item_path_str(ccx.tcx, local_def(it.id)));
686 let _indenter = indenter();
689 ast::ItemStatic(_, _, ref e) |
690 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
691 ast::ItemEnum(ref enum_definition, _) => {
692 check_enum_variants(ccx,
694 enum_definition.variants[],
697 ast::ItemFn(ref decl, _, _, _, ref body) => {
698 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
699 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
700 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
702 ast::ItemImpl(_, _, _, _, ref impl_items) => {
703 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
705 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
707 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
708 Some(impl_trait_ref) => {
709 check_impl_items_against_trait(ccx,
712 impl_items.as_slice());
717 for impl_item in impl_items.iter() {
719 ast::MethodImplItem(ref m) => {
720 check_method_body(ccx, &impl_pty.generics, &**m);
722 ast::TypeImplItem(_) => {
723 // Nothing to do here.
729 ast::ItemTrait(_, _, _, ref trait_methods) => {
730 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
731 for trait_method in trait_methods.iter() {
732 match *trait_method {
733 RequiredMethod(..) => {
734 // Nothing to do, since required methods don't have
737 ProvidedMethod(ref m) => {
738 check_method_body(ccx, &trait_def.generics, &**m);
740 TypeTraitItem(_) => {
746 ast::ItemStruct(..) => {
747 check_struct(ccx, it.id, it.span);
749 ast::ItemTy(ref t, ref generics) => {
750 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
751 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
753 ast::ItemForeignMod(ref m) => {
754 if m.abi == abi::RustIntrinsic {
755 for item in m.items.iter() {
756 check_intrinsic_type(ccx, &**item);
759 for item in m.items.iter() {
760 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
761 if !pty.generics.types.is_empty() {
762 span_err!(ccx.tcx.sess, item.span, E0044,
763 "foreign items may not have type parameters");
766 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
767 if fn_decl.variadic && m.abi != abi::C {
768 span_err!(ccx.tcx.sess, item.span, E0045,
769 "variadic function must have C calling convention");
775 _ => {/* nothing to do */ }
779 /// Type checks a method body.
783 /// * `item_generics`: generics defined on the impl/trait that contains
785 /// * `self_bound`: bound for the `Self` type parameter, if any
786 /// * `method`: the method definition
787 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
788 item_generics: &ty::Generics<'tcx>,
789 method: &ast::Method) {
790 debug!("check_method_body(item_generics={}, method.id={})",
791 item_generics.repr(ccx.tcx),
793 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
795 let fty = ty::node_id_to_type(ccx.tcx, method.id);
796 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
799 &*method.pe_fn_decl(),
806 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
808 impl_trait_ref: &ty::TraitRef<'tcx>,
809 impl_items: &[ast::ImplItem]) {
810 // Locate trait methods
812 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
814 // Check existing impl methods to see if they are both present in trait
815 // and compatible with trait signature
816 for impl_item in impl_items.iter() {
818 ast::MethodImplItem(ref impl_method) => {
819 let impl_method_def_id = local_def(impl_method.id);
820 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
823 // If this is an impl of a trait method, find the
824 // corresponding method definition in the trait.
825 let opt_trait_method_ty =
827 .find(|ti| ti.name() == impl_item_ty.name());
828 match opt_trait_method_ty {
829 Some(trait_method_ty) => {
830 match (trait_method_ty, &impl_item_ty) {
831 (&ty::MethodTraitItem(ref trait_method_ty),
832 &ty::MethodTraitItem(ref impl_method_ty)) => {
833 compare_impl_method(ccx.tcx,
836 impl_method.pe_body().id,
841 // This is span_bug as it should have already been
842 // caught in resolve.
845 format!("item `{}` is of a different kind from its trait `{}`",
846 token::get_name(impl_item_ty.name()),
847 impl_trait_ref.repr(tcx)).as_slice());
852 // This is span_bug as it should have already been
853 // caught in resolve.
856 format!("method `{}` is not a member of trait `{}`",
857 token::get_name(impl_item_ty.name()),
858 impl_trait_ref.repr(tcx)).as_slice());
862 ast::TypeImplItem(ref typedef) => {
863 let typedef_def_id = local_def(typedef.id);
864 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
867 // If this is an impl of an associated type, find the
868 // corresponding type definition in the trait.
869 let opt_associated_type =
871 .find(|ti| ti.name() == typedef_ty.name());
872 match opt_associated_type {
873 Some(associated_type) => {
874 match (associated_type, &typedef_ty) {
875 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
877 // This is `span_bug` as it should have
878 // already been caught in resolve.
881 format!("item `{}` is of a different kind from its trait `{}`",
882 token::get_name(typedef_ty.name()),
883 impl_trait_ref.repr(tcx)).as_slice());
888 // This is `span_bug` as it should have already been
889 // caught in resolve.
893 "associated type `{}` is not a member of \
895 token::get_name(typedef_ty.name()),
896 impl_trait_ref.repr(tcx)).as_slice());
903 // Check for missing items from trait
904 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
905 let mut missing_methods = Vec::new();
906 for trait_item in trait_items.iter() {
908 ty::MethodTraitItem(ref trait_method) => {
910 impl_items.iter().any(|ii| {
912 ast::MethodImplItem(ref m) => {
913 m.pe_ident().name == trait_method.name
915 ast::TypeImplItem(_) => false,
919 provided_methods.iter().any(|m| m.name == trait_method.name);
920 if !is_implemented && !is_provided {
921 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
924 ty::TypeTraitItem(ref associated_type) => {
925 let is_implemented = impl_items.iter().any(|ii| {
927 ast::TypeImplItem(ref typedef) => {
928 typedef.ident.name == associated_type.name
930 ast::MethodImplItem(_) => false,
934 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
940 if !missing_methods.is_empty() {
941 span_err!(tcx.sess, impl_span, E0046,
942 "not all trait items implemented, missing: {}",
943 missing_methods.connect(", "));
947 /// Checks that a method from an impl conforms to the signature of
948 /// the same method as declared in the trait.
952 /// - impl_generics: the generics declared on the impl itself (not the method!)
953 /// - impl_m: type of the method we are checking
954 /// - impl_m_span: span to use for reporting errors
955 /// - impl_m_body_id: id of the method body
956 /// - trait_m: the method in the trait
957 /// - trait_to_impl_substs: the substitutions used on the type of the trait
958 fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
959 impl_m: &ty::Method<'tcx>,
961 impl_m_body_id: ast::NodeId,
962 trait_m: &ty::Method<'tcx>,
963 impl_trait_ref: &ty::TraitRef<'tcx>) {
964 debug!("compare_impl_method(impl_trait_ref={})",
965 impl_trait_ref.repr(tcx));
967 debug!("impl_trait_ref (liberated) = {}",
968 impl_trait_ref.repr(tcx));
970 let infcx = infer::new_infer_ctxt(tcx);
971 let mut fulfillment_cx = traits::FulfillmentContext::new();
973 let trait_to_impl_substs = &impl_trait_ref.substs;
975 // Try to give more informative error messages about self typing
976 // mismatches. Note that any mismatch will also be detected
977 // below, where we construct a canonical function type that
978 // includes the self parameter as a normal parameter. It's just
979 // that the error messages you get out of this code are a bit more
980 // inscrutable, particularly for cases where one method has no
982 match (&trait_m.explicit_self, &impl_m.explicit_self) {
983 (&ty::StaticExplicitSelfCategory,
984 &ty::StaticExplicitSelfCategory) => {}
985 (&ty::StaticExplicitSelfCategory, _) => {
988 format!("method `{}` has a `{}` declaration in the impl, \
989 but not in the trait",
990 token::get_name(trait_m.name),
991 ppaux::explicit_self_category_to_str(
992 &impl_m.explicit_self))[]);
995 (_, &ty::StaticExplicitSelfCategory) => {
998 format!("method `{}` has a `{}` declaration in the trait, \
999 but not in the impl",
1000 token::get_name(trait_m.name),
1001 ppaux::explicit_self_category_to_str(
1002 &trait_m.explicit_self))[]);
1006 // Let the type checker catch other errors below
1010 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
1011 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
1012 if num_impl_m_type_params != num_trait_m_type_params {
1013 span_err!(tcx.sess, impl_m_span, E0049,
1014 "method `{}` has {} type parameter{} \
1015 but its trait declaration has {} type parameter{}",
1016 token::get_name(trait_m.name),
1017 num_impl_m_type_params,
1018 if num_impl_m_type_params == 1 {""} else {"s"},
1019 num_trait_m_type_params,
1020 if num_trait_m_type_params == 1 {""} else {"s"});
1024 if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
1025 span_err!(tcx.sess, impl_m_span, E0050,
1026 "method `{}` has {} parameter{} \
1027 but the declaration in trait `{}` has {}",
1028 token::get_name(trait_m.name),
1029 impl_m.fty.sig.0.inputs.len(),
1030 if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
1031 ty::item_path_str(tcx, trait_m.def_id),
1032 trait_m.fty.sig.0.inputs.len());
1036 // This code is best explained by example. Consider a trait:
1038 // trait Trait<'t,T> {
1039 // fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
1044 // impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
1045 // fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
1048 // We wish to decide if those two method types are compatible.
1050 // We start out with trait_to_impl_substs, that maps the trait
1051 // type parameters to impl type parameters. This is taken from the
1052 // impl trait reference:
1054 // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
1056 // We create a mapping `dummy_substs` that maps from the impl type
1057 // parameters to fresh types and regions. For type parameters,
1058 // this is the identity transform, but we could as well use any
1059 // skolemized types. For regions, we convert from bound to free
1060 // regions (Note: but only early-bound regions, i.e., those
1061 // declared on the impl or used in type parameter bounds).
1063 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1065 // Now we can apply skol_substs to the type of the impl method
1066 // to yield a new function type in terms of our fresh, skolemized
1069 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1071 // We now want to extract and substitute the type of the *trait*
1072 // method and compare it. To do so, we must create a compound
1073 // substitution by combining trait_to_impl_substs and
1074 // impl_to_skol_substs, and also adding a mapping for the method
1075 // type parameters. We extend the mapping to also include
1076 // the method parameters.
1078 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1080 // Applying this to the trait method type yields:
1082 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1084 // This type is also the same but the name of the bound region ('a
1085 // vs 'b). However, the normal subtyping rules on fn types handle
1086 // this kind of equivalency just fine.
1088 // Create mapping from impl to skolemized.
1089 let impl_param_env = ty::construct_parameter_environment(tcx, &impl_m.generics, impl_m_body_id);
1090 let impl_to_skol_substs = &impl_param_env.free_substs;
1092 // Create mapping from trait to skolemized.
1093 let trait_to_skol_substs =
1094 trait_to_impl_substs
1095 .subst(tcx, impl_to_skol_substs)
1096 .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
1097 impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
1099 // Check region bounds.
1100 if !check_region_bounds_on_impl_method(tcx,
1105 &trait_to_skol_substs,
1106 impl_to_skol_substs) {
1110 // Check bounds. Note that the bounds from the impl may reference
1111 // late-bound regions declared on the impl, so liberate those.
1112 // This requires two artificial binding scopes -- one for the impl,
1113 // and one for the method.
1115 // An example would be:
1117 // trait Foo<T> { fn method<U:Bound<T>>() { ... } }
1119 // impl<'a> Foo<&'a T> for &'a U {
1120 // fn method<U:Bound<&'a T>>() { ... }
1123 // Here, the region parameter `'a` is late-bound, so in the bound
1124 // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
1125 // depth of 3 (it is nested within 3 binders: the impl, method,
1126 // and trait-ref itself). So when we do the liberation, we have
1127 // two introduce two `ty::Binder` scopes, one for the impl and one
1130 // The only late-bounded regions that can possibly appear here are
1131 // from the impl, not the method. This is because region
1132 // parameters declared on the method which appear in a type bound
1133 // would be early bound. On the trait side, there can be no
1134 // late-bound lifetimes because trait definitions do not introduce
1135 // a late region binder.
1137 trait_m.generics.types.get_slice(subst::FnSpace).iter()
1138 .map(|trait_param_def| &trait_param_def.bounds);
1140 impl_m.generics.types.get_slice(subst::FnSpace).iter()
1141 .map(|impl_param_def| &impl_param_def.bounds);
1142 for (i, (trait_param_bounds, impl_param_bounds)) in
1143 trait_bounds.zip(impl_bounds).enumerate()
1145 // Check that the impl does not require any builtin-bounds
1146 // that the trait does not guarantee:
1148 impl_param_bounds.builtin_bounds -
1149 trait_param_bounds.builtin_bounds;
1150 if !extra_bounds.is_empty() {
1151 span_err!(tcx.sess, impl_m_span, E0051,
1152 "in method `{}`, type parameter {} requires `{}`, \
1153 which is not required by the corresponding type parameter \
1154 in the trait declaration",
1155 token::get_name(trait_m.name),
1157 extra_bounds.user_string(tcx));
1161 // Check that the trait bounds of the trait imply the bounds of its
1164 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1165 // traits, but I doubt that'll be wanted often, so meh.
1166 for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
1167 debug!("compare_impl_method(): impl-trait-bound subst");
1168 let impl_trait_bound =
1169 impl_trait_bound.subst(tcx, impl_to_skol_substs);
1171 // There may be late-bound regions from the impl in the
1172 // impl's bound, so "liberate" those. Note that the
1173 // trait_to_skol_substs is derived from the impl's
1174 // trait-ref, and the late-bound regions appearing there
1175 // have already been liberated, so the result should match
1178 let found_match_in_trait =
1179 trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
1180 debug!("compare_impl_method(): trait-bound subst");
1182 trait_bound.subst(tcx, &trait_to_skol_substs);
1183 infer::mk_sub_poly_trait_refs(&infcx,
1185 infer::Misc(impl_m_span),
1187 impl_trait_bound.clone()).is_ok()
1190 if !found_match_in_trait {
1191 span_err!(tcx.sess, impl_m_span, E0052,
1192 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1193 required by the corresponding type parameter in the trait declaration",
1194 token::get_name(trait_m.name),
1196 impl_trait_bound.user_string(tcx));
1201 // We now need to check that the signature of the impl method is
1202 // compatible with that of the trait method. We do this by
1203 // checking that `impl_fty <: trait_fty`.
1205 // FIXME. Unfortunately, this doesn't quite work right now because
1206 // associated type normalization is not integrated into subtype
1207 // checks. For the comparison to be valid, we need to
1208 // normalize the associated types in the impl/trait methods
1209 // first. However, because function types bind regions, just
1210 // calling `normalize_associated_types_in` would have no effect on
1211 // any associated types appearing in the fn arguments or return
1215 // Compute skolemized form of impl and trait method tys.
1216 let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
1217 let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
1218 let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
1219 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1221 let err = infcx.try(|snapshot| {
1222 let origin = infer::MethodCompatCheck(impl_m_span);
1225 infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
1226 infer::HigherRankedType,
1229 impl_sig.subst(tcx, impl_to_skol_substs);
1231 assoc::normalize_associated_types_in(&infcx,
1233 &mut fulfillment_cx,
1240 tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
1241 abi: impl_m.fty.abi,
1242 sig: ty::Binder(impl_sig) }));
1243 debug!("compare_impl_method: impl_fty={}",
1244 impl_fty.repr(tcx));
1246 let (trait_sig, skol_map) =
1247 infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
1249 trait_sig.subst(tcx, &trait_to_skol_substs);
1251 assoc::normalize_associated_types_in(&infcx,
1253 &mut fulfillment_cx,
1260 tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
1261 abi: trait_m.fty.abi,
1262 sig: ty::Binder(trait_sig) }));
1264 debug!("compare_impl_method: trait_fty={}",
1265 trait_fty.repr(tcx));
1267 try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
1269 infcx.leak_check(&skol_map, snapshot)
1275 debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
1277 trait_fty.repr(tcx));
1278 span_err!(tcx.sess, impl_m_span, E0053,
1279 "method `{}` has an incompatible type for trait: {}",
1280 token::get_name(trait_m.name),
1281 ty::type_err_to_str(tcx, &terr));
1286 // Run the fulfillment context to completion to accommodate any
1287 // associated type normalizations that may have occurred.
1288 match fulfillment_cx.select_all_or_error(&infcx, &impl_param_env) {
1291 traits::report_fulfillment_errors(&infcx, &errors);
1295 // Finally, resolve all regions. This catches wily misuses of lifetime
1297 infcx.resolve_regions_and_report_errors(impl_m_body_id);
1299 /// Check that region bounds on impl method are the same as those on the trait. In principle,
1300 /// it could be ok for there to be fewer region bounds on the impl method, but this leads to an
1301 /// annoying corner case that is painful to handle (described below), so for now we can just
1304 /// Example (see `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1308 /// fn method1<'b>();
1309 /// fn method2<'b:'a>();
1312 /// impl<'a> Foo<'a> for ... {
1313 /// fn method1<'b:'a>() { .. case 1, definitely bad .. }
1314 /// fn method2<'b>() { .. case 2, could be ok .. }
1318 /// The "definitely bad" case is case #1. Here, the impl adds an extra constraint not present
1321 /// The "maybe bad" case is case #2. Here, the impl adds an extra constraint not present in the
1322 /// trait. We could in principle allow this, but it interacts in a complex way with early/late
1323 /// bound resolution of lifetimes. Basically the presence or absence of a lifetime bound
1324 /// affects whether the lifetime is early/late bound, and right now the code breaks if the
1325 /// trait has an early bound lifetime parameter and the method does not.
1326 fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
1328 impl_m: &ty::Method<'tcx>,
1329 trait_generics: &ty::Generics<'tcx>,
1330 impl_generics: &ty::Generics<'tcx>,
1331 trait_to_skol_substs: &Substs<'tcx>,
1332 impl_to_skol_substs: &Substs<'tcx>)
1336 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1337 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1339 debug!("check_region_bounds_on_impl_method: \
1342 trait_to_skol_substs={} \
1343 impl_to_skol_substs={}",
1344 trait_generics.repr(tcx),
1345 impl_generics.repr(tcx),
1346 trait_to_skol_substs.repr(tcx),
1347 impl_to_skol_substs.repr(tcx));
1349 // Must have same number of early-bound lifetime parameters.
1350 // Unfortunately, if the user screws up the bounds, then this
1351 // will change classification between early and late. E.g.,
1352 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1353 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1354 // in trait but 0 in the impl. But if we report "expected 2
1355 // but found 0" it's confusing, because it looks like there
1356 // are zero. Since I don't quite know how to phrase things at
1357 // the moment, give a kind of vague error message.
1358 if trait_params.len() != impl_params.len() {
1361 format!("lifetime parameters or bounds on method `{}` do \
1362 not match the trait declaration",
1363 token::get_name(impl_m.name))[]);
1367 // Each parameter `'a:'b+'c+'d` in trait should have the same
1368 // set of bounds in the impl, after subst.
1369 for (trait_param, impl_param) in
1370 trait_params.iter().zip(
1374 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1376 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1378 debug!("check_region_bounds_on_impl_method: \
1383 trait_param.repr(tcx),
1384 impl_param.repr(tcx),
1385 trait_bounds.repr(tcx),
1386 impl_bounds.repr(tcx));
1388 // Collect the set of bounds present in trait but not in
1390 let missing: Vec<ty::Region> =
1392 .filter(|&b| !impl_bounds.contains(b))
1396 // Collect set present in impl but not in trait.
1397 let extra: Vec<ty::Region> =
1399 .filter(|&b| !trait_bounds.contains(b))
1403 debug!("missing={} extra={}",
1404 missing.repr(tcx), extra.repr(tcx));
1406 let err = if missing.len() != 0 || extra.len() != 0 {
1410 "the lifetime parameter `{}` declared in the impl \
1411 has a distinct set of bounds \
1412 from its counterpart `{}` \
1413 declared in the trait",
1414 impl_param.name.user_string(tcx),
1415 trait_param.name.user_string(tcx))[]);
1421 if missing.len() != 0 {
1424 format!("the impl is missing the following bounds: `{}`",
1425 missing.user_string(tcx))[]);
1428 if extra.len() != 0 {
1431 format!("the impl has the following extra bounds: `{}`",
1432 extra.user_string(tcx))[]);
1444 fn check_cast(fcx: &FnCtxt,
1445 cast_expr: &ast::Expr,
1448 let id = cast_expr.id;
1449 let span = cast_expr.span;
1451 // Find the type of `e`. Supply hints based on the type we are casting to,
1453 let t_1 = fcx.to_ty(t);
1454 let t_1 = structurally_resolved_type(fcx, span, t_1);
1456 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1458 let t_e = fcx.expr_ty(e);
1460 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1461 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1463 if ty::type_is_error(t_e) {
1464 fcx.write_error(id);
1468 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1469 let tstr = fcx.infcx().ty_to_string(t_1);
1470 fcx.type_error_message(span, |actual| {
1471 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1474 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1475 let mtstr = match mt {
1476 ast::MutMutable => "mut ",
1477 ast::MutImmutable => ""
1479 if ty::type_is_trait(t_1) {
1480 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1482 span_help!(fcx.tcx().sess, span,
1483 "consider using an implicit coercion to `&{}{}` instead",
1487 ty::ty_uniq(..) => {
1488 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1491 span_help!(fcx.tcx().sess, e.span,
1492 "consider using a box or reference as appropriate");
1495 fcx.write_error(id);
1499 if ty::type_is_trait(t_1) {
1500 // This will be looked up later on.
1501 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1502 fcx.write_ty(id, t_1);
1506 let t_1 = structurally_resolved_type(fcx, span, t_1);
1507 let t_e = structurally_resolved_type(fcx, span, t_e);
1509 if ty::type_is_nil(t_e) {
1510 fcx.type_error_message(span, |actual| {
1511 format!("cast from nil: `{}` as `{}`",
1513 fcx.infcx().ty_to_string(t_1))
1515 } else if ty::type_is_nil(t_1) {
1516 fcx.type_error_message(span, |actual| {
1517 format!("cast to nil: `{}` as `{}`",
1519 fcx.infcx().ty_to_string(t_1))
1523 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1525 let t_1_is_scalar = ty::type_is_scalar(t_1);
1526 let t_1_is_char = ty::type_is_char(t_1);
1527 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1528 let t_1_is_float = ty::type_is_floating_point(t_1);
1530 // casts to scalars other than `char` and `bare fn` are trivial
1531 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1532 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1533 demand::coerce(fcx, e.span, t_1, &*e);
1534 } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1535 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1536 fcx.type_error_message(span, |actual| {
1537 format!("illegal cast; cast through an \
1538 integer first: `{}` as `{}`",
1540 fcx.infcx().ty_to_string(t_1))
1543 // casts from C-like enums are allowed
1544 } else if t_1_is_char {
1545 let t_e = fcx.infcx().shallow_resolve(t_e);
1546 if t_e.sty != ty::ty_uint(ast::TyU8) {
1547 fcx.type_error_message(span, |actual| {
1548 format!("only `u8` can be cast as \
1549 `char`, not `{}`", actual)
1552 } else if t_1.sty == ty::ty_bool {
1553 span_err!(fcx.tcx().sess, span, E0054,
1554 "cannot cast as `bool`, compare with zero instead");
1555 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1556 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1557 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1559 ty::ty_vec(_, Some(_)) => {}
1562 if ty::type_needs_infer(t2) {
1563 // This prevents this special case from going off when casting
1564 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1569 let el = ty::sequence_element_type(fcx.tcx(), t1);
1570 infer::mk_eqty(fcx.infcx(),
1577 // Due to the limitations of LLVM global constants,
1578 // region pointers end up pointing at copies of
1579 // vector elements instead of the original values.
1580 // To allow unsafe pointers to work correctly, we
1581 // need to special-case obtaining an unsafe pointer
1582 // from a region pointer to a vector.
1584 /* this cast is only allowed from &[T, ..n] to *T or
1586 match (&t_e.sty, &t_1.sty) {
1587 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1588 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1589 if types_compatible(fcx, e.span, mt1, mt2) => {
1590 /* this case is allowed */
1593 demand::coerce(fcx, e.span, t_1, &*e);
1596 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1598 If more type combinations should be supported than are
1599 supported here, then file an enhancement issue and
1600 record the issue number in this comment.
1602 fcx.type_error_message(span, |actual| {
1603 format!("non-scalar cast: `{}` as `{}`",
1605 fcx.infcx().ty_to_string(t_1))
1607 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1608 fcx.type_error_message(span, |actual| {
1609 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1612 fcx.infcx().ty_to_string(t_1))
1616 fcx.write_ty(id, t_1);
1619 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1620 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1622 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1623 ty::lookup_item_type(self.tcx(), id)
1626 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1627 ty::lookup_trait_def(self.tcx(), id)
1630 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1631 Some(&self.inh.param_env.free_substs)
1634 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1635 self.infcx().next_ty_var()
1638 fn projected_ty_from_poly_trait_ref(&self,
1640 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1641 item_name: ast::Name)
1644 let (trait_ref, _) =
1645 self.infcx().replace_late_bound_regions_with_fresh_var(
1647 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1650 self.normalize_associated_type(span, trait_ref, item_name)
1653 fn projected_ty(&self,
1655 trait_ref: Rc<ty::TraitRef<'tcx>>,
1656 item_name: ast::Name)
1659 self.normalize_associated_type(span, trait_ref, item_name)
1663 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1664 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1666 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1670 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1674 pub fn sess(&self) -> &Session {
1678 pub fn err_count_since_creation(&self) -> uint {
1679 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1682 /// Resolves all type variables in `t` and then, if any were left
1683 /// unresolved, substitutes an error type. This is used after the
1684 /// main checking when doing a second pass before writeback. The
1685 /// justification is that writeback will produce an error for
1686 /// these unconstrained type variables.
1687 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1688 let t = self.infcx().resolve_type_vars_if_possible(t);
1689 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1692 pub fn tag(&self) -> String {
1693 format!("{}", self as *const FnCtxt)
1696 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1697 match self.inh.locals.borrow().get(&nid) {
1700 self.tcx().sess.span_bug(
1702 format!("no type for local variable {}",
1708 /// Apply "fallbacks" to some types
1709 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1710 pub fn default_type_parameters(&self) {
1711 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1712 for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1713 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1714 if self.infcx().type_var_diverges(resolved) {
1715 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1717 match self.infcx().type_is_unconstrained_numeric(resolved) {
1718 UnconstrainedInt => {
1719 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1721 UnconstrainedFloat => {
1722 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1731 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1732 debug!("write_ty({}, {}) in fcx {}",
1733 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1734 self.inh.node_types.borrow_mut().insert(node_id, ty);
1737 pub fn write_object_cast(&self,
1739 trait_ref: ty::PolyTraitRef<'tcx>) {
1740 debug!("write_object_cast key={} trait_ref={}",
1741 key, trait_ref.repr(self.tcx()));
1742 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1745 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1746 if !substs.substs.is_noop() {
1747 debug!("write_substs({}, {}) in fcx {}",
1749 substs.repr(self.tcx()),
1752 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1756 pub fn write_autoderef_adjustment(&self,
1757 node_id: ast::NodeId,
1760 if derefs == 0 { return; }
1761 self.write_adjustment(
1764 ty::AdjustDerefRef(ty::AutoDerefRef {
1770 pub fn write_adjustment(&self,
1771 node_id: ast::NodeId,
1773 adj: ty::AutoAdjustment<'tcx>) {
1774 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1776 if adj.is_identity() {
1780 // Careful: adjustments can imply trait obligations if we are
1781 // casting from a concrete type to an object type. I think
1782 // it'd probably be nicer to move the logic that creates the
1783 // obligation into the code that creates the adjustment, but
1784 // that's a bit awkward, so instead we go digging and pull the
1785 // obligation out here.
1786 self.register_adjustment_obligations(span, &adj);
1787 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1790 /// Basically whenever we are converting from a type scheme into
1791 /// the fn body space, we always want to normalize associated
1792 /// types as well. This function combines the two.
1793 fn instantiate_type_scheme<T>(&self,
1795 substs: &Substs<'tcx>,
1798 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1800 let value = value.subst(self.tcx(), substs);
1801 let result = self.normalize_associated_types_in(span, &value);
1802 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1803 value.repr(self.tcx()),
1804 substs.repr(self.tcx()),
1805 result.repr(self.tcx()));
1809 /// As `instantiate_type_scheme`, but for the bounds found in a
1810 /// generic type scheme.
1811 fn instantiate_bounds(&self,
1813 substs: &Substs<'tcx>,
1814 generics: &ty::Generics<'tcx>)
1815 -> ty::GenericBounds<'tcx>
1818 predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
1823 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1824 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1826 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1829 fn normalize_associated_type(&self,
1831 trait_ref: Rc<ty::TraitRef<'tcx>>,
1832 item_name: ast::Name)
1835 let cause = traits::ObligationCause::new(span,
1837 traits::ObligationCauseCode::MiscObligation);
1838 self.inh.fulfillment_cx
1840 .normalize_projection_type(self.infcx(),
1843 trait_ref: trait_ref,
1844 item_name: item_name,
1849 fn register_adjustment_obligations(&self,
1851 adj: &ty::AutoAdjustment<'tcx>) {
1853 ty::AdjustAddEnv(..) |
1854 ty::AdjustReifyFnPointer(..) => {
1856 ty::AdjustDerefRef(ref d_r) => {
1859 self.register_autoref_obligations(span, a_r);
1867 fn register_autoref_obligations(&self,
1869 autoref: &ty::AutoRef<'tcx>) {
1871 ty::AutoUnsize(ref unsize) => {
1872 self.register_unsize_obligations(span, unsize);
1874 ty::AutoPtr(_, _, None) |
1875 ty::AutoUnsafe(_, None) => {
1877 ty::AutoPtr(_, _, Some(ref a_r)) |
1878 ty::AutoUnsafe(_, Some(ref a_r)) => {
1879 self.register_autoref_obligations(span, &**a_r)
1881 ty::AutoUnsizeUniq(ref unsize) => {
1882 self.register_unsize_obligations(span, unsize);
1887 fn register_unsize_obligations(&self,
1889 unsize: &ty::UnsizeKind<'tcx>) {
1890 debug!("register_unsize_obligations: unsize={}", unsize);
1893 ty::UnsizeLength(..) => {}
1894 ty::UnsizeStruct(ref u, _) => {
1895 self.register_unsize_obligations(span, &**u)
1897 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1898 vtable::check_object_safety(self.tcx(), ty_trait, span);
1900 // If the type is `Foo+'a`, ensures that the type
1901 // being cast to `Foo+'a` implements `Foo`:
1902 vtable::register_object_cast_obligations(self,
1907 // If the type is `Foo+'a`, ensures that the type
1908 // being cast to `Foo+'a` outlives `'a`:
1909 let cause = traits::ObligationCause { span: span,
1910 body_id: self.body_id,
1911 code: traits::ObjectCastObligation(self_ty) };
1912 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1917 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1918 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1919 /// Registers any trait obligations specified on `def_id` at the same time.
1921 /// Note that function is only intended to be used with types (notably, not fns). This is
1922 /// because it doesn't do any instantiation of late-bound regions.
1923 pub fn instantiate_type(&self,
1926 -> TypeAndSubsts<'tcx>
1929 ty::lookup_item_type(self.tcx(), def_id);
1931 self.infcx().fresh_substs_for_generics(
1933 &type_scheme.generics);
1935 self.instantiate_bounds(span, &substs, &type_scheme.generics);
1936 self.add_obligations_for_parameters(
1937 traits::ObligationCause::new(
1940 traits::ItemObligation(def_id)),
1943 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1951 pub fn write_nil(&self, node_id: ast::NodeId) {
1952 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1954 pub fn write_error(&self, node_id: ast::NodeId) {
1955 self.write_ty(node_id, self.tcx().types.err);
1958 pub fn require_type_meets(&self,
1961 code: traits::ObligationCauseCode<'tcx>,
1962 bound: ty::BuiltinBound)
1964 self.register_builtin_bound(
1967 traits::ObligationCause::new(span, self.body_id, code));
1970 pub fn require_type_is_sized(&self,
1973 code: traits::ObligationCauseCode<'tcx>)
1975 self.require_type_meets(ty, span, code, ty::BoundSized);
1978 pub fn require_expr_have_sized_type(&self,
1980 code: traits::ObligationCauseCode<'tcx>)
1982 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1985 pub fn type_is_known_to_be_sized(&self,
1990 traits::type_known_to_meet_builtin_bound(self.infcx(),
1997 pub fn register_builtin_bound(&self,
1999 builtin_bound: ty::BuiltinBound,
2000 cause: traits::ObligationCause<'tcx>)
2002 self.inh.fulfillment_cx.borrow_mut()
2003 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
2006 pub fn register_predicate(&self,
2007 obligation: traits::PredicateObligation<'tcx>)
2009 debug!("register_predicate({})",
2010 obligation.repr(self.tcx()));
2012 self.inh.fulfillment_cx
2014 .register_predicate_obligation(self.infcx(), obligation);
2017 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
2018 let t = ast_ty_to_ty(self, self, ast_t);
2020 let mut bounds_checker = wf::BoundsChecker::new(self,
2022 CodeExtent::from_node_id(self.body_id),
2024 bounds_checker.check_ty(t);
2029 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
2030 pat.repr(self.tcx())
2033 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
2034 match self.inh.node_types.borrow().get(&ex.id) {
2037 self.tcx().sess.bug(format!("no type for expr in fcx {}",
2043 /// Apply `adjustment` to the type of `expr`
2044 pub fn adjust_expr_ty(&self,
2046 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
2049 let raw_ty = self.expr_ty(expr);
2050 let raw_ty = self.infcx().shallow_resolve(raw_ty);
2051 ty::adjust_ty(self.tcx(),
2056 |method_call| self.inh.method_map.borrow()
2058 .map(|method| method.ty))
2061 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
2062 match self.inh.node_types.borrow().get(&id) {
2065 self.tcx().sess.bug(
2066 format!("no type for node {}: {} in fcx {}",
2067 id, self.tcx().map.node_to_string(id),
2073 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
2074 self.inh.item_substs.borrow()
2077 pub fn opt_node_ty_substs<F>(&self,
2080 F: FnOnce(&ty::ItemSubsts<'tcx>),
2082 match self.inh.item_substs.borrow().get(&id) {
2088 pub fn mk_subty(&self,
2089 a_is_expected: bool,
2090 origin: infer::TypeOrigin,
2093 -> Result<(), ty::type_err<'tcx>> {
2094 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
2097 pub fn mk_assignty(&self,
2101 -> Result<(), ty::type_err<'tcx>> {
2102 match infer::mk_coercety(self.infcx(),
2104 infer::ExprAssignable(expr.span),
2108 Err(ref e) => Err((*e)),
2109 Ok(Some(adjustment)) => {
2110 self.write_adjustment(expr.id, expr.span, adjustment);
2116 pub fn mk_eqty(&self,
2117 a_is_expected: bool,
2118 origin: infer::TypeOrigin,
2121 -> Result<(), ty::type_err<'tcx>> {
2122 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
2125 pub fn mk_subr(&self,
2126 origin: infer::SubregionOrigin<'tcx>,
2129 infer::mk_subr(self.infcx(), origin, sub, sup)
2132 pub fn type_error_message<M>(&self,
2135 actual_ty: Ty<'tcx>,
2136 err: Option<&ty::type_err<'tcx>>) where
2137 M: FnOnce(String) -> String,
2139 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
2142 pub fn report_mismatched_types(&self,
2146 err: &ty::type_err<'tcx>) {
2147 self.infcx().report_mismatched_types(sp, e, a, err)
2150 /// Registers an obligation for checking later, during regionck, that the type `ty` must
2151 /// outlive the region `r`.
2152 pub fn register_region_obligation(&self,
2155 cause: traits::ObligationCause<'tcx>)
2157 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
2158 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
2161 pub fn add_default_region_param_bounds(&self,
2162 substs: &Substs<'tcx>,
2165 for &ty in substs.types.iter() {
2166 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
2167 let cause = traits::ObligationCause::new(expr.span, self.body_id,
2168 traits::MiscObligation);
2169 self.register_region_obligation(ty, default_bound, cause);
2173 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
2174 /// type/region parameter was instantiated (`substs`), creates and registers suitable
2175 /// trait/region obligations.
2177 /// For example, if there is a function:
2180 /// fn foo<'a,T:'a>(...)
2183 /// and a reference:
2189 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
2190 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
2191 pub fn add_obligations_for_parameters(&self,
2192 cause: traits::ObligationCause<'tcx>,
2193 generic_bounds: &ty::GenericBounds<'tcx>)
2195 assert!(!generic_bounds.has_escaping_regions());
2197 debug!("add_obligations_for_parameters(generic_bounds={})",
2198 generic_bounds.repr(self.tcx()));
2200 let obligations = traits::predicates_for_generics(self.tcx(),
2204 obligations.map_move(|o| self.register_predicate(o));
2208 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
2209 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
2210 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
2213 fn anon_regions(&self, span: Span, count: uint)
2214 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
2215 Ok(range(0, count).map(|_| {
2216 self.infcx().next_region_var(infer::MiscVariable(span))
2221 #[deriving(Copy, Show, PartialEq, Eq)]
2222 pub enum LvaluePreference {
2227 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
2228 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
2230 /// Note: this method does not modify the adjustments table. The caller is responsible for
2231 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
2232 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
2234 expr_id: Option<ast::NodeId>,
2235 mut lvalue_pref: LvaluePreference,
2237 -> (Ty<'tcx>, uint, Option<T>) where
2238 F: FnMut(Ty<'tcx>, uint) -> Option<T>,
2240 let mut t = base_ty;
2241 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
2242 let resolved_t = structurally_resolved_type(fcx, sp, t);
2244 if ty::type_is_error(resolved_t) {
2245 return (resolved_t, autoderefs, None);
2248 match should_stop(resolved_t, autoderefs) {
2249 Some(x) => return (resolved_t, autoderefs, Some(x)),
2253 // Otherwise, deref if type is derefable:
2254 let mt = match ty::deref(resolved_t, false) {
2255 Some(mt) => Some(mt),
2257 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
2258 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2264 if mt.mutbl == ast::MutImmutable {
2265 lvalue_pref = NoPreference;
2268 None => return (resolved_t, autoderefs, None)
2272 // We've reached the recursion limit, error gracefully.
2273 span_err!(fcx.tcx().sess, sp, E0055,
2274 "reached the recursion limit while auto-dereferencing {}",
2275 base_ty.repr(fcx.tcx()));
2276 (fcx.tcx().types.err, 0, None)
2279 /// Attempts to resolve a call expression as an overloaded call.
2280 fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2281 call_expression: &ast::Expr,
2283 callee_type: Ty<'tcx>,
2284 args: &[&P<ast::Expr>])
2286 // Bail out if the callee is a bare function or a closure. We check those
2288 match structurally_resolved_type(fcx, callee.span, callee_type).sty {
2289 ty::ty_bare_fn(..) | ty::ty_closure(_) => return false,
2293 // Try the options that are least restrictive on the caller first.
2294 for &(maybe_function_trait, method_name) in [
2295 (fcx.tcx().lang_items.fn_trait(), token::intern("call")),
2296 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2297 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2299 let function_trait = match maybe_function_trait {
2301 Some(function_trait) => function_trait,
2304 match method::lookup_in_trait(fcx,
2305 call_expression.span,
2312 Some(method_callee) => method_callee,
2314 let method_call = MethodCall::expr(call_expression.id);
2315 let output_type = check_method_argument_types(fcx,
2316 call_expression.span,
2322 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2323 write_call(fcx, call_expression, output_type);
2331 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2333 method_call: Option<MethodCall>,
2334 base_expr: Option<&ast::Expr>,
2336 lvalue_pref: LvaluePreference)
2337 -> Option<ty::mt<'tcx>>
2339 // Try DerefMut first, if preferred.
2340 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2341 (PreferMutLvalue, Some(trait_did)) => {
2342 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2343 token::intern("deref_mut"), trait_did,
2349 // Otherwise, fall back to Deref.
2350 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2351 (None, Some(trait_did)) => {
2352 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2353 token::intern("deref"), trait_did,
2356 (method, _) => method
2359 make_overloaded_lvalue_return_type(fcx, method_call, method)
2362 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2363 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2364 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2365 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2366 method_call: Option<MethodCall>,
2367 method: Option<MethodCallee<'tcx>>)
2368 -> Option<ty::mt<'tcx>>
2372 let ref_ty = ty::ty_fn_ret(method.ty);
2374 Some(method_call) => {
2375 fcx.inh.method_map.borrow_mut().insert(method_call,
2381 ty::FnConverging(ref_ty) => {
2382 ty::deref(ref_ty, true)
2384 ty::FnDiverging => {
2385 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2393 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2394 base_expr: &ast::Expr,
2396 lvalue_pref: LvaluePreference,
2399 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2401 // FIXME(#18741) -- this is almost but not quite the same as the
2402 // autoderef that normal method probing does. They could likely be
2405 let (ty, autoderefs, final_mt) =
2406 autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
2407 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2408 step(adj_ty, autoderefref)
2411 if final_mt.is_some() {
2415 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2416 // do a final unsized coercion to yield [T].
2418 ty::ty_vec(element_ty, Some(n)) => {
2419 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2420 let autoderefref = ty::AutoDerefRef {
2421 autoderefs: autoderefs,
2422 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2424 step(adjusted_ty, autoderefref)
2432 /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one,
2433 /// installs method info and returns type of method (else None).
2434 fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2435 method_call: MethodCall,
2437 base_expr: &ast::Expr,
2438 base_ty: Ty<'tcx>, // autoderef'd type
2439 autoderefref: ty::AutoDerefRef<'tcx>,
2440 lvalue_pref: LvaluePreference,
2441 start_expr: &Option<P<ast::Expr>>,
2442 end_expr: &Option<P<ast::Expr>>)
2443 -> Option<(Ty<'tcx>, /* index type */
2444 Ty<'tcx>)> /* return type */
2446 let input_ty = fcx.infcx().next_ty_var();
2447 let return_ty = fcx.infcx().next_ty_var();
2449 let method = match lvalue_pref {
2450 PreferMutLvalue => {
2451 // Try `SliceMut` first, if preferred.
2452 match fcx.tcx().lang_items.slice_mut_trait() {
2453 Some(trait_did) => {
2454 let method_name = match (start_expr, end_expr) {
2455 (&Some(_), &Some(_)) => "slice_or_fail_mut",
2456 (&Some(_), &None) => "slice_from_or_fail_mut",
2457 (&None, &Some(_)) => "slice_to_or_fail_mut",
2458 (&None, &None) => "as_mut_slice_",
2461 method::lookup_in_trait_adjusted(fcx,
2464 token::intern(method_name),
2468 Some(vec![input_ty, return_ty]))
2474 // Otherwise, fall back to `Slice`.
2475 match fcx.tcx().lang_items.slice_trait() {
2476 Some(trait_did) => {
2477 let method_name = match (start_expr, end_expr) {
2478 (&Some(_), &Some(_)) => "slice_or_fail",
2479 (&Some(_), &None) => "slice_from_or_fail",
2480 (&None, &Some(_)) => "slice_to_or_fail",
2481 (&None, &None) => "as_slice_",
2484 method::lookup_in_trait_adjusted(fcx,
2487 token::intern(method_name),
2491 Some(vec![input_ty, return_ty]))
2498 // If some lookup succeeded, install method in table
2499 method.map(|method| {
2500 let method_ty = method.ty;
2501 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method));
2503 let result_ty = ty::ty_fn_ret(method_ty);
2504 let result_ty = match result_ty {
2505 ty::FnConverging(result_ty) => result_ty,
2506 ty::FnDiverging => {
2507 fcx.tcx().sess.span_bug(expr.span,
2508 "slice trait does not define a `!` return")
2512 (input_ty, result_ty)
2516 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2517 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2518 /// This loop implements one step in that search; the autoderef loop is implemented by
2519 /// `autoderef_for_index`.
2520 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2521 method_call: MethodCall,
2523 base_expr: &ast::Expr,
2524 adjusted_ty: Ty<'tcx>,
2525 adjustment: ty::AutoDerefRef<'tcx>,
2526 lvalue_pref: LvaluePreference)
2527 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2529 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={})",
2530 expr.repr(fcx.tcx()),
2531 base_expr.repr(fcx.tcx()),
2532 adjusted_ty.repr(fcx.tcx()),
2535 // Try built-in indexing first.
2536 match ty::index(adjusted_ty) {
2538 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2539 return Some((fcx.tcx().types.uint, ty));
2545 let input_ty = fcx.infcx().next_ty_var();
2547 // Try `IndexMut` first, if preferred.
2548 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2549 (PreferMutLvalue, Some(trait_did)) => {
2550 method::lookup_in_trait_adjusted(fcx,
2553 token::intern("index_mut"),
2557 Some(vec![input_ty]))
2562 // Otherwise, fall back to `Index`.
2563 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2564 (None, Some(trait_did)) => {
2565 method::lookup_in_trait_adjusted(fcx,
2568 token::intern("index"),
2572 Some(vec![input_ty]))
2574 (method, _) => method,
2577 // If some lookup succeeds, write callee into table and extract index/element
2578 // type from the method signature.
2579 // If some lookup succeeded, install method in table
2580 method.and_then(|method| {
2581 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2582 map(|ret| (input_ty, ret.ty))
2586 /// Given the head of a `for` expression, looks up the `next` method in the
2587 /// `Iterator` trait. Panics if the expression does not implement `next`.
2589 /// The return type of this function represents the concrete element type
2590 /// `A` in the type `Iterator<A>` that the method returns.
2591 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2592 iterator_expr: &ast::Expr,
2593 loop_id: ast::NodeId)
2595 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2596 Ok(trait_did) => trait_did,
2597 Err(ref err_string) => {
2598 fcx.tcx().sess.span_err(iterator_expr.span,
2600 return fcx.tcx().types.err
2604 let expr_type = fcx.expr_ty(&*iterator_expr);
2605 let method = method::lookup_in_trait(fcx,
2607 Some(&*iterator_expr),
2608 token::intern("next"),
2613 // Regardless of whether the lookup succeeds, check the method arguments
2614 // so that we have *some* type for each argument.
2615 let method_type = match method {
2616 Some(ref method) => method.ty,
2618 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2620 if !ty::type_is_error(true_expr_type) {
2621 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2622 fcx.tcx().sess.span_err(iterator_expr.span,
2623 format!("`for` loop expression has type `{}` which does \
2624 not implement the `Iterator` trait; \
2631 let return_type = check_method_argument_types(fcx,
2637 DontTupleArguments);
2641 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2644 // We expect the return type to be `Option` or something like it.
2645 // Grab the first parameter of its type substitution.
2646 let return_type = match return_type {
2647 ty::FnConverging(return_type) =>
2648 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2649 ty::FnDiverging => fcx.tcx().types.err
2651 match return_type.sty {
2652 ty::ty_enum(_, ref substs)
2653 if !substs.types.is_empty_in(subst::TypeSpace) => {
2654 *substs.types.get(subst::TypeSpace, 0)
2660 fcx.tcx().sess.span_err(iterator_expr.span,
2661 format!("`next` method of the `Iterator` \
2662 trait has an unexpected type `{}`",
2663 fcx.infcx().ty_to_string(return_type))
2669 None => fcx.tcx().types.err
2673 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2675 method_fn_ty: Ty<'tcx>,
2676 callee_expr: &ast::Expr,
2677 args_no_rcvr: &[&P<ast::Expr>],
2678 autoref_args: AutorefArgs,
2679 tuple_arguments: TupleArgumentsFlag)
2680 -> ty::FnOutput<'tcx> {
2681 if ty::type_is_error(method_fn_ty) {
2682 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2684 let err_inputs = match tuple_arguments {
2685 DontTupleArguments => err_inputs,
2686 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2689 check_argument_types(fcx,
2697 ty::FnConverging(fcx.tcx().types.err)
2699 match method_fn_ty.sty {
2700 ty::ty_bare_fn(_, ref fty) => {
2701 // HACK(eddyb) ignore self in the definition (see above).
2702 check_argument_types(fcx,
2704 fty.sig.0.inputs.slice_from(1),
2713 fcx.tcx().sess.span_bug(callee_expr.span,
2714 "method without bare fn type");
2720 /// Generic function that factors out common logic from function calls, method calls and overloaded
2722 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2724 fn_inputs: &[Ty<'tcx>],
2725 _callee_expr: &ast::Expr,
2726 args: &[&P<ast::Expr>],
2727 autoref_args: AutorefArgs,
2729 tuple_arguments: TupleArgumentsFlag) {
2730 let tcx = fcx.ccx.tcx;
2732 // Grab the argument types, supplying fresh type variables
2733 // if the wrong number of arguments were supplied
2734 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2740 let expected_arg_count = fn_inputs.len();
2741 let formal_tys = if tuple_arguments == TupleArguments {
2742 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2743 match tuple_type.sty {
2744 ty::ty_tup(ref arg_types) => {
2745 if arg_types.len() != args.len() {
2746 span_err!(tcx.sess, sp, E0057,
2747 "this function takes {} parameter{} but {} parameter{} supplied",
2749 if arg_types.len() == 1 {""} else {"s"},
2751 if args.len() == 1 {" was"} else {"s were"});
2752 err_args(fcx.tcx(), args.len())
2754 (*arg_types).clone()
2758 span_err!(tcx.sess, sp, E0059,
2759 "cannot use call notation; the first type parameter \
2760 for the function trait is neither a tuple nor unit");
2761 err_args(fcx.tcx(), args.len())
2764 } else if expected_arg_count == supplied_arg_count {
2765 fn_inputs.iter().map(|a| *a).collect()
2766 } else if variadic {
2767 if supplied_arg_count >= expected_arg_count {
2768 fn_inputs.iter().map(|a| *a).collect()
2770 span_err!(tcx.sess, sp, E0060,
2771 "this function takes at least {} parameter{} \
2772 but {} parameter{} supplied",
2774 if expected_arg_count == 1 {""} else {"s"},
2776 if supplied_arg_count == 1 {" was"} else {"s were"});
2777 err_args(fcx.tcx(), supplied_arg_count)
2780 span_err!(tcx.sess, sp, E0061,
2781 "this function takes {} parameter{} but {} parameter{} supplied",
2783 if expected_arg_count == 1 {""} else {"s"},
2785 if supplied_arg_count == 1 {" was"} else {"s were"});
2786 err_args(fcx.tcx(), supplied_arg_count)
2789 debug!("check_argument_types: formal_tys={}",
2790 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2792 // Check the arguments.
2793 // We do this in a pretty awful way: first we typecheck any arguments
2794 // that are not anonymous functions, then we typecheck the anonymous
2795 // functions. This is so that we have more information about the types
2796 // of arguments when we typecheck the functions. This isn't really the
2797 // right way to do this.
2798 let xs = [false, true];
2799 for check_blocks in xs.iter() {
2800 let check_blocks = *check_blocks;
2801 debug!("check_blocks={}", check_blocks);
2803 // More awful hacks: before we check the blocks, try to do
2804 // an "opportunistic" vtable resolution of any trait
2805 // bounds on the call.
2807 vtable::select_new_fcx_obligations(fcx);
2810 // For variadic functions, we don't have a declared type for all of
2811 // the arguments hence we only do our usual type checking with
2812 // the arguments who's types we do know.
2813 let t = if variadic {
2815 } else if tuple_arguments == TupleArguments {
2820 for (i, arg) in args.iter().take(t).enumerate() {
2821 let is_block = match arg.node {
2822 ast::ExprClosure(..) => true,
2826 if is_block == check_blocks {
2827 debug!("checking the argument");
2828 let mut formal_ty = formal_tys[i];
2830 match autoref_args {
2831 AutorefArgs::Yes => {
2832 match formal_ty.sty {
2833 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2836 // So we hit this case when one implements the
2837 // operator traits but leaves an argument as
2838 // just T instead of &T. We'll catch it in the
2839 // mismatch impl/trait method phase no need to
2842 formal_ty = tcx.types.err;
2846 AutorefArgs::No => {}
2849 check_expr_coercable_to_type(fcx, &***arg, formal_ty);
2854 // We also need to make sure we at least write the ty of the other
2855 // arguments which we skipped above.
2857 for arg in args.iter().skip(expected_arg_count) {
2858 check_expr(fcx, &***arg);
2860 // There are a few types which get autopromoted when passed via varargs
2861 // in C but we just error out instead and require explicit casts.
2862 let arg_ty = structurally_resolved_type(fcx, arg.span,
2863 fcx.expr_ty(&***arg));
2865 ty::ty_float(ast::TyF32) => {
2866 fcx.type_error_message(arg.span,
2868 format!("can't pass an {} to variadic \
2869 function, cast to c_double", t)
2872 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2873 fcx.type_error_message(arg.span, |t| {
2874 format!("can't pass {} to variadic \
2875 function, cast to c_int",
2879 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2880 fcx.type_error_message(arg.span, |t| {
2881 format!("can't pass {} to variadic \
2882 function, cast to c_uint",
2892 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2893 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2894 range(0, len).map(|_| tcx.types.err).collect()
2897 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2898 call_expr: &ast::Expr,
2899 output: ty::FnOutput<'tcx>) {
2900 fcx.write_ty(call_expr.id, match output {
2901 ty::FnConverging(output_ty) => output_ty,
2902 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2906 // AST fragment checking
2907 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2909 expected: Expectation<'tcx>)
2912 let tcx = fcx.ccx.tcx;
2915 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2916 ast::LitBinary(..) => {
2918 tcx.mk_region(ty::ReStatic),
2919 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2921 ast::LitByte(_) => tcx.types.u8,
2922 ast::LitChar(_) => tcx.types.char,
2923 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2924 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2925 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2926 let opt_ty = expected.map_to_option(fcx, |ty| {
2928 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2929 ty::ty_char => Some(tcx.types.u8),
2930 ty::ty_ptr(..) => Some(tcx.types.uint),
2931 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2935 opt_ty.unwrap_or_else(
2936 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2938 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2939 ast::LitFloatUnsuffixed(_) => {
2940 let opt_ty = expected.map_to_option(fcx, |ty| {
2942 ty::ty_float(_) => Some(ty),
2946 opt_ty.unwrap_or_else(
2947 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2949 ast::LitBool(_) => tcx.types.bool
2953 pub fn valid_range_bounds(ccx: &CrateCtxt,
2957 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2958 Some(val) => Some(val <= 0),
2963 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2965 expected: Ty<'tcx>) {
2966 check_expr_with_unifier(
2967 fcx, expr, ExpectHasType(expected), NoPreference,
2968 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2971 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2973 expected: Ty<'tcx>) {
2974 check_expr_with_unifier(
2975 fcx, expr, ExpectHasType(expected), NoPreference,
2976 || demand::coerce(fcx, expr.span, expected, expr));
2979 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2980 expected: Ty<'tcx>) {
2981 check_expr_with_unifier(
2982 fcx, expr, ExpectHasType(expected), NoPreference,
2986 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2988 expected: Expectation<'tcx>) {
2989 check_expr_with_unifier(
2990 fcx, expr, expected, NoPreference,
2994 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2996 expected: Expectation<'tcx>,
2997 lvalue_pref: LvaluePreference)
2999 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
3002 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
3003 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
3006 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
3007 lvalue_pref: LvaluePreference) {
3008 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
3011 // determine the `self` type, using fresh variables for all variables
3012 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
3013 // would return ($0, $1) where $0 and $1 are freshly instantiated type
3015 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3016 span: Span, // (potential) receiver for this impl
3018 -> TypeAndSubsts<'tcx> {
3019 let tcx = fcx.tcx();
3021 let ity = ty::lookup_item_type(tcx, did);
3022 let (n_tps, rps, raw_ty) =
3023 (ity.generics.types.len(subst::TypeSpace),
3024 ity.generics.regions.get_slice(subst::TypeSpace),
3027 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
3028 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
3029 let substs = subst::Substs::new_type(tps, rps);
3030 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
3032 TypeAndSubsts { substs: substs, ty: substd_ty }
3035 // Only for fields! Returns <none> for methods>
3036 // Indifferent to privacy flags
3037 pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
3038 class_id: ast::DefId,
3039 items: &[ty::field_ty],
3040 fieldname: ast::Name,
3041 substs: &subst::Substs<'tcx>)
3042 -> Option<Ty<'tcx>> {
3044 let o_field = items.iter().find(|f| f.name == fieldname);
3045 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
3048 pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
3049 class_id: ast::DefId,
3050 items: &[ty::field_ty],
3052 substs: &subst::Substs<'tcx>)
3053 -> Option<Ty<'tcx>> {
3055 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
3056 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
3059 // Controls whether the arguments are automatically referenced. This is useful
3060 // for overloaded binary and unary operators.
3061 #[deriving(Copy, PartialEq)]
3062 pub enum AutorefArgs {
3067 /// Controls whether the arguments are tupled. This is used for the call
3070 /// Tupling means that all call-side arguments are packed into a tuple and
3071 /// passed as a single parameter. For example, if tupling is enabled, this
3074 /// fn f(x: (int, int))
3076 /// Can be called as:
3083 #[deriving(Clone, Eq, PartialEq)]
3084 enum TupleArgumentsFlag {
3090 /// If an expression has any sub-expressions that result in a type error,
3091 /// inspecting that expression's type with `ty::type_is_error` will return
3092 /// true. Likewise, if an expression is known to diverge, inspecting its
3093 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
3094 /// strict, _|_ can appear in the type of an expression that does not,
3095 /// itself, diverge: for example, fn() -> _|_.)
3096 /// Note that inspecting a type's structure *directly* may expose the fact
3097 /// that there are actually multiple representations for `ty_err`, so avoid
3098 /// that when err needs to be handled differently.
3099 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3101 expected: Expectation<'tcx>,
3102 lvalue_pref: LvaluePreference,
3106 debug!(">> typechecking: expr={} expected={}",
3107 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
3109 // A generic function for doing all of the checking for call expressions
3110 fn check_call(fcx: &FnCtxt,
3111 call_expr: &ast::Expr,
3113 args: &[&P<ast::Expr>]) {
3114 // Store the type of `f` as the type of the callee
3115 let fn_ty = fcx.expr_ty(f);
3117 // Extract the function signature from `in_fty`.
3118 let fn_ty = structurally_resolved_type(fcx, f.span, fn_ty);
3120 // This is the "default" function signature, used in case of error.
3121 // In that case, we check each argument against "error" in order to
3122 // set up all the node type bindings.
3123 let error_fn_sig = ty::Binder(FnSig {
3124 inputs: err_args(fcx.tcx(), args.len()),
3125 output: ty::FnConverging(fcx.tcx().types.err),
3129 let fn_sig = match fn_ty.sty {
3130 ty::ty_bare_fn(_, &ty::BareFnTy {ref sig, ..}) |
3131 ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
3133 fcx.type_error_message(call_expr.span, |actual| {
3134 format!("expected function, found `{}`", actual)
3140 // Replace any late-bound regions that appear in the function
3141 // signature with region variables. We also have to
3142 // renormalize the associated types at this point, since they
3143 // previously appeared within a `Binder<>` and hence would not
3144 // have been normalized before.
3146 fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
3150 fcx.normalize_associated_types_in(call_expr.span,
3153 // Call the generic checker.
3154 check_argument_types(fcx,
3161 DontTupleArguments);
3163 write_call(fcx, call_expr, fn_sig.output);
3166 // Checks a method call.
3167 fn check_method_call(fcx: &FnCtxt,
3169 method_name: ast::SpannedIdent,
3170 args: &[P<ast::Expr>],
3172 lvalue_pref: LvaluePreference) {
3173 let rcvr = &*args[0];
3174 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
3176 // no need to check for bot/err -- callee does that
3177 let expr_t = structurally_resolved_type(fcx,
3179 fcx.expr_ty(&*rcvr));
3181 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
3182 let fn_ty = match method::lookup(fcx,
3184 method_name.node.name,
3190 let method_ty = method.ty;
3191 let method_call = MethodCall::expr(expr.id);
3192 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3196 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
3197 fcx.write_error(expr.id);
3202 // Call the generic checker.
3203 let args: Vec<_> = args[1..].iter().map(|x| x).collect();
3204 let ret_ty = check_method_argument_types(fcx,
3210 DontTupleArguments);
3212 write_call(fcx, expr, ret_ty);
3215 // A generic function for checking the then and else in an if
3217 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3218 cond_expr: &ast::Expr,
3219 then_blk: &ast::Block,
3220 opt_else_expr: Option<&ast::Expr>,
3223 expected: Expectation<'tcx>) {
3224 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
3226 let expected = expected.adjust_for_branches(fcx);
3227 check_block_with_expected(fcx, then_blk, expected);
3228 let then_ty = fcx.node_ty(then_blk.id);
3230 let branches_ty = match opt_else_expr {
3231 Some(ref else_expr) => {
3232 check_expr_with_expectation(fcx, &**else_expr, expected);
3233 let else_ty = fcx.expr_ty(&**else_expr);
3234 infer::common_supertype(fcx.infcx(),
3235 infer::IfExpression(sp),
3241 infer::common_supertype(fcx.infcx(),
3242 infer::IfExpressionWithNoElse(sp),
3245 ty::mk_nil(fcx.tcx()))
3249 let cond_ty = fcx.expr_ty(cond_expr);
3250 let if_ty = if ty::type_is_error(cond_ty) {
3256 fcx.write_ty(id, if_ty);
3259 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
3263 trait_did: Option<ast::DefId>,
3265 rhs: Option<&P<ast::Expr>>,
3267 autoref_args: AutorefArgs) -> Ty<'tcx> where
3270 let method = match trait_did {
3271 Some(trait_did) => {
3272 // We do eager coercions to make using operators
3275 // - If the input is of type &'a T (resp. &'a mut T),
3276 // then reborrow it to &'b T (resp. &'b mut T) where
3277 // 'b <= 'a. This makes things like `x == y`, where
3278 // `x` and `y` are both region pointers, work. We
3279 // could also solve this with variance or different
3280 // traits that don't force left and right to have same
3282 let (adj_ty, adjustment) = match lhs_ty.sty {
3283 ty::ty_rptr(r_in, mt) => {
3284 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
3285 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
3286 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
3287 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
3288 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
3289 (adjusted_ty, adjustment)
3292 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
3296 debug!("adjusted_ty={} adjustment={}",
3297 adj_ty.repr(fcx.tcx()),
3300 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
3301 trait_did, adjustment, adj_ty, None)
3305 let args = match rhs {
3306 Some(rhs) => vec![rhs],
3311 let method_ty = method.ty;
3312 // HACK(eddyb) Fully qualified path to work around a resolve bug.
3313 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
3314 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3315 match check_method_argument_types(fcx,
3321 DontTupleArguments) {
3322 ty::FnConverging(result_type) => result_type,
3323 ty::FnDiverging => fcx.tcx().types.err
3328 // Check the args anyway
3329 // so we get all the error messages
3330 let expected_ty = fcx.tcx().types.err;
3331 check_method_argument_types(fcx,
3337 DontTupleArguments);
3343 // could be either an expr_binop or an expr_assign_binop
3344 fn check_binop(fcx: &FnCtxt,
3349 is_binop_assignment: IsBinopAssignment) {
3350 let tcx = fcx.ccx.tcx;
3352 let lvalue_pref = match is_binop_assignment {
3353 BinopAssignment => PreferMutLvalue,
3354 SimpleBinop => NoPreference
3356 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
3358 // Callee does bot / err checking
3359 let lhs_t = structurally_resolved_type(fcx, lhs.span,
3360 fcx.expr_ty(&*lhs));
3362 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
3363 // Shift is a special case: rhs must be uint, no matter what lhs is
3364 check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint);
3365 fcx.write_ty(expr.id, lhs_t);
3369 if ty::is_binopable(tcx, lhs_t, op) {
3370 let tvar = fcx.infcx().next_ty_var();
3371 demand::suptype(fcx, expr.span, tvar, lhs_t);
3372 check_expr_has_type(fcx, &**rhs, tvar);
3374 let result_t = match op {
3375 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
3377 if ty::type_is_simd(tcx, lhs_t) {
3378 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
3379 fcx.type_error_message(expr.span,
3381 format!("binary comparison \
3382 operation `{}` not \
3383 supported for floating \
3384 point SIMD vector `{}`",
3385 ast_util::binop_to_string(op),
3396 fcx.tcx().types.bool
3402 fcx.write_ty(expr.id, result_t);
3406 if op == ast::BiOr || op == ast::BiAnd {
3407 // This is an error; one of the operands must have the wrong
3409 fcx.write_error(expr.id);
3410 fcx.write_error(rhs.id);
3411 fcx.type_error_message(expr.span,
3413 format!("binary operation `{}` cannot be applied \
3415 ast_util::binop_to_string(op),
3422 // Check for overloaded operators if not an assignment.
3423 let result_t = if is_binop_assignment == SimpleBinop {
3424 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3426 fcx.type_error_message(expr.span,
3428 format!("binary assignment \
3430 cannot be applied to \
3432 ast_util::binop_to_string(op),
3437 check_expr(fcx, &**rhs);
3441 fcx.write_ty(expr.id, result_t);
3442 if ty::type_is_error(result_t) {
3443 fcx.write_ty(rhs.id, result_t);
3447 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3449 lhs_expr: &ast::Expr,
3450 lhs_resolved_t: Ty<'tcx>,
3452 rhs: &P<ast::Expr>) -> Ty<'tcx> {
3453 let tcx = fcx.ccx.tcx;
3454 let lang = &tcx.lang_items;
3455 let (name, trait_did) = match op {
3456 ast::BiAdd => ("add", lang.add_trait()),
3457 ast::BiSub => ("sub", lang.sub_trait()),
3458 ast::BiMul => ("mul", lang.mul_trait()),
3459 ast::BiDiv => ("div", lang.div_trait()),
3460 ast::BiRem => ("rem", lang.rem_trait()),
3461 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3462 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3463 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3464 ast::BiShl => ("shl", lang.shl_trait()),
3465 ast::BiShr => ("shr", lang.shr_trait()),
3466 ast::BiLt => ("lt", lang.ord_trait()),
3467 ast::BiLe => ("le", lang.ord_trait()),
3468 ast::BiGe => ("ge", lang.ord_trait()),
3469 ast::BiGt => ("gt", lang.ord_trait()),
3470 ast::BiEq => ("eq", lang.eq_trait()),
3471 ast::BiNe => ("ne", lang.eq_trait()),
3472 ast::BiAnd | ast::BiOr => {
3473 check_expr(fcx, &**rhs);
3474 return tcx.types.err;
3477 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3478 trait_did, lhs_expr, Some(rhs), || {
3479 fcx.type_error_message(ex.span, |actual| {
3480 format!("binary operation `{}` cannot be applied to type `{}`",
3481 ast_util::binop_to_string(op),
3483 }, lhs_resolved_t, None)
3484 }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3487 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3490 trait_did: Option<ast::DefId>,
3492 rhs_expr: &ast::Expr,
3494 op: ast::UnOp) -> Ty<'tcx> {
3495 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3496 trait_did, rhs_expr, None, || {
3497 fcx.type_error_message(ex.span, |actual| {
3498 format!("cannot apply unary operator `{}` to type `{}`",
3501 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3504 // Check field access expressions
3505 fn check_field(fcx: &FnCtxt,
3507 lvalue_pref: LvaluePreference,
3509 field: &ast::SpannedIdent) {
3510 let tcx = fcx.ccx.tcx;
3511 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3512 let expr_t = structurally_resolved_type(fcx, expr.span,
3514 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3515 let (_, autoderefs, field_ty) =
3516 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3518 ty::ty_struct(base_id, substs) => {
3519 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3520 let fields = ty::lookup_struct_fields(tcx, base_id);
3521 lookup_field_ty(tcx, base_id, fields[],
3522 field.node.name, &(*substs))
3529 fcx.write_ty(expr.id, field_ty);
3530 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3536 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3537 fcx.type_error_message(
3540 format!("attempted to take value of method `{}` on type \
3541 `{}`", token::get_ident(field.node), actual)
3545 tcx.sess.span_help(field.span,
3546 "maybe a `()` to call it is missing? \
3547 If not, try an anonymous function");
3549 fcx.type_error_message(
3552 format!("attempted access of field `{}` on \
3553 type `{}`, but no field with that \
3555 token::get_ident(field.node),
3561 fcx.write_error(expr.id);
3564 // Check tuple index expressions
3565 fn check_tup_field(fcx: &FnCtxt,
3567 lvalue_pref: LvaluePreference,
3569 idx: codemap::Spanned<uint>) {
3570 let tcx = fcx.ccx.tcx;
3571 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3572 let expr_t = structurally_resolved_type(fcx, expr.span,
3574 let mut tuple_like = false;
3575 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3576 let (_, autoderefs, field_ty) =
3577 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3579 ty::ty_struct(base_id, substs) => {
3580 tuple_like = ty::is_tuple_struct(tcx, base_id);
3582 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3583 let fields = ty::lookup_struct_fields(tcx, base_id);
3584 lookup_tup_field_ty(tcx, base_id, fields[],
3585 idx.node, &(*substs))
3590 ty::ty_tup(ref v) => {
3592 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3599 fcx.write_ty(expr.id, field_ty);
3600 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3605 fcx.type_error_message(
3609 format!("attempted out-of-bounds tuple index `{}` on \
3614 format!("attempted tuple index `{}` on type `{}`, but the \
3615 type was not a tuple or tuple struct",
3622 fcx.write_error(expr.id);
3625 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3626 struct_ty: Ty<'tcx>,
3628 class_id: ast::DefId,
3629 node_id: ast::NodeId,
3630 substitutions: &'tcx subst::Substs<'tcx>,
3631 field_types: &[ty::field_ty],
3632 ast_fields: &[ast::Field],
3633 check_completeness: bool,
3634 enum_id_opt: Option<ast::DefId>) {
3635 let tcx = fcx.ccx.tcx;
3637 let mut class_field_map = FnvHashMap::new();
3638 let mut fields_found = 0;
3639 for field in field_types.iter() {
3640 class_field_map.insert(field.name, (field.id, false));
3643 let mut error_happened = false;
3645 // Typecheck each field.
3646 for field in ast_fields.iter() {
3647 let mut expected_field_type = tcx.types.err;
3649 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3652 fcx.type_error_message(
3654 |actual| match enum_id_opt {
3656 let variant_type = ty::enum_variant_with_id(tcx,
3659 format!("struct variant `{}::{}` has no field named `{}`",
3660 actual, variant_type.name.as_str(),
3661 token::get_ident(field.ident.node))
3664 format!("structure `{}` has no field named `{}`",
3666 token::get_ident(field.ident.node))
3671 error_happened = true;
3673 Some((_, true)) => {
3674 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3675 "field `{}` specified more than once",
3676 token::get_ident(field.ident.node));
3677 error_happened = true;
3679 Some((field_id, false)) => {
3680 expected_field_type =
3681 ty::lookup_field_type(
3682 tcx, class_id, field_id, substitutions);
3683 class_field_map.insert(
3684 field.ident.node.name, (field_id, true));
3688 // Make sure to give a type to the field even if there's
3689 // an error, so we can continue typechecking
3690 check_expr_coercable_to_type(
3693 expected_field_type);
3697 fcx.write_error(node_id);
3700 if check_completeness && !error_happened {
3701 // Make sure the programmer specified all the fields.
3702 assert!(fields_found <= field_types.len());
3703 if fields_found < field_types.len() {
3704 let mut missing_fields = Vec::new();
3705 for class_field in field_types.iter() {
3706 let name = class_field.name;
3707 let (_, seen) = class_field_map[name];
3709 missing_fields.push(
3710 format!("`{}`", token::get_name(name).get()))
3714 span_err!(tcx.sess, span, E0063,
3715 "missing field{}: {}",
3716 if missing_fields.len() == 1 {""} else {"s"},
3717 missing_fields.connect(", "));
3721 if !error_happened {
3722 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3723 class_id, substitutions));
3727 fn check_struct_constructor(fcx: &FnCtxt,
3729 span: codemap::Span,
3730 class_id: ast::DefId,
3731 fields: &[ast::Field],
3732 base_expr: Option<&ast::Expr>) {
3733 let tcx = fcx.ccx.tcx;
3735 // Generate the struct type.
3737 ty: mut struct_type,
3738 substs: struct_substs
3739 } = fcx.instantiate_type(span, class_id);
3741 // Look up and check the fields.
3742 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3743 check_struct_or_variant_fields(fcx,
3748 fcx.ccx.tcx.mk_substs(struct_substs),
3751 base_expr.is_none(),
3753 if ty::type_is_error(fcx.node_ty(id)) {
3754 struct_type = tcx.types.err;
3757 // Check the base expression if necessary.
3760 Some(base_expr) => {
3761 check_expr_has_type(fcx, &*base_expr, struct_type);
3765 // Write in the resulting type.
3766 fcx.write_ty(id, struct_type);
3769 fn check_struct_enum_variant(fcx: &FnCtxt,
3771 span: codemap::Span,
3772 enum_id: ast::DefId,
3773 variant_id: ast::DefId,
3774 fields: &[ast::Field]) {
3775 let tcx = fcx.ccx.tcx;
3777 // Look up the number of type parameters and the raw type, and
3778 // determine whether the enum is region-parameterized.
3781 substs: substitutions
3782 } = fcx.instantiate_type(span, enum_id);
3784 // Look up and check the enum variant fields.
3785 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3786 check_struct_or_variant_fields(fcx,
3791 fcx.ccx.tcx.mk_substs(substitutions),
3796 fcx.write_ty(id, enum_type);
3799 fn check_struct_fields_on_error(fcx: &FnCtxt,
3801 fields: &[ast::Field],
3802 base_expr: &Option<P<ast::Expr>>) {
3803 // Make sure to still write the types
3804 // otherwise we might ICE
3805 fcx.write_error(id);
3806 for field in fields.iter() {
3807 check_expr(fcx, &*field.expr);
3810 Some(ref base) => check_expr(fcx, &**base),
3815 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3817 let tcx = fcx.ccx.tcx;
3820 ast::ExprBox(ref opt_place, ref subexpr) => {
3821 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3822 check_expr(fcx, &**subexpr);
3824 let mut checked = false;
3825 opt_place.as_ref().map(|place| match place.node {
3826 ast::ExprPath(ref path) => {
3827 // FIXME(pcwalton): For now we hardcode the two permissible
3828 // places: the exchange heap and the managed heap.
3829 let definition = lookup_def(fcx, path.span, place.id);
3830 let def_id = definition.def_id();
3831 let referent_ty = fcx.expr_ty(&**subexpr);
3832 if tcx.lang_items.exchange_heap() == Some(def_id) {
3833 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3841 span_err!(tcx.sess, expr.span, E0066,
3842 "only the managed heap and exchange heap are currently supported");
3843 fcx.write_ty(id, tcx.types.err);
3847 ast::ExprLit(ref lit) => {
3848 let typ = check_lit(fcx, &**lit, expected);
3849 fcx.write_ty(id, typ);
3851 ast::ExprBinary(op, ref lhs, ref rhs) => {
3852 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3854 let lhs_ty = fcx.expr_ty(&**lhs);
3855 let rhs_ty = fcx.expr_ty(&**rhs);
3856 if ty::type_is_error(lhs_ty) ||
3857 ty::type_is_error(rhs_ty) {
3858 fcx.write_error(id);
3861 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3862 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3864 let lhs_t = fcx.expr_ty(&**lhs);
3865 let result_t = fcx.expr_ty(expr);
3866 demand::suptype(fcx, expr.span, result_t, lhs_t);
3868 let tcx = fcx.tcx();
3869 if !ty::expr_is_lval(tcx, &**lhs) {
3870 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3873 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3875 // Overwrite result of check_binop...this preserves existing behavior
3876 // but seems quite dubious with regard to user-defined methods
3877 // and so forth. - Niko
3878 if !ty::type_is_error(result_t) {
3879 fcx.write_nil(expr.id);
3882 ast::ExprUnary(unop, ref oprnd) => {
3883 let expected_inner = expected.map(fcx, |ty| {
3885 ast::UnUniq => match ty.sty {
3886 ty::ty_uniq(ty) => {
3887 Expectation::rvalue_hint(ty)
3893 ast::UnNot | ast::UnNeg => {
3901 let lvalue_pref = match unop {
3902 ast::UnDeref => lvalue_pref,
3905 check_expr_with_expectation_and_lvalue_pref(
3906 fcx, &**oprnd, expected_inner, lvalue_pref);
3907 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3909 if !ty::type_is_error(oprnd_t) {
3912 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3915 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3916 oprnd_t = match ty::deref(oprnd_t, true) {
3918 None => match try_overloaded_deref(fcx, expr.span,
3919 Some(MethodCall::expr(expr.id)),
3920 Some(&**oprnd), oprnd_t, lvalue_pref) {
3923 let is_newtype = match oprnd_t.sty {
3924 ty::ty_struct(did, substs) => {
3925 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3927 && fields[0].name ==
3928 token::special_idents::unnamed_field.name
3933 // This is an obsolete struct deref
3934 span_err!(tcx.sess, expr.span, E0068,
3935 "single-field tuple-structs can \
3936 no longer be dereferenced");
3938 fcx.type_error_message(expr.span, |actual| {
3939 format!("type `{}` cannot be \
3940 dereferenced", actual)
3949 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3951 if !(ty::type_is_integral(oprnd_t) ||
3952 oprnd_t.sty == ty::ty_bool) {
3953 oprnd_t = check_user_unop(fcx, "!", "not",
3954 tcx.lang_items.not_trait(),
3955 expr, &**oprnd, oprnd_t, unop);
3959 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3961 if !(ty::type_is_integral(oprnd_t) ||
3962 ty::type_is_fp(oprnd_t)) {
3963 oprnd_t = check_user_unop(fcx, "-", "neg",
3964 tcx.lang_items.neg_trait(),
3965 expr, &**oprnd, oprnd_t, unop);
3970 fcx.write_ty(id, oprnd_t);
3972 ast::ExprAddrOf(mutbl, ref oprnd) => {
3973 let expected = expected.only_has_type();
3974 let hint = expected.map(fcx, |ty| {
3976 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3977 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3978 // Lvalues may legitimately have unsized types.
3979 // For example, dereferences of a fat pointer and
3980 // the last field of a struct can be unsized.
3981 ExpectHasType(mt.ty)
3983 Expectation::rvalue_hint(mt.ty)
3989 let lvalue_pref = match mutbl {
3990 ast::MutMutable => PreferMutLvalue,
3991 ast::MutImmutable => NoPreference
3993 check_expr_with_expectation_and_lvalue_pref(fcx,
3998 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3999 let oprnd_t = if ty::type_is_error(tm.ty) {
4002 // Note: at this point, we cannot say what the best lifetime
4003 // is to use for resulting pointer. We want to use the
4004 // shortest lifetime possible so as to avoid spurious borrowck
4005 // errors. Moreover, the longest lifetime will depend on the
4006 // precise details of the value whose address is being taken
4007 // (and how long it is valid), which we don't know yet until type
4008 // inference is complete.
4010 // Therefore, here we simply generate a region variable. The
4011 // region inferencer will then select the ultimate value.
4012 // Finally, borrowck is charged with guaranteeing that the
4013 // value whose address was taken can actually be made to live
4014 // as long as it needs to live.
4016 // String literals are already, implicitly converted to slices.
4017 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
4018 // Empty slices live in static memory.
4019 ast::ExprVec(ref elements) if elements.len() == 0 => {
4020 // Note: we do not assign a lifetime of
4021 // static. This is because the resulting type
4022 // `&'static [T]` would require that T outlives
4024 let region = fcx.infcx().next_region_var(
4025 infer::AddrOfSlice(expr.span));
4026 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
4029 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
4030 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
4034 fcx.write_ty(id, oprnd_t);
4036 ast::ExprPath(ref pth) => {
4037 let defn = lookup_def(fcx, pth.span, id);
4038 let pty = type_scheme_for_def(fcx, expr.span, defn);
4039 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
4041 // We always require that the type provided as the value for
4042 // a type parameter outlives the moment of instantiation.
4043 constrain_path_type_parameters(fcx, expr);
4045 ast::ExprInlineAsm(ref ia) => {
4046 for &(_, ref input) in ia.inputs.iter() {
4047 check_expr(fcx, &**input);
4049 for &(_, ref out, _) in ia.outputs.iter() {
4050 check_expr(fcx, &**out);
4054 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
4055 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
4056 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
4057 ast::ExprRet(ref expr_opt) => {
4059 ty::FnConverging(result_type) => {
4062 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
4063 result_type, ty::mk_nil(fcx.tcx())) {
4064 span_err!(tcx.sess, expr.span, E0069,
4065 "`return;` in function returning non-nil");
4068 check_expr_coercable_to_type(fcx, &**e, result_type);
4072 ty::FnDiverging => {
4073 if let Some(ref e) = *expr_opt {
4074 check_expr(fcx, &**e);
4076 span_err!(tcx.sess, expr.span, E0166,
4077 "`return` in a function declared as diverging");
4080 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4082 ast::ExprParen(ref a) => {
4083 check_expr_with_expectation_and_lvalue_pref(fcx,
4087 fcx.write_ty(id, fcx.expr_ty(&**a));
4089 ast::ExprAssign(ref lhs, ref rhs) => {
4090 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4092 let tcx = fcx.tcx();
4093 if !ty::expr_is_lval(tcx, &**lhs) {
4094 span_err!(tcx.sess, expr.span, E0070,
4095 "illegal left-hand side expression");
4098 let lhs_ty = fcx.expr_ty(&**lhs);
4099 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
4100 let rhs_ty = fcx.expr_ty(&**rhs);
4102 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4104 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4105 fcx.write_error(id);
4110 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4111 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4112 id, expr.span, expected);
4114 ast::ExprIfLet(..) => {
4115 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
4117 ast::ExprWhile(ref cond, ref body, _) => {
4118 check_expr_has_type(fcx, &**cond, tcx.types.bool);
4119 check_block_no_value(fcx, &**body);
4120 let cond_ty = fcx.expr_ty(&**cond);
4121 let body_ty = fcx.node_ty(body.id);
4122 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4123 fcx.write_error(id);
4129 ast::ExprWhileLet(..) => {
4130 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
4132 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4133 check_expr(fcx, &**head);
4134 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4135 vtable::select_new_fcx_obligations(fcx);
4137 debug!("ExprForLoop each item has type {}",
4138 fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
4140 let pcx = pat_ctxt {
4142 map: pat_id_map(&tcx.def_map, &**pat),
4144 _match::check_pat(&pcx, &**pat, typ);
4146 check_block_no_value(fcx, &**block);
4149 ast::ExprLoop(ref body, _) => {
4150 check_block_no_value(fcx, &**body);
4151 if !may_break(tcx, expr.id, &**body) {
4152 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
4157 ast::ExprMatch(ref discrim, ref arms, match_src) => {
4158 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
4160 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
4161 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
4163 ast::ExprBlock(ref b) => {
4164 check_block_with_expected(fcx, &**b, expected);
4165 fcx.write_ty(id, fcx.node_ty(b.id));
4167 ast::ExprCall(ref f, ref args) => {
4168 // Index expressions need to be handled separately, to inform them
4169 // that they appear in call position.
4170 check_expr(fcx, &**f);
4171 let f_ty = fcx.expr_ty(&**f);
4173 let args: Vec<_> = args.iter().map(|x| x).collect();
4174 if !try_overloaded_call(fcx, expr, &**f, f_ty, args[]) {
4175 check_call(fcx, expr, &**f, args[]);
4176 let args_err = args.iter().fold(false,
4178 // is this not working?
4179 let a_ty = fcx.expr_ty(&***a);
4180 rest_err || ty::type_is_error(a_ty)});
4181 if ty::type_is_error(f_ty) || args_err {
4182 fcx.write_error(id);
4186 ast::ExprMethodCall(ident, ref tps, ref args) => {
4187 check_method_call(fcx, expr, ident, args[], tps[], lvalue_pref);
4188 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4189 let args_err = arg_tys.fold(false,
4191 rest_err || ty::type_is_error(a)});
4193 fcx.write_error(id);
4196 ast::ExprCast(ref e, ref t) => {
4197 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
4198 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
4200 check_cast(fcx, expr, &**e, &**t);
4202 ast::ExprVec(ref args) => {
4203 let uty = expected.map_to_option(fcx, |uty| {
4205 ty::ty_vec(ty, _) => Some(ty),
4210 let typ = match uty {
4212 for e in args.iter() {
4213 check_expr_coercable_to_type(fcx, &**e, uty);
4218 let t: Ty = fcx.infcx().next_ty_var();
4219 for e in args.iter() {
4220 check_expr_has_type(fcx, &**e, t);
4225 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4226 fcx.write_ty(id, typ);
4228 ast::ExprRepeat(ref element, ref count_expr) => {
4229 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
4230 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4232 let uty = match expected {
4233 ExpectHasType(uty) => {
4235 ty::ty_vec(ty, _) => Some(ty),
4242 let (element_ty, t) = match uty {
4244 check_expr_coercable_to_type(fcx, &**element, uty);
4248 let t: Ty = fcx.infcx().next_ty_var();
4249 check_expr_has_type(fcx, &**element, t);
4250 (fcx.expr_ty(&**element), t)
4255 // For [foo, ..n] where n > 1, `foo` must have
4257 fcx.require_type_meets(
4264 if ty::type_is_error(element_ty) {
4265 fcx.write_error(id);
4267 let t = ty::mk_vec(tcx, t, Some(count));
4268 fcx.write_ty(id, t);
4271 ast::ExprTup(ref elts) => {
4272 let expected = expected.only_has_type();
4273 let flds = expected.map_to_option(fcx, |ty| {
4275 ty::ty_tup(ref flds) => Some(flds[]),
4279 let mut err_field = false;
4281 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4282 let t = match flds {
4283 Some(ref fs) if i < fs.len() => {
4285 check_expr_coercable_to_type(fcx, &**e, ety);
4289 check_expr_with_expectation(fcx, &**e, NoExpectation);
4293 err_field = err_field || ty::type_is_error(t);
4297 fcx.write_error(id);
4299 let typ = ty::mk_tup(tcx, elt_ts);
4300 fcx.write_ty(id, typ);
4303 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4304 // Resolve the path.
4305 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
4306 let struct_id = match def {
4307 Some(def::DefVariant(enum_id, variant_id, true)) => {
4308 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4309 variant_id, fields[]);
4312 Some(def::DefTrait(def_id)) => {
4313 span_err!(tcx.sess, path.span, E0159,
4314 "use of trait `{}` as a struct constructor",
4315 pprust::path_to_string(path));
4316 check_struct_fields_on_error(fcx,
4323 // Verify that this was actually a struct.
4324 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4326 ty::ty_struct(struct_did, _) => {
4327 check_struct_constructor(fcx,
4332 base_expr.as_ref().map(|e| &**e));
4335 span_err!(tcx.sess, path.span, E0071,
4336 "`{}` does not name a structure",
4337 pprust::path_to_string(path));
4338 check_struct_fields_on_error(fcx,
4348 tcx.sess.span_bug(path.span,
4349 "structure constructor wasn't resolved")
4353 // Turn the path into a type and verify that that type unifies with
4354 // the resulting structure type. This is needed to handle type
4355 // parameters correctly.
4356 let actual_structure_type = fcx.expr_ty(&*expr);
4357 if !ty::type_is_error(actual_structure_type) {
4358 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4362 match fcx.mk_subty(false,
4363 infer::Misc(path.span),
4364 actual_structure_type,
4365 type_and_substs.ty) {
4367 Err(type_error) => {
4368 let type_error_description =
4369 ty::type_err_to_str(tcx, &type_error);
4372 .span_err(path.span,
4373 format!("structure constructor specifies a \
4374 structure of type `{}`, but this \
4375 structure has type `{}`: {}",
4377 .ty_to_string(type_and_substs.ty),
4380 actual_structure_type),
4381 type_error_description)[]);
4382 ty::note_and_explain_type_err(tcx, &type_error);
4387 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4389 ast::ExprField(ref base, ref field) => {
4390 check_field(fcx, expr, lvalue_pref, &**base, field);
4392 ast::ExprTupField(ref base, idx) => {
4393 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
4395 ast::ExprIndex(ref base, ref idx) => {
4396 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4397 let base_t = fcx.expr_ty(&**base);
4398 if ty::type_is_error(base_t) {
4399 fcx.write_ty(id, base_t);
4402 ast::ExprRange(ref start, ref end) => {
4403 // A slice, rather than an index. Special cased for now (KILLME).
4404 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
4407 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
4408 try_overloaded_slice_step(fcx,
4409 MethodCall::expr(expr.id),
4419 let mut args = vec![];
4420 start.as_ref().map(|x| args.push(x));
4421 end.as_ref().map(|x| args.push(x));
4424 Some((index_ty, element_ty)) => {
4425 for a in args.iter() {
4426 check_expr_has_type(fcx, &***a, index_ty);
4428 fcx.write_ty(idx.id, element_ty);
4429 fcx.write_ty(id, element_ty)
4432 for a in args.iter() {
4433 check_expr(fcx, &***a);
4435 fcx.type_error_message(expr.span,
4437 format!("cannot take a slice of a value with type `{}`",
4442 fcx.write_ty(idx.id, fcx.tcx().types.err);
4443 fcx.write_ty(id, fcx.tcx().types.err);
4448 check_expr(fcx, &**idx);
4449 let idx_t = fcx.expr_ty(&**idx);
4450 if ty::type_is_error(idx_t) {
4451 fcx.write_ty(id, idx_t);
4453 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
4456 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
4458 MethodCall::expr(expr.id),
4467 Some((index_ty, element_ty)) => {
4468 check_expr_has_type(fcx, &**idx, index_ty);
4469 fcx.write_ty(id, element_ty);
4472 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
4473 fcx.type_error_message(
4476 format!("cannot index a value of type `{}`",
4481 fcx.write_ty(id, fcx.tcx().types.err);
4489 ast::ExprRange(ref start, ref end) => {
4490 let t_start = start.as_ref().map(|e| {
4491 check_expr(fcx, &**e);
4494 let t_end = end.as_ref().map(|e| {
4495 check_expr(fcx, &**e);
4499 let idx_type = match (t_start, t_end) {
4500 (Some(ty), None) | (None, Some(ty)) => {
4503 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
4504 ty::type_is_error(t_end)) => {
4505 Some(fcx.tcx().types.err)
4507 (Some(t_start), Some(t_end)) => {
4508 Some(infer::common_supertype(fcx.infcx(),
4509 infer::RangeExpression(expr.span),
4517 // Note that we don't check the type of start/end satisfy any
4518 // bounds because right the range structs do not have any. If we add
4519 // some bounds, then we'll need to check `t_start` against them here.
4521 let range_type = match idx_type {
4522 Some(idx_type) if ty::type_is_error(idx_type) => {
4526 // Find the did from the appropriate lang item.
4527 let did = match (start, end) {
4528 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
4529 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
4530 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4532 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4536 if let Some(did) = did {
4537 let polytype = ty::lookup_item_type(tcx, did);
4538 let substs = Substs::new_type(vec![idx_type], vec![]);
4539 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4540 fcx.add_obligations_for_parameters(
4541 traits::ObligationCause::new(expr.span,
4543 traits::ItemObligation(did)),
4546 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4548 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4553 // Neither start nor end => FullRange
4554 if let Some(did) = tcx.lang_items.full_range_struct() {
4555 let substs = Substs::new_type(vec![], vec![]);
4556 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4558 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4564 fcx.write_ty(id, range_type);
4569 debug!("type of expr({}) {} is...", expr.id,
4570 syntax::print::pprust::expr_to_string(expr));
4571 debug!("... {}, expected is {}",
4572 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4573 expected.repr(tcx));
4578 fn constrain_path_type_parameters(fcx: &FnCtxt,
4581 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4582 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4586 impl<'tcx> Expectation<'tcx> {
4587 /// Provide an expectation for an rvalue expression given an *optional*
4588 /// hint, which is not required for type safety (the resulting type might
4589 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4590 /// is useful in determining the concrete type.
4592 /// The primary use case is where the expected type is a fat pointer,
4593 /// like `&[int]`. For example, consider the following statement:
4595 /// let x: &[int] = &[1, 2, 3];
4597 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4598 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4599 /// expectation `ExpectHasType([int])`, that would be too strong --
4600 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4601 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4602 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4603 /// which still is useful, because it informs integer literals and the like.
4604 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4605 /// for examples of where this comes up,.
4606 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4608 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4609 ExpectRvalueLikeUnsized(ty)
4611 _ => ExpectHasType(ty)
4615 fn only_has_type(self) -> Expectation<'tcx> {
4617 ExpectHasType(t) => ExpectHasType(t),
4622 // Resolves `expected` by a single level if it is a variable. If
4623 // there is no expected type or resolution is not possible (e.g.,
4624 // no constraints yet present), just returns `None`.
4625 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4630 ExpectCastableToType(t) => {
4631 ExpectCastableToType(
4632 fcx.infcx().resolve_type_vars_if_possible(&t))
4634 ExpectHasType(t) => {
4636 fcx.infcx().resolve_type_vars_if_possible(&t))
4638 ExpectRvalueLikeUnsized(t) => {
4639 ExpectRvalueLikeUnsized(
4640 fcx.infcx().resolve_type_vars_if_possible(&t))
4645 fn map<'a, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Expectation<'tcx> where
4646 F: FnOnce(Ty<'tcx>) -> Expectation<'tcx>
4648 match self.resolve(fcx) {
4649 NoExpectation => NoExpectation,
4650 ExpectCastableToType(ty) |
4652 ExpectRvalueLikeUnsized(ty) => unpack(ty),
4656 fn map_to_option<'a, O, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Option<O> where
4657 F: FnOnce(Ty<'tcx>) -> Option<O>,
4659 match self.resolve(fcx) {
4660 NoExpectation => None,
4661 ExpectCastableToType(ty) |
4663 ExpectRvalueLikeUnsized(ty) => unpack(ty),
4668 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4669 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4671 NoExpectation => format!("NoExpectation"),
4672 ExpectHasType(t) => format!("ExpectHasType({})",
4674 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4676 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4682 pub fn check_decl_initializer(fcx: &FnCtxt,
4686 let local_ty = fcx.local_ty(init.span, nid);
4687 check_expr_coercable_to_type(fcx, init, local_ty)
4690 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4691 let tcx = fcx.ccx.tcx;
4693 let t = fcx.local_ty(local.span, local.id);
4694 fcx.write_ty(local.id, t);
4696 if let Some(ref init) = local.init {
4697 check_decl_initializer(fcx, local.id, &**init);
4698 let init_ty = fcx.expr_ty(&**init);
4699 if ty::type_is_error(init_ty) {
4700 fcx.write_ty(local.id, init_ty);
4704 let pcx = pat_ctxt {
4706 map: pat_id_map(&tcx.def_map, &*local.pat),
4708 _match::check_pat(&pcx, &*local.pat, t);
4709 let pat_ty = fcx.node_ty(local.pat.id);
4710 if ty::type_is_error(pat_ty) {
4711 fcx.write_ty(local.id, pat_ty);
4715 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4717 let mut saw_bot = false;
4718 let mut saw_err = false;
4720 ast::StmtDecl(ref decl, id) => {
4723 ast::DeclLocal(ref l) => {
4724 check_decl_local(fcx, &**l);
4725 let l_t = fcx.node_ty(l.id);
4726 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4727 saw_err = saw_err || ty::type_is_error(l_t);
4729 ast::DeclItem(_) => {/* ignore for now */ }
4732 ast::StmtExpr(ref expr, id) => {
4734 // Check with expected type of ()
4735 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4736 let expr_ty = fcx.expr_ty(&**expr);
4737 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4738 saw_err = saw_err || ty::type_is_error(expr_ty);
4740 ast::StmtSemi(ref expr, id) => {
4742 check_expr(fcx, &**expr);
4743 let expr_ty = fcx.expr_ty(&**expr);
4744 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4745 saw_err |= ty::type_is_error(expr_ty);
4747 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4750 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4753 fcx.write_error(node_id);
4756 fcx.write_nil(node_id)
4760 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4761 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4762 let blkty = fcx.node_ty(blk.id);
4763 if ty::type_is_error(blkty) {
4764 fcx.write_error(blk.id);
4766 let nilty = ty::mk_nil(fcx.tcx());
4767 demand::suptype(fcx, blk.span, nilty, blkty);
4771 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4773 expected: Expectation<'tcx>) {
4775 let mut fcx_ps = fcx.ps.borrow_mut();
4776 let unsafety_state = fcx_ps.recurse(blk);
4777 replace(&mut *fcx_ps, unsafety_state)
4780 let mut warned = false;
4781 let mut any_diverges = false;
4782 let mut any_err = false;
4783 for s in blk.stmts.iter() {
4784 check_stmt(fcx, &**s);
4785 let s_id = ast_util::stmt_id(&**s);
4786 let s_ty = fcx.node_ty(s_id);
4787 if any_diverges && !warned && match s.node {
4788 ast::StmtDecl(ref decl, _) => {
4790 ast::DeclLocal(_) => true,
4794 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4800 .add_lint(lint::builtin::UNREACHABLE_CODE,
4803 "unreachable statement".to_string());
4806 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4807 any_err = any_err || ty::type_is_error(s_ty);
4810 None => if any_err {
4811 fcx.write_error(blk.id);
4812 } else if any_diverges {
4813 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4815 fcx.write_nil(blk.id);
4818 if any_diverges && !warned {
4822 .add_lint(lint::builtin::UNREACHABLE_CODE,
4825 "unreachable expression".to_string());
4827 let ety = match expected {
4828 ExpectHasType(ety) => {
4829 check_expr_coercable_to_type(fcx, &**e, ety);
4833 check_expr_with_expectation(fcx, &**e, expected);
4839 fcx.write_error(blk.id);
4840 } else if any_diverges {
4841 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4843 fcx.write_ty(blk.id, ety);
4848 *fcx.ps.borrow_mut() = prev;
4851 /// Checks a constant appearing in a type. At the moment this is just the
4852 /// length expression in a fixed-length vector, but someday it might be
4853 /// extended to type-level numeric literals.
4854 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4856 expected_type: Ty<'tcx>) {
4857 let inh = static_inherited_fields(ccx);
4858 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4859 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4862 fn check_const(ccx: &CrateCtxt,
4866 let inh = static_inherited_fields(ccx);
4867 let rty = ty::node_id_to_type(ccx.tcx, id);
4868 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4869 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4870 check_const_with_ty(&fcx, sp, e, declty);
4873 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4877 // Gather locals in statics (because of block expressions).
4878 // This is technically unnecessary because locals in static items are forbidden,
4879 // but prevents type checking from blowing up before const checking can properly
4881 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4883 check_expr_with_hint(fcx, e, declty);
4884 demand::coerce(fcx, e.span, declty, e);
4885 vtable::select_all_fcx_obligations_or_error(fcx);
4886 regionck::regionck_expr(fcx, e);
4887 writeback::resolve_type_vars_in_expr(fcx, e);
4890 /// Checks whether a type can be represented in memory. In particular, it
4891 /// identifies types that contain themselves without indirection through a
4892 /// pointer, which would mean their size is unbounded. This is different from
4893 /// the question of whether a type can be instantiated. See the definition of
4894 /// `check_instantiable`.
4895 pub fn check_representable(tcx: &ty::ctxt,
4897 item_id: ast::NodeId,
4898 designation: &str) -> bool {
4899 let rty = ty::node_id_to_type(tcx, item_id);
4901 // Check that it is possible to represent this type. This call identifies
4902 // (1) types that contain themselves and (2) types that contain a different
4903 // recursive type. It is only necessary to throw an error on those that
4904 // contain themselves. For case 2, there must be an inner type that will be
4905 // caught by case 1.
4906 match ty::is_type_representable(tcx, sp, rty) {
4907 ty::SelfRecursive => {
4908 span_err!(tcx.sess, sp, E0072,
4909 "illegal recursive {} type; \
4910 wrap the inner value in a box to make it representable",
4914 ty::Representable | ty::ContainsRecursive => (),
4919 /// Checks whether a type can be created without an instance of itself.
4920 /// This is similar but different from the question of whether a type
4921 /// can be represented. For example, the following type:
4923 /// enum foo { None, Some(foo) }
4925 /// is instantiable but is not representable. Similarly, the type
4927 /// enum foo { Some(@foo) }
4929 /// is representable, but not instantiable.
4930 pub fn check_instantiable(tcx: &ty::ctxt,
4932 item_id: ast::NodeId)
4934 let item_ty = ty::node_id_to_type(tcx, item_id);
4935 if !ty::is_instantiable(tcx, item_ty) {
4936 span_err!(tcx.sess, sp, E0073,
4937 "this type cannot be instantiated without an \
4938 instance of itself");
4939 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4940 ppaux::ty_to_string(tcx, item_ty));
4947 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4948 let t = ty::node_id_to_type(tcx, id);
4949 if ty::type_needs_subst(t) {
4950 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4954 ty::ty_struct(did, substs) => {
4955 let fields = ty::lookup_struct_fields(tcx, did);
4956 if fields.is_empty() {
4957 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4960 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4961 if !fields.iter().all(
4962 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4963 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4966 if !ty::type_is_machine(e) {
4967 span_err!(tcx.sess, sp, E0077,
4968 "SIMD vector element type should be machine type");
4976 pub fn check_enum_variants(ccx: &CrateCtxt,
4978 vs: &[P<ast::Variant>],
4981 fn disr_in_range(ccx: &CrateCtxt,
4983 disr: ty::Disr) -> bool {
4984 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4986 ast::TyU8 => disr as u8 as Disr == disr,
4987 ast::TyU16 => disr as u16 as Disr == disr,
4988 ast::TyU32 => disr as u32 as Disr == disr,
4989 ast::TyU64 => disr as u64 as Disr == disr,
4990 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4993 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4995 ast::TyI8 => disr as i8 as Disr == disr,
4996 ast::TyI16 => disr as i16 as Disr == disr,
4997 ast::TyI32 => disr as i32 as Disr == disr,
4998 ast::TyI64 => disr as i64 as Disr == disr,
4999 ast::TyI => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
5003 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
5004 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
5008 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5009 vs: &[P<ast::Variant>],
5011 hint: attr::ReprAttr)
5012 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
5014 let rty = ty::node_id_to_type(ccx.tcx, id);
5015 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
5016 let mut disr_vals: Vec<ty::Disr> = Vec::new();
5017 let mut prev_disr_val: Option<ty::Disr> = None;
5019 for v in vs.iter() {
5021 // If the discriminant value is specified explicitly in the enum check whether the
5022 // initialization expression is valid, otherwise use the last value plus one.
5023 let mut current_disr_val = match prev_disr_val {
5024 Some(prev_disr_val) => prev_disr_val + 1,
5025 None => ty::INITIAL_DISCRIMINANT_VALUE
5028 match v.node.disr_expr {
5030 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
5032 let inh = static_inherited_fields(ccx);
5033 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
5034 let declty = match hint {
5035 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
5036 attr::ReprInt(_, attr::SignedInt(ity)) => {
5037 ty::mk_mach_int(fcx.tcx(), ity)
5039 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
5040 ty::mk_mach_uint(fcx.tcx(), ity)
5043 check_const_with_ty(&fcx, e.span, &**e, declty);
5044 // check_expr (from check_const pass) doesn't guarantee
5045 // that the expression is in a form that eval_const_expr can
5046 // handle, so we may still get an internal compiler error
5048 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
5049 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
5050 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
5052 span_err!(ccx.tcx.sess, e.span, E0079,
5053 "expected signed integer constant");
5056 span_err!(ccx.tcx.sess, e.span, E0080,
5057 "expected constant: {}", *err);
5064 // Check for duplicate discriminant values
5065 match disr_vals.iter().position(|&x| x == current_disr_val) {
5067 span_err!(ccx.tcx.sess, v.span, E0081,
5068 "discriminant value `{}` already exists", disr_vals[i]);
5069 span_note!(ccx.tcx.sess, ccx.tcx().map.span(variants[i].id.node),
5070 "conflicting discriminant here")
5074 // Check for unrepresentable discriminant values
5076 attr::ReprAny | attr::ReprExtern => (),
5077 attr::ReprInt(sp, ity) => {
5078 if !disr_in_range(ccx, ity, current_disr_val) {
5079 span_err!(ccx.tcx.sess, v.span, E0082,
5080 "discriminant value outside specified type");
5081 span_note!(ccx.tcx.sess, sp,
5082 "discriminant type specified here");
5085 attr::ReprPacked => {
5086 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
5089 disr_vals.push(current_disr_val);
5091 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
5093 prev_disr_val = Some(current_disr_val);
5095 variants.push(variant_info);
5101 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
5102 [].get(0).unwrap_or(&attr::ReprAny);
5104 if hint != attr::ReprAny && vs.len() <= 1 {
5106 span_err!(ccx.tcx.sess, sp, E0083,
5107 "unsupported representation for univariant enum");
5109 span_err!(ccx.tcx.sess, sp, E0084,
5110 "unsupported representation for zero-variant enum");
5114 let variants = do_check(ccx, vs, id, hint);
5116 // cache so that ty::enum_variants won't repeat this work
5117 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
5119 check_representable(ccx.tcx, sp, id, "enum");
5121 // Check that it is possible to instantiate this enum:
5123 // This *sounds* like the same that as representable, but it's
5124 // not. See def'n of `check_instantiable()` for details.
5125 check_instantiable(ccx.tcx, sp, id);
5128 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
5129 lookup_def_ccx(fcx.ccx, sp, id)
5132 // Returns the type parameter count and the type for the given definition.
5133 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5136 -> TypeScheme<'tcx> {
5138 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
5139 let typ = fcx.local_ty(sp, nid);
5140 return no_params(typ);
5142 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
5143 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
5144 def::DefStruct(id) | def::DefConst(id) => {
5145 return ty::lookup_item_type(fcx.ccx.tcx, id);
5149 def::DefAssociatedTy(..) |
5150 def::DefAssociatedPath(..) |
5152 def::DefTyParam(..) => {
5153 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
5155 def::DefMod(..) | def::DefForeignMod(..) => {
5156 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
5158 def::DefUse(..) => {
5159 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
5161 def::DefRegion(..) => {
5162 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
5164 def::DefTyParamBinder(..) => {
5165 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
5167 def::DefLabel(..) => {
5168 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
5170 def::DefSelfTy(..) => {
5171 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5176 // Instantiates the given path, which must refer to an item with the given
5177 // number of type parameters and type.
5178 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5180 type_scheme: TypeScheme<'tcx>,
5183 node_id: ast::NodeId) {
5184 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
5185 path.repr(fcx.tcx()),
5186 def.repr(fcx.tcx()),
5188 type_scheme.repr(fcx.tcx()));
5190 // We need to extract the type parameters supplied by the user in
5191 // the path `path`. Due to the current setup, this is a bit of a
5192 // tricky-process; the problem is that resolve only tells us the
5193 // end-point of the path resolution, and not the intermediate steps.
5194 // Luckily, we can (at least for now) deduce the intermediate steps
5195 // just from the end-point.
5197 // There are basically three cases to consider:
5199 // 1. Reference to a *type*, such as a struct or enum:
5201 // mod a { struct Foo<T> { ... } }
5203 // Because we don't allow types to be declared within one
5204 // another, a path that leads to a type will always look like
5205 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
5206 // that only the final segment can have type parameters, and
5207 // they are located in the TypeSpace.
5209 // *Note:* Generally speaking, references to types don't
5210 // actually pass through this function, but rather the
5211 // `ast_ty_to_ty` function in `astconv`. However, in the case
5212 // of struct patterns (and maybe literals) we do invoke
5213 // `instantiate_path` to get the general type of an instance of
5214 // a struct. (In these cases, there are actually no type
5215 // parameters permitted at present, but perhaps we will allow
5216 // them in the future.)
5218 // 1b. Reference to a enum variant or tuple-like struct:
5220 // struct foo<T>(...)
5221 // enum E<T> { foo(...) }
5223 // In these cases, the parameters are declared in the type
5226 // 2. Reference to a *fn item*:
5230 // In this case, the path will again always have the form
5231 // `a::b::foo::<T>` where only the final segment should have
5232 // type parameters. However, in this case, those parameters are
5233 // declared on a value, and hence are in the `FnSpace`.
5235 // 3. Reference to a *method*:
5237 // impl<A> SomeStruct<A> {
5241 // Here we can have a path like
5242 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5243 // may appear in two places. The penultimate segment,
5244 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5245 // final segment, `foo::<B>` contains parameters in fn space.
5247 // The first step then is to categorize the segments appropriately.
5249 assert!(path.segments.len() >= 1);
5250 let mut segment_spaces: Vec<_>;
5252 // Case 1 and 1b. Reference to a *type* or *enum variant*.
5253 def::DefSelfTy(..) |
5254 def::DefStruct(..) |
5255 def::DefVariant(..) |
5256 def::DefTyParamBinder(..) |
5258 def::DefAssociatedTy(..) |
5259 def::DefAssociatedPath(..) |
5261 def::DefPrimTy(..) |
5262 def::DefTyParam(..) => {
5263 // Everything but the final segment should have no
5264 // parameters at all.
5265 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
5266 segment_spaces.push(Some(subst::TypeSpace));
5269 // Case 2. Reference to a top-level value.
5272 def::DefStatic(..) => {
5273 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
5274 segment_spaces.push(Some(subst::FnSpace));
5277 // Case 3. Reference to a method.
5278 def::DefStaticMethod(_, providence) |
5279 def::DefMethod(_, _, providence) => {
5280 assert!(path.segments.len() >= 2);
5283 def::FromTrait(trait_did) => {
5284 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
5286 def::FromImpl(_) => {}
5289 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
5290 segment_spaces.push(Some(subst::TypeSpace));
5291 segment_spaces.push(Some(subst::FnSpace));
5294 // Other cases. Various nonsense that really shouldn't show up
5295 // here. If they do, an error will have been reported
5296 // elsewhere. (I hope)
5298 def::DefForeignMod(..) |
5301 def::DefRegion(..) |
5303 def::DefUpvar(..) => {
5304 segment_spaces = repeat(None).take(path.segments.len()).collect();
5307 assert_eq!(segment_spaces.len(), path.segments.len());
5309 debug!("segment_spaces={}", segment_spaces);
5311 // Next, examine the definition, and determine how many type
5312 // parameters we expect from each space.
5313 let type_defs = &type_scheme.generics.types;
5314 let region_defs = &type_scheme.generics.regions;
5316 // Now that we have categorized what space the parameters for each
5317 // segment belong to, let's sort out the parameters that the user
5318 // provided (if any) into their appropriate spaces. We'll also report
5319 // errors if type parameters are provided in an inappropriate place.
5320 let mut substs = Substs::empty();
5321 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5324 report_error_if_segment_contains_type_parameters(fcx, segment);
5328 push_explicit_parameters_from_segment_to_substs(fcx,
5339 // Now we have to compare the types that the user *actually*
5340 // provided against the types that were *expected*. If the user
5341 // did not provide any types, then we want to substitute inference
5342 // variables. If the user provided some types, we may still need
5343 // to add defaults. If the user provided *too many* types, that's
5345 for &space in ParamSpace::all().iter() {
5346 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5347 assert_eq!(substs.types.len(space), type_defs.len(space));
5349 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5350 assert_eq!(substs.regions().len(space), region_defs.len(space));
5353 // The things we are substituting into the type should not contain
5354 // escaping late-bound regions, and nor should the base type scheme.
5355 assert!(!substs.has_regions_escaping_depth(0));
5356 assert!(!type_scheme.has_escaping_regions());
5358 // Add all the obligations that are required, substituting and
5359 // normalized appropriately.
5360 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
5361 fcx.add_obligations_for_parameters(
5362 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
5365 // Substitute the values for the type parameters into the type of
5366 // the referenced item.
5367 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
5369 fcx.write_ty(node_id, ty_substituted);
5370 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
5373 fn report_error_if_segment_contains_type_parameters(
5375 segment: &ast::PathSegment)
5377 for typ in segment.parameters.types().iter() {
5378 span_err!(fcx.tcx().sess, typ.span, E0085,
5379 "type parameters may not appear here");
5383 for lifetime in segment.parameters.lifetimes().iter() {
5384 span_err!(fcx.tcx().sess, lifetime.span, E0086,
5385 "lifetime parameters may not appear here");
5390 /// Finds the parameters that the user provided and adds them to `substs`. If too many
5391 /// parameters are provided, then reports an error and clears the output vector.
5393 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
5394 /// use inference variables. This seems less likely to lead to derived errors.
5396 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
5397 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
5398 /// here because we can easily use the precise span of the N+1'th parameter.
5399 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
5400 fcx: &FnCtxt<'a, 'tcx>,
5401 space: subst::ParamSpace,
5403 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5404 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5405 segment: &ast::PathSegment,
5406 substs: &mut Substs<'tcx>)
5408 match segment.parameters {
5409 ast::AngleBracketedParameters(ref data) => {
5410 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
5411 fcx, space, type_defs, region_defs, data, substs);
5414 ast::ParenthesizedParameters(ref data) => {
5415 fcx.tcx().sess.span_err(
5417 "parenthesized parameters may only be used with a trait");
5418 push_explicit_parenthesized_parameters_from_segment_to_substs(
5419 fcx, space, span, type_defs, data, substs);
5424 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
5425 fcx: &FnCtxt<'a, 'tcx>,
5426 space: subst::ParamSpace,
5427 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5428 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5429 data: &ast::AngleBracketedParameterData,
5430 substs: &mut Substs<'tcx>)
5433 let type_count = type_defs.len(space);
5434 assert_eq!(substs.types.len(space), 0);
5435 for (i, typ) in data.types.iter().enumerate() {
5436 let t = fcx.to_ty(&**typ);
5438 substs.types.push(space, t);
5439 } else if i == type_count {
5440 span_err!(fcx.tcx().sess, typ.span, E0087,
5441 "too many type parameters provided: \
5442 expected at most {} parameter(s), \
5443 found {} parameter(s)",
5444 type_count, data.types.len());
5445 substs.types.truncate(space, 0);
5451 if data.bindings.len() > 0 {
5452 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
5453 "unexpected binding of associated item in expression path \
5454 (only allowed in type paths)");
5458 let region_count = region_defs.len(space);
5459 assert_eq!(substs.regions().len(space), 0);
5460 for (i, lifetime) in data.lifetimes.iter().enumerate() {
5461 let r = ast_region_to_region(fcx.tcx(), lifetime);
5462 if i < region_count {
5463 substs.mut_regions().push(space, r);
5464 } else if i == region_count {
5465 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5466 "too many lifetime parameters provided: \
5467 expected {} parameter(s), found {} parameter(s)",
5469 data.lifetimes.len());
5470 substs.mut_regions().truncate(space, 0);
5478 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
5479 /// but intended for `Foo(A,B) -> C` form. This expands to
5480 /// roughly the same thing as `Foo<(A,B),C>`. One important
5481 /// difference has to do with the treatment of anonymous
5482 /// regions, which are translated into bound regions (NYI).
5483 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
5484 fcx: &FnCtxt<'a, 'tcx>,
5485 space: subst::ParamSpace,
5487 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5488 data: &ast::ParenthesizedParameterData,
5489 substs: &mut Substs<'tcx>)
5491 let type_count = type_defs.len(space);
5493 span_err!(fcx.tcx().sess, span, E0167,
5494 "parenthesized form always supplies 2 type parameters, \
5495 but only {} parameter(s) were expected",
5499 let input_tys: Vec<Ty> =
5500 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
5503 ty::mk_tup(fcx.tcx(), input_tys);
5505 if type_count >= 1 {
5506 substs.types.push(space, tuple_ty);
5509 let output_ty: Option<Ty> =
5510 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
5513 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
5515 if type_count >= 2 {
5516 substs.types.push(space, output_ty);
5520 fn adjust_type_parameters<'a, 'tcx>(
5521 fcx: &FnCtxt<'a, 'tcx>,
5524 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5525 substs: &mut Substs<'tcx>)
5527 let provided_len = substs.types.len(space);
5528 let desired = defs.get_slice(space);
5529 let required_len = desired.iter()
5530 .take_while(|d| d.default.is_none())
5533 debug!("adjust_type_parameters(space={}, \
5542 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5543 assert!(provided_len <= desired.len());
5545 // Nothing specified at all: supply inference variables for
5547 if provided_len == 0 {
5548 substs.types.replace(space,
5549 fcx.infcx().next_ty_vars(desired.len()));
5553 // Too few parameters specified: report an error and use Err
5555 if provided_len < required_len {
5557 if desired.len() != required_len { "at least " } else { "" };
5558 span_err!(fcx.tcx().sess, span, E0089,
5559 "too few type parameters provided: expected {}{} parameter(s) \
5560 , found {} parameter(s)",
5561 qualifier, required_len, provided_len);
5562 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5566 // Otherwise, add in any optional parameters that the user
5567 // omitted. The case of *too many* parameters is handled
5569 // push_explicit_parameters_from_segment_to_substs(). Note
5570 // that the *default* type are expressed in terms of all prior
5571 // parameters, so we have to substitute as we go with the
5572 // partial substitution that we have built up.
5573 for i in range(provided_len, desired.len()) {
5574 let default = desired[i].default.unwrap();
5575 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5576 substs.types.push(space, default);
5578 assert_eq!(substs.types.len(space), desired.len());
5580 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5583 fn adjust_region_parameters(
5587 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5588 substs: &mut Substs)
5590 let provided_len = substs.mut_regions().len(space);
5591 let desired = defs.get_slice(space);
5593 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5594 assert!(provided_len <= desired.len());
5596 // If nothing was provided, just use inference variables.
5597 if provided_len == 0 {
5598 substs.mut_regions().replace(
5600 fcx.infcx().region_vars_for_defs(span, desired));
5604 // If just the right number were provided, everybody is happy.
5605 if provided_len == desired.len() {
5609 // Otherwise, too few were provided. Report an error and then
5610 // use inference variables.
5611 span_err!(fcx.tcx().sess, span, E0090,
5612 "too few lifetime parameters provided: expected {} parameter(s), \
5613 found {} parameter(s)",
5614 desired.len(), provided_len);
5616 substs.mut_regions().replace(
5618 fcx.infcx().region_vars_for_defs(span, desired));
5622 // Resolves `typ` by a single level if `typ` is a type variable. If no
5623 // resolution is possible, then an error is reported.
5624 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5625 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5626 // If `ty` is a type variable, see whether we already know what it is.
5627 ty = fcx.infcx().shallow_resolve(ty);
5629 // If not, try resolve pending fcx obligations. Those can shed light.
5631 // FIXME(#18391) -- This current strategy can lead to bad performance in
5632 // extreme cases. We probably ought to smarter in general about
5633 // only resolving when we need help and only resolving obligations
5634 // will actually help.
5635 if ty::type_is_ty_var(ty) {
5636 vtable::select_fcx_obligations_where_possible(fcx);
5637 ty = fcx.infcx().shallow_resolve(ty);
5641 if ty::type_is_ty_var(ty) {
5642 fcx.type_error_message(sp, |_actual| {
5643 "the type of this value must be known in this \
5644 context".to_string()
5646 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5647 ty = fcx.tcx().types.err;
5653 // Returns true if b contains a break that can exit from b
5654 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5655 // First: is there an unlabeled break immediately
5657 (loop_query(&*b, |e| {
5659 ast::ExprBreak(_) => true,
5663 // Second: is there a labeled break with label
5664 // <id> nested anywhere inside the loop?
5665 (block_query(b, |e| {
5667 ast::ExprBreak(Some(_)) => {
5668 match cx.def_map.borrow().get(&e.id) {
5669 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5677 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5679 tps: &OwnedSlice<ast::TyParam>,
5681 debug!("check_bounds_are_used(n_tps={}, ty={})",
5682 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5684 // make a vector of booleans initially false, set to true when used
5685 if tps.len() == 0u { return; }
5686 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5688 ty::walk_ty(ty, |t| {
5690 ty::ty_param(ParamTy {idx, ..}) => {
5691 debug!("Found use of ty param num {}", idx);
5692 tps_used[idx as uint] = true;
5698 for (i, b) in tps_used.iter().enumerate() {
5700 span_err!(ccx.tcx.sess, span, E0091,
5701 "type parameter `{}` is unused",
5702 token::get_ident(tps[i].ident));
5707 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5708 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5709 let name = token::intern(format!("P{}", n).as_slice());
5710 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5714 let name = token::get_ident(it.ident);
5715 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5716 let split : Vec<&str> = name.get().split('_').collect();
5717 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5719 //We only care about the operation here
5720 let (n_tps, inputs, output) = match split[1] {
5721 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5725 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5727 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5730 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5731 "min" | "umax" | "umin" => {
5732 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5736 (0, Vec::new(), ty::mk_nil(tcx))
5739 span_err!(tcx.sess, it.span, E0092,
5740 "unrecognized atomic operation function: `{}`", op);
5744 (n_tps, inputs, ty::FnConverging(output))
5745 } else if name.get() == "abort" || name.get() == "unreachable" {
5746 (0, Vec::new(), ty::FnDiverging)
5748 let (n_tps, inputs, output) = match name.get() {
5749 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5751 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5752 "init" => (1u, Vec::new(), param(ccx, 0)),
5753 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5754 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5755 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5756 "move_val_init" => {
5759 ty::mk_mut_rptr(tcx,
5760 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5767 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5768 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5771 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5773 Err(s) => { tcx.sess.span_fatal(it.span, s[]); }
5775 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5777 mutbl: ast::MutImmutable
5779 (1u, Vec::new(), td_ptr)
5782 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5786 ty::mk_struct(ccx.tcx, did,
5787 ccx.tcx.mk_substs(subst::Substs::empty()))),
5789 tcx.sess.span_fatal(it.span, msg[]);
5796 ty::mk_ptr(tcx, ty::mt {
5798 mutbl: ast::MutImmutable
5802 ty::mk_ptr(tcx, ty::mt {
5804 mutbl: ast::MutImmutable
5807 "copy_memory" | "copy_nonoverlapping_memory" |
5808 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5811 ty::mk_ptr(tcx, ty::mt {
5813 mutbl: ast::MutMutable
5815 ty::mk_ptr(tcx, ty::mt {
5817 mutbl: ast::MutImmutable
5823 "set_memory" | "volatile_set_memory" => {
5826 ty::mk_ptr(tcx, ty::mt {
5828 mutbl: ast::MutMutable
5835 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5836 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5839 vec!( tcx.types.f32, tcx.types.i32 ),
5844 vec!( tcx.types.f64, tcx.types.i32 ),
5847 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5848 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5849 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5850 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5853 vec!( tcx.types.f32, tcx.types.f32 ),
5858 vec!( tcx.types.f64, tcx.types.f64 ),
5861 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5862 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5863 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5864 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5865 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5866 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5867 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5868 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5869 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5870 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5873 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5878 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5881 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5882 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5883 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5884 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5885 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5886 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5887 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5888 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5889 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5890 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5891 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5892 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5893 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5894 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5895 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5896 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5897 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5898 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5899 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5900 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5901 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5902 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5903 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5904 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5905 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5906 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5907 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5908 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5909 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5910 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5911 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5914 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5916 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5918 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5919 (0, vec!(tcx.types.i8, tcx.types.i8),
5920 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5922 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5923 (0, vec!(tcx.types.i16, tcx.types.i16),
5924 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5926 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5927 (0, vec!(tcx.types.i32, tcx.types.i32),
5928 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5930 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5931 (0, vec!(tcx.types.i64, tcx.types.i64),
5932 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5934 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5935 (0, vec!(tcx.types.u8, tcx.types.u8),
5936 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5938 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5939 (0, vec!(tcx.types.u16, tcx.types.u16),
5940 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5942 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5943 (0, vec!(tcx.types.u32, tcx.types.u32),
5944 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5946 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5947 (0, vec!(tcx.types.u64, tcx.types.u64),
5948 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5950 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5952 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5955 span_err!(tcx.sess, it.span, E0093,
5956 "unrecognized intrinsic function: `{}`", *other);
5960 (n_tps, inputs, ty::FnConverging(output))
5962 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5963 unsafety: ast::Unsafety::Unsafe,
5964 abi: abi::RustIntrinsic,
5965 sig: ty::Binder(FnSig {
5971 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5972 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5973 if i_n_tps != n_tps {
5974 span_err!(tcx.sess, it.span, E0094,
5975 "intrinsic has wrong number of type \
5976 parameters: found {}, expected {}",
5979 require_same_types(tcx,
5986 format!("intrinsic has wrong type: expected `{}`",
5987 ppaux::ty_to_string(ccx.tcx, fty))