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 pub use self::compare_method::compare_impl_method;
82 use self::IsBinopAssignment::*;
83 use self::TupleArgumentsFlag::*;
85 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
86 use check::_match::pat_ctxt;
87 use fmt_macros::{Parser, Piece, Position};
88 use middle::{const_eval, def};
90 use middle::lang_items::IteratorItem;
91 use middle::mem_categorization as mc;
92 use middle::mem_categorization::McResult;
93 use middle::pat_util::{self, pat_id_map};
94 use middle::region::CodeExtent;
95 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
97 use middle::ty::{FnSig, VariantInfo, TypeScheme};
98 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
99 use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
100 use middle::ty::liberate_late_bound_regions;
101 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
102 use middle::ty_fold::{TypeFolder, TypeFoldable};
103 use rscope::RegionScope;
104 use session::Session;
105 use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
107 use middle::lang_items::TypeIdLangItem;
109 use util::common::{block_query, indenter, loop_query};
110 use util::ppaux::{self, Repr};
111 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
113 use std::cell::{Cell, Ref, RefCell};
114 use std::mem::replace;
116 use std::iter::repeat;
118 use syntax::{self, abi, attr};
119 use syntax::attr::AttrMetaMethods;
120 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
121 use syntax::ast_util::{self, local_def, PostExpansionMethod};
122 use syntax::codemap::{self, Span};
123 use syntax::owned_slice::OwnedSlice;
124 use syntax::parse::token;
125 use syntax::print::pprust;
127 use syntax::visit::{self, Visitor};
143 /// closures defined within the function. For example:
146 /// bar(move|| { ... })
149 /// Here, the function `foo()` and the closure passed to
150 /// `bar()` will each have their own `FnCtxt`, but they will
151 /// share the inherited fields.
152 pub struct Inherited<'a, 'tcx: 'a> {
153 infcx: infer::InferCtxt<'a, 'tcx>,
154 locals: RefCell<NodeMap<Ty<'tcx>>>,
155 param_env: ty::ParameterEnvironment<'a, 'tcx>,
158 node_types: RefCell<NodeMap<Ty<'tcx>>>,
159 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
160 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
161 method_map: MethodMap<'tcx>,
162 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
163 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
164 object_cast_map: ObjectCastMap<'tcx>,
166 // A mapping from each fn's id to its signature, with all bound
167 // regions replaced with free ones. Unlike the other tables, this
168 // one is never copied into the tcx: it is only used by regionck.
169 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
171 // Tracks trait obligations incurred during this function body.
172 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
175 /// When type-checking an expression, we propagate downward
176 /// whatever type hint we are able in the form of an `Expectation`.
178 enum Expectation<'tcx> {
179 /// We know nothing about what type this expression should have.
182 /// This expression should have the type given (or some subtype)
183 ExpectHasType(Ty<'tcx>),
185 /// This expression will be cast to the `Ty`
186 ExpectCastableToType(Ty<'tcx>),
188 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
189 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
190 ExpectRvalueLikeUnsized(Ty<'tcx>),
193 impl<'tcx> Expectation<'tcx> {
194 // Disregard "castable to" expectations because they
195 // can lead us astray. Consider for example `if cond
196 // {22} else {c} as u8` -- if we propagate the
197 // "castable to u8" constraint to 22, it will pick the
198 // type 22u8, which is overly constrained (c might not
199 // be a u8). In effect, the problem is that the
200 // "castable to" expectation is not the tightest thing
201 // we can say, so we want to drop it in this case.
202 // The tightest thing we can say is "must unify with
203 // else branch". Note that in the case of a "has type"
204 // constraint, this limitation does not hold.
206 // If the expected type is just a type variable, then don't use
207 // an expected type. Otherwise, we might write parts of the type
208 // when checking the 'then' block which are incompatible with the
210 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
212 ExpectHasType(ety) => {
213 let ety = fcx.infcx().shallow_resolve(ety);
214 if !ty::type_is_ty_var(ety) {
220 ExpectRvalueLikeUnsized(ety) => {
221 ExpectRvalueLikeUnsized(ety)
228 #[derive(Copy, Clone)]
229 pub struct UnsafetyState {
230 pub def: ast::NodeId,
231 pub unsafety: ast::Unsafety,
236 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
237 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
240 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
241 match self.unsafety {
242 // If this unsafe, then if the outer function was already marked as
243 // unsafe we shouldn't attribute the unsafe'ness to the block. This
244 // way the block can be warned about instead of ignoring this
245 // extraneous block (functions are never warned about).
246 ast::Unsafety::Unsafe if self.from_fn => *self,
249 let (unsafety, def) = match blk.rules {
250 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
251 ast::DefaultBlock => (unsafety, self.def),
253 UnsafetyState{ def: def,
261 /// Whether `check_binop` is part of an assignment or not.
262 /// Used to know whether we allow user overloads and to print
263 /// better messages on error.
265 enum IsBinopAssignment{
271 pub struct FnCtxt<'a, 'tcx: 'a> {
272 body_id: ast::NodeId,
274 // This flag is set to true if, during the writeback phase, we encounter
275 // a type error in this function.
276 writeback_errors: Cell<bool>,
278 // Number of errors that had been reported when we started
279 // checking this function. On exit, if we find that *more* errors
280 // have been reported, we will skip regionck and other work that
281 // expects the types within the function to be consistent.
282 err_count_on_creation: uint,
284 ret_ty: ty::FnOutput<'tcx>,
286 ps: RefCell<UnsafetyState>,
288 inh: &'a Inherited<'a, 'tcx>,
290 ccx: &'a CrateCtxt<'a, 'tcx>,
293 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
294 fn tcx(&self) -> &ty::ctxt<'tcx> {
297 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
298 let ty = self.node_ty(id);
299 self.resolve_type_vars_or_error(&ty)
301 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
302 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
303 self.resolve_type_vars_or_error(&ty)
305 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
306 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
307 traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
309 fn node_method_ty(&self, method_call: ty::MethodCall)
310 -> Option<Ty<'tcx>> {
311 self.inh.method_map.borrow()
313 .map(|method| method.ty)
314 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
316 fn node_method_origin(&self, method_call: ty::MethodCall)
317 -> Option<ty::MethodOrigin<'tcx>>
319 self.inh.method_map.borrow()
321 .map(|method| method.origin.clone())
323 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
324 &self.inh.adjustments
326 fn is_method_call(&self, id: ast::NodeId) -> bool {
327 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
329 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
330 self.param_env().temporary_scope(rvalue_id)
332 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
333 self.inh.upvar_borrow_map.borrow().get(&upvar_id).cloned()
335 fn capture_mode(&self, closure_expr_id: ast::NodeId)
336 -> ast::CaptureClause {
337 self.ccx.tcx.capture_mode(closure_expr_id)
341 impl<'a, 'tcx> ty::UnboxedClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
342 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
346 fn unboxed_closure_kind(&self,
348 -> ty::UnboxedClosureKind
350 self.inh.unboxed_closures.borrow()[def_id].kind
353 fn unboxed_closure_type(&self,
355 substs: &subst::Substs<'tcx>)
356 -> ty::ClosureTy<'tcx>
358 self.inh.unboxed_closures.borrow()[def_id].closure_type.subst(self.tcx(), substs)
361 fn unboxed_closure_upvars(&self,
363 substs: &Substs<'tcx>)
364 -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
366 ty::unboxed_closure_upvars(self, def_id, substs)
370 impl<'a, 'tcx> Inherited<'a, 'tcx> {
371 fn new(tcx: &'a ty::ctxt<'tcx>,
372 param_env: ty::ParameterEnvironment<'a, 'tcx>)
373 -> Inherited<'a, 'tcx> {
375 infcx: infer::new_infer_ctxt(tcx),
376 locals: RefCell::new(NodeMap::new()),
377 param_env: param_env,
378 node_types: RefCell::new(NodeMap::new()),
379 item_substs: RefCell::new(NodeMap::new()),
380 adjustments: RefCell::new(NodeMap::new()),
381 method_map: RefCell::new(FnvHashMap::new()),
382 object_cast_map: RefCell::new(NodeMap::new()),
383 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
384 unboxed_closures: RefCell::new(DefIdMap::new()),
385 fn_sig_map: RefCell::new(NodeMap::new()),
386 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
390 fn normalize_associated_types_in<T>(&self,
391 typer: &ty::UnboxedClosureTyper<'tcx>,
393 body_id: ast::NodeId,
396 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
398 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
399 assoc::normalize_associated_types_in(&self.infcx,
401 &mut *fulfillment_cx, span,
408 // Used by check_const and check_enum_variants
409 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
410 inh: &'a Inherited<'a, 'tcx>,
411 rty: ty::FnOutput<'tcx>,
412 body_id: ast::NodeId)
413 -> FnCtxt<'a, 'tcx> {
416 writeback_errors: Cell::new(false),
417 err_count_on_creation: ccx.tcx.sess.err_count(),
419 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
425 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
426 -> Inherited<'a, 'tcx> {
427 // It's kind of a kludge to manufacture a fake function context
428 // and statement context, but we might as well do write the code only once
429 let param_env = ty::empty_parameter_environment(ccx.tcx);
430 Inherited::new(ccx.tcx, param_env)
433 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
435 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
436 fn visit_item(&mut self, i: &ast::Item) {
437 check_item(self.ccx, i);
438 visit::walk_item(self, i);
441 fn visit_ty(&mut self, t: &ast::Ty) {
443 ast::TyFixedLengthVec(_, ref expr) => {
444 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
449 visit::walk_ty(self, t);
453 pub fn check_item_types(ccx: &CrateCtxt) {
454 let krate = ccx.tcx.map.krate();
455 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
456 visit::walk_crate(&mut visit, krate);
458 // If types are not well-formed, it leads to all manner of errors
459 // downstream, so stop reporting errors at this point.
460 ccx.tcx.sess.abort_if_errors();
462 let mut visit = CheckItemTypesVisitor { ccx: ccx };
463 visit::walk_crate(&mut visit, krate);
465 ccx.tcx.sess.abort_if_errors();
468 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
473 param_env: ty::ParameterEnvironment<'a, 'tcx>) {
475 ty::ty_bare_fn(_, ref fn_ty) => {
476 let inh = Inherited::new(ccx.tcx, param_env);
478 // Compute the fty from point of view of inside fn.
480 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
482 liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig);
484 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
486 let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
487 decl, id, body, &inh);
489 vtable::select_all_fcx_obligations_or_error(&fcx);
490 upvar::closure_analyze_fn(&fcx, id, decl, body);
491 regionck::regionck_fn(&fcx, id, decl, body);
492 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
494 _ => ccx.tcx.sess.impossible_case(body.span,
495 "check_bare_fn: function type expected")
499 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
500 fcx: &'a FnCtxt<'a, 'tcx>
503 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
504 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
507 // infer the variable's type
508 let var_ty = self.fcx.infcx().next_ty_var();
509 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
513 // take type that the user specified
514 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
521 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
522 // Add explicitly-declared locals.
523 fn visit_local(&mut self, local: &ast::Local) {
524 let o_ty = match local.ty {
525 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
528 self.assign(local.span, local.id, o_ty);
529 debug!("Local variable {} is assigned type {}",
530 self.fcx.pat_to_string(&*local.pat),
531 self.fcx.infcx().ty_to_string(
532 self.fcx.inh.locals.borrow()[local.id].clone()));
533 visit::walk_local(self, local);
536 // Add pattern bindings.
537 fn visit_pat(&mut self, p: &ast::Pat) {
538 if let ast::PatIdent(_, ref path1, _) = p.node {
539 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
540 let var_ty = self.assign(p.span, p.id, None);
542 self.fcx.require_type_is_sized(var_ty, p.span,
543 traits::VariableType(p.id));
545 debug!("Pattern binding {} is assigned to {} with type {}",
546 token::get_ident(path1.node),
547 self.fcx.infcx().ty_to_string(
548 self.fcx.inh.locals.borrow()[p.id].clone()),
549 var_ty.repr(self.fcx.tcx()));
552 visit::walk_pat(self, p);
555 fn visit_block(&mut self, b: &ast::Block) {
556 // non-obvious: the `blk` variable maps to region lb, so
557 // we have to keep this up-to-date. This
558 // is... unfortunate. It'd be nice to not need this.
559 visit::walk_block(self, b);
562 // Since an expr occurs as part of the type fixed size arrays we
563 // need to record the type for that node
564 fn visit_ty(&mut self, t: &ast::Ty) {
566 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
567 self.visit_ty(&**ty);
568 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
570 _ => visit::walk_ty(self, t)
574 // Don't descend into fns and items
575 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
576 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
577 fn visit_item(&mut self, _: &ast::Item) { }
581 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
582 /// body and returns the function context used for that purpose, since in the case of a fn item
583 /// there is still a bit more to do.
586 /// * inherited: other fields inherited from the enclosing fn (if any)
587 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
588 unsafety: ast::Unsafety,
589 unsafety_id: ast::NodeId,
590 fn_sig: &ty::FnSig<'tcx>,
594 inherited: &'a Inherited<'a, 'tcx>)
598 let err_count_on_creation = tcx.sess.err_count();
600 let arg_tys = &fn_sig.inputs[];
601 let ret_ty = fn_sig.output;
603 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
608 // Create the function context. This is either derived from scratch or,
609 // in the case of function expressions, based on the outer context.
612 writeback_errors: Cell::new(false),
613 err_count_on_creation: err_count_on_creation,
615 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
620 // Remember return type so that regionck can access it later.
621 let mut fn_sig_tys: Vec<Ty> =
626 if let ty::FnConverging(ret_ty) = ret_ty {
627 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
628 fn_sig_tys.push(ret_ty);
631 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
633 fn_sig_tys.repr(tcx));
635 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
638 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
640 // Add formal parameters.
641 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
642 // Create type variables for each argument.
643 pat_util::pat_bindings(
646 |_bm, pat_id, sp, _path| {
647 let var_ty = visit.assign(sp, pat_id, None);
648 fcx.require_type_is_sized(var_ty, sp,
649 traits::VariableType(pat_id));
652 // Check the pattern.
655 map: pat_id_map(&tcx.def_map, &*input.pat),
657 _match::check_pat(&pcx, &*input.pat, *arg_ty);
660 visit.visit_block(body);
663 check_block_with_expected(&fcx, body, match ret_ty {
664 ty::FnConverging(result_type) => ExpectHasType(result_type),
665 ty::FnDiverging => NoExpectation
668 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
669 fcx.write_ty(input.id, *arg);
675 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
678 check_representable(tcx, span, id, "struct");
679 check_instantiable(tcx, span, id);
681 if ty::lookup_simd(tcx, local_def(id)) {
682 check_simd(tcx, span, id);
686 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
687 debug!("check_item(it.id={}, it.ident={})",
689 ty::item_path_str(ccx.tcx, local_def(it.id)));
690 let _indenter = indenter();
693 ast::ItemStatic(_, _, ref e) |
694 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
695 ast::ItemEnum(ref enum_definition, _) => {
696 check_enum_variants(ccx,
698 &enum_definition.variants[],
701 ast::ItemFn(ref decl, _, _, _, ref body) => {
702 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
703 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
704 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
706 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
707 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
709 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
711 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
712 Some(impl_trait_ref) => {
713 check_impl_items_against_trait(ccx,
716 impl_items.as_slice());
721 for impl_item in impl_items.iter() {
723 ast::MethodImplItem(ref m) => {
724 check_method_body(ccx, &impl_pty.generics, &**m);
726 ast::TypeImplItem(_) => {
727 // Nothing to do here.
733 ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
734 check_trait_on_unimplemented(ccx, generics, it);
735 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
736 for trait_method in trait_methods.iter() {
737 match *trait_method {
738 RequiredMethod(..) => {
739 // Nothing to do, since required methods don't have
742 ProvidedMethod(ref m) => {
743 check_method_body(ccx, &trait_def.generics, &**m);
745 TypeTraitItem(_) => {
751 ast::ItemStruct(..) => {
752 check_struct(ccx, it.id, it.span);
754 ast::ItemTy(ref t, ref generics) => {
755 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
756 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
758 ast::ItemForeignMod(ref m) => {
759 if m.abi == abi::RustIntrinsic {
760 for item in m.items.iter() {
761 check_intrinsic_type(ccx, &**item);
764 for item in m.items.iter() {
765 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
766 if !pty.generics.types.is_empty() {
767 span_err!(ccx.tcx.sess, item.span, E0044,
768 "foreign items may not have type parameters");
771 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
772 if fn_decl.variadic && m.abi != abi::C {
773 span_err!(ccx.tcx.sess, item.span, E0045,
774 "variadic function must have C calling convention");
780 _ => {/* nothing to do */ }
784 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
785 generics: &ast::Generics,
787 if let Some(ref attr) = item.attrs.iter().find(|&: a| {
788 a.check_name("rustc_on_unimplemented")
790 if let Some(ref istring) = attr.value_str() {
791 let mut parser = Parser::new(istring.get());
792 let types = generics.ty_params.as_slice();
793 for token in parser {
795 Piece::String(_) => (), // Normal string, no need to check it
796 Piece::NextArgument(a) => match a.position {
797 // `{Self}` is allowed
798 Position::ArgumentNamed(s) if s == "Self" => (),
799 // So is `{A}` if A is a type parameter
800 Position::ArgumentNamed(s) => match types.iter().find(|t| {
801 t.ident.as_str() == s
805 ccx.tcx.sess.span_err(attr.span,
806 format!("there is no type parameter \
808 s, item.ident.as_str())
812 // `{:1}` and `{}` are not to be used
813 Position::ArgumentIs(_) | Position::ArgumentNext => {
814 ccx.tcx.sess.span_err(attr.span,
815 "only named substitution \
816 parameters are allowed");
822 ccx.tcx.sess.span_err(attr.span,
823 "this attribute must have a value, \
824 eg `#[rustc_on_unimplemented = \"foo\"]`")
829 /// Type checks a method body.
833 /// * `item_generics`: generics defined on the impl/trait that contains
835 /// * `self_bound`: bound for the `Self` type parameter, if any
836 /// * `method`: the method definition
837 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
838 item_generics: &ty::Generics<'tcx>,
839 method: &ast::Method) {
840 debug!("check_method_body(item_generics={}, method.id={})",
841 item_generics.repr(ccx.tcx),
843 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
845 let fty = ty::node_id_to_type(ccx.tcx, method.id);
846 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
849 &*method.pe_fn_decl(),
856 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
858 impl_trait_ref: &ty::TraitRef<'tcx>,
859 impl_items: &[ast::ImplItem]) {
860 // Locate trait methods
862 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
864 // Check existing impl methods to see if they are both present in trait
865 // and compatible with trait signature
866 for impl_item in impl_items.iter() {
868 ast::MethodImplItem(ref impl_method) => {
869 let impl_method_def_id = local_def(impl_method.id);
870 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
873 // If this is an impl of a trait method, find the
874 // corresponding method definition in the trait.
875 let opt_trait_method_ty =
877 .find(|ti| ti.name() == impl_item_ty.name());
878 match opt_trait_method_ty {
879 Some(trait_method_ty) => {
880 match (trait_method_ty, &impl_item_ty) {
881 (&ty::MethodTraitItem(ref trait_method_ty),
882 &ty::MethodTraitItem(ref impl_method_ty)) => {
883 compare_impl_method(ccx.tcx,
886 impl_method.pe_body().id,
891 // This is span_bug as it should have already been
892 // caught in resolve.
895 format!("item `{}` is of a different kind from its trait `{}`",
896 token::get_name(impl_item_ty.name()),
897 impl_trait_ref.repr(tcx)).as_slice());
902 // This is span_bug as it should have already been
903 // caught in resolve.
906 format!("method `{}` is not a member of trait `{}`",
907 token::get_name(impl_item_ty.name()),
908 impl_trait_ref.repr(tcx)).as_slice());
912 ast::TypeImplItem(ref typedef) => {
913 let typedef_def_id = local_def(typedef.id);
914 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
917 // If this is an impl of an associated type, find the
918 // corresponding type definition in the trait.
919 let opt_associated_type =
921 .find(|ti| ti.name() == typedef_ty.name());
922 match opt_associated_type {
923 Some(associated_type) => {
924 match (associated_type, &typedef_ty) {
925 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
927 // This is `span_bug` as it should have
928 // already been caught in resolve.
931 format!("item `{}` is of a different kind from its trait `{}`",
932 token::get_name(typedef_ty.name()),
933 impl_trait_ref.repr(tcx)).as_slice());
938 // This is `span_bug` as it should have already been
939 // caught in resolve.
943 "associated type `{}` is not a member of \
945 token::get_name(typedef_ty.name()),
946 impl_trait_ref.repr(tcx)).as_slice());
953 // Check for missing items from trait
954 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
955 let mut missing_methods = Vec::new();
956 for trait_item in trait_items.iter() {
958 ty::MethodTraitItem(ref trait_method) => {
960 impl_items.iter().any(|ii| {
962 ast::MethodImplItem(ref m) => {
963 m.pe_ident().name == trait_method.name
965 ast::TypeImplItem(_) => false,
969 provided_methods.iter().any(|m| m.name == trait_method.name);
970 if !is_implemented && !is_provided {
971 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
974 ty::TypeTraitItem(ref associated_type) => {
975 let is_implemented = impl_items.iter().any(|ii| {
977 ast::TypeImplItem(ref typedef) => {
978 typedef.ident.name == associated_type.name
980 ast::MethodImplItem(_) => false,
984 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
990 if !missing_methods.is_empty() {
991 span_err!(tcx.sess, impl_span, E0046,
992 "not all trait items implemented, missing: {}",
993 missing_methods.connect(", "));
997 fn check_cast(fcx: &FnCtxt,
998 cast_expr: &ast::Expr,
1001 let id = cast_expr.id;
1002 let span = cast_expr.span;
1004 // Find the type of `e`. Supply hints based on the type we are casting to,
1006 let t_1 = fcx.to_ty(t);
1007 let t_1 = structurally_resolved_type(fcx, span, t_1);
1009 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1011 let t_e = fcx.expr_ty(e);
1013 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1014 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1016 if ty::type_is_error(t_e) {
1017 fcx.write_error(id);
1021 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1022 let tstr = fcx.infcx().ty_to_string(t_1);
1023 fcx.type_error_message(span, |actual| {
1024 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1027 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1028 let mtstr = match mt {
1029 ast::MutMutable => "mut ",
1030 ast::MutImmutable => ""
1032 if ty::type_is_trait(t_1) {
1033 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1035 span_help!(fcx.tcx().sess, span,
1036 "consider using an implicit coercion to `&{}{}` instead",
1040 ty::ty_uniq(..) => {
1041 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1044 span_help!(fcx.tcx().sess, e.span,
1045 "consider using a box or reference as appropriate");
1048 fcx.write_error(id);
1052 if ty::type_is_trait(t_1) {
1053 // This will be looked up later on.
1054 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1055 fcx.write_ty(id, t_1);
1059 let t_1 = structurally_resolved_type(fcx, span, t_1);
1060 let t_e = structurally_resolved_type(fcx, span, t_e);
1062 if ty::type_is_nil(t_e) {
1063 fcx.type_error_message(span, |actual| {
1064 format!("cast from nil: `{}` as `{}`",
1066 fcx.infcx().ty_to_string(t_1))
1068 } else if ty::type_is_nil(t_1) {
1069 fcx.type_error_message(span, |actual| {
1070 format!("cast to nil: `{}` as `{}`",
1072 fcx.infcx().ty_to_string(t_1))
1076 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1078 let t_1_is_scalar = ty::type_is_scalar(t_1);
1079 let t_1_is_char = ty::type_is_char(t_1);
1080 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1081 let t_1_is_float = ty::type_is_floating_point(t_1);
1083 // casts to scalars other than `char` and `bare fn` are trivial
1084 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1085 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1086 demand::coerce(fcx, e.span, t_1, &*e);
1087 } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1088 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1089 fcx.type_error_message(span, |actual| {
1090 format!("illegal cast; cast through an \
1091 integer first: `{}` as `{}`",
1093 fcx.infcx().ty_to_string(t_1))
1096 // casts from C-like enums are allowed
1097 } else if t_1_is_char {
1098 let t_e = fcx.infcx().shallow_resolve(t_e);
1099 if t_e.sty != ty::ty_uint(ast::TyU8) {
1100 fcx.type_error_message(span, |actual| {
1101 format!("only `u8` can be cast as \
1102 `char`, not `{}`", actual)
1105 } else if t_1.sty == ty::ty_bool {
1106 span_err!(fcx.tcx().sess, span, E0054,
1107 "cannot cast as `bool`, compare with zero instead");
1108 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1109 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1110 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1112 ty::ty_vec(_, Some(_)) => {}
1115 if ty::type_needs_infer(t2) {
1116 // This prevents this special case from going off when casting
1117 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1122 let el = ty::sequence_element_type(fcx.tcx(), t1);
1123 infer::mk_eqty(fcx.infcx(),
1130 // Due to the limitations of LLVM global constants,
1131 // region pointers end up pointing at copies of
1132 // vector elements instead of the original values.
1133 // To allow unsafe pointers to work correctly, we
1134 // need to special-case obtaining an unsafe pointer
1135 // from a region pointer to a vector.
1137 /* this cast is only allowed from &[T, ..n] to *T or
1139 match (&t_e.sty, &t_1.sty) {
1140 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1141 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1142 if types_compatible(fcx, e.span, mt1, mt2) => {
1143 /* this case is allowed */
1146 demand::coerce(fcx, e.span, t_1, &*e);
1149 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1151 If more type combinations should be supported than are
1152 supported here, then file an enhancement issue and
1153 record the issue number in this comment.
1155 fcx.type_error_message(span, |actual| {
1156 format!("non-scalar cast: `{}` as `{}`",
1158 fcx.infcx().ty_to_string(t_1))
1160 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1161 fcx.type_error_message(span, |actual| {
1162 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1165 fcx.infcx().ty_to_string(t_1))
1169 fcx.write_ty(id, t_1);
1172 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1173 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1175 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1176 ty::lookup_item_type(self.tcx(), id)
1179 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1180 ty::lookup_trait_def(self.tcx(), id)
1183 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1184 Some(&self.inh.param_env.free_substs)
1187 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1188 self.infcx().next_ty_var()
1191 fn projected_ty_from_poly_trait_ref(&self,
1193 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1194 item_name: ast::Name)
1197 let (trait_ref, _) =
1198 self.infcx().replace_late_bound_regions_with_fresh_var(
1200 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1203 self.normalize_associated_type(span, trait_ref, item_name)
1206 fn projected_ty(&self,
1208 trait_ref: Rc<ty::TraitRef<'tcx>>,
1209 item_name: ast::Name)
1212 self.normalize_associated_type(span, trait_ref, item_name)
1216 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1217 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1219 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1223 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1227 pub fn sess(&self) -> &Session {
1231 pub fn err_count_since_creation(&self) -> uint {
1232 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1235 /// Resolves all type variables in `t` and then, if any were left
1236 /// unresolved, substitutes an error type. This is used after the
1237 /// main checking when doing a second pass before writeback. The
1238 /// justification is that writeback will produce an error for
1239 /// these unconstrained type variables.
1240 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1241 let t = self.infcx().resolve_type_vars_if_possible(t);
1242 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1245 pub fn tag(&self) -> String {
1246 format!("{:?}", self as *const FnCtxt)
1249 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1250 match self.inh.locals.borrow().get(&nid) {
1253 self.tcx().sess.span_bug(
1255 &format!("no type for local variable {}",
1261 /// Apply "fallbacks" to some types
1262 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1263 pub fn default_type_parameters(&self) {
1264 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1265 for (_, &mut ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1266 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1267 if self.infcx().type_var_diverges(resolved) {
1268 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1270 match self.infcx().type_is_unconstrained_numeric(resolved) {
1271 UnconstrainedInt => {
1272 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1274 UnconstrainedFloat => {
1275 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1284 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1285 debug!("write_ty({}, {}) in fcx {}",
1286 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1287 self.inh.node_types.borrow_mut().insert(node_id, ty);
1290 pub fn write_object_cast(&self,
1292 trait_ref: ty::PolyTraitRef<'tcx>) {
1293 debug!("write_object_cast key={} trait_ref={}",
1294 key, trait_ref.repr(self.tcx()));
1295 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1298 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1299 if !substs.substs.is_noop() {
1300 debug!("write_substs({}, {}) in fcx {}",
1302 substs.repr(self.tcx()),
1305 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1309 pub fn write_autoderef_adjustment(&self,
1310 node_id: ast::NodeId,
1313 if derefs == 0 { return; }
1314 self.write_adjustment(
1317 ty::AdjustDerefRef(ty::AutoDerefRef {
1323 pub fn write_adjustment(&self,
1324 node_id: ast::NodeId,
1326 adj: ty::AutoAdjustment<'tcx>) {
1327 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1329 if adj.is_identity() {
1333 // Careful: adjustments can imply trait obligations if we are
1334 // casting from a concrete type to an object type. I think
1335 // it'd probably be nicer to move the logic that creates the
1336 // obligation into the code that creates the adjustment, but
1337 // that's a bit awkward, so instead we go digging and pull the
1338 // obligation out here.
1339 self.register_adjustment_obligations(span, &adj);
1340 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1343 /// Basically whenever we are converting from a type scheme into
1344 /// the fn body space, we always want to normalize associated
1345 /// types as well. This function combines the two.
1346 fn instantiate_type_scheme<T>(&self,
1348 substs: &Substs<'tcx>,
1351 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1353 let value = value.subst(self.tcx(), substs);
1354 let result = self.normalize_associated_types_in(span, &value);
1355 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1356 value.repr(self.tcx()),
1357 substs.repr(self.tcx()),
1358 result.repr(self.tcx()));
1362 /// As `instantiate_type_scheme`, but for the bounds found in a
1363 /// generic type scheme.
1364 fn instantiate_bounds(&self,
1366 substs: &Substs<'tcx>,
1367 generics: &ty::Generics<'tcx>)
1368 -> ty::GenericBounds<'tcx>
1371 predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
1376 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1377 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1379 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1382 fn normalize_associated_type(&self,
1384 trait_ref: Rc<ty::TraitRef<'tcx>>,
1385 item_name: ast::Name)
1388 let cause = traits::ObligationCause::new(span,
1390 traits::ObligationCauseCode::MiscObligation);
1391 self.inh.fulfillment_cx
1393 .normalize_projection_type(self.infcx(),
1396 trait_ref: trait_ref,
1397 item_name: item_name,
1402 fn register_adjustment_obligations(&self,
1404 adj: &ty::AutoAdjustment<'tcx>) {
1406 ty::AdjustReifyFnPointer(..) => {
1408 ty::AdjustDerefRef(ref d_r) => {
1411 self.register_autoref_obligations(span, a_r);
1419 fn register_autoref_obligations(&self,
1421 autoref: &ty::AutoRef<'tcx>) {
1423 ty::AutoUnsize(ref unsize) => {
1424 self.register_unsize_obligations(span, unsize);
1426 ty::AutoPtr(_, _, None) |
1427 ty::AutoUnsafe(_, None) => {
1429 ty::AutoPtr(_, _, Some(ref a_r)) |
1430 ty::AutoUnsafe(_, Some(ref a_r)) => {
1431 self.register_autoref_obligations(span, &**a_r)
1433 ty::AutoUnsizeUniq(ref unsize) => {
1434 self.register_unsize_obligations(span, unsize);
1439 fn register_unsize_obligations(&self,
1441 unsize: &ty::UnsizeKind<'tcx>) {
1442 debug!("register_unsize_obligations: unsize={:?}", unsize);
1445 ty::UnsizeLength(..) => {}
1446 ty::UnsizeStruct(ref u, _) => {
1447 self.register_unsize_obligations(span, &**u)
1449 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1450 vtable::check_object_safety(self.tcx(), ty_trait, span);
1452 // If the type is `Foo+'a`, ensures that the type
1453 // being cast to `Foo+'a` implements `Foo`:
1454 vtable::register_object_cast_obligations(self,
1459 // If the type is `Foo+'a`, ensures that the type
1460 // being cast to `Foo+'a` outlives `'a`:
1461 let cause = traits::ObligationCause { span: span,
1462 body_id: self.body_id,
1463 code: traits::ObjectCastObligation(self_ty) };
1464 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1469 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1470 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1471 /// Registers any trait obligations specified on `def_id` at the same time.
1473 /// Note that function is only intended to be used with types (notably, not fns). This is
1474 /// because it doesn't do any instantiation of late-bound regions.
1475 pub fn instantiate_type(&self,
1478 -> TypeAndSubsts<'tcx>
1481 ty::lookup_item_type(self.tcx(), def_id);
1483 self.infcx().fresh_substs_for_generics(
1485 &type_scheme.generics);
1487 self.instantiate_bounds(span, &substs, &type_scheme.generics);
1488 self.add_obligations_for_parameters(
1489 traits::ObligationCause::new(
1492 traits::ItemObligation(def_id)),
1495 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1503 /// Returns the type that this AST path refers to. If the path has no type
1504 /// parameters and the corresponding type has type parameters, fresh type
1505 /// and/or region variables are substituted.
1507 /// This is used when checking the constructor in struct literals.
1508 fn instantiate_struct_literal_ty(&self,
1511 -> TypeAndSubsts<'tcx>
1513 let tcx = self.tcx();
1515 let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
1518 generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1520 let needs_defaults =
1522 path.segments.iter().all(|s| s.parameters.is_empty());
1524 let substs = if needs_defaults {
1526 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1528 self.infcx().region_vars_for_defs(path.span,
1529 generics.regions.get_slice(TypeSpace));
1530 Substs::new_type(tps, rps)
1532 astconv::ast_path_substs_for_ty(self, self, &generics, path)
1535 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1537 TypeAndSubsts { substs: substs, ty: ty }
1540 pub fn write_nil(&self, node_id: ast::NodeId) {
1541 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1543 pub fn write_error(&self, node_id: ast::NodeId) {
1544 self.write_ty(node_id, self.tcx().types.err);
1547 pub fn require_type_meets(&self,
1550 code: traits::ObligationCauseCode<'tcx>,
1551 bound: ty::BuiltinBound)
1553 self.register_builtin_bound(
1556 traits::ObligationCause::new(span, self.body_id, code));
1559 pub fn require_type_is_sized(&self,
1562 code: traits::ObligationCauseCode<'tcx>)
1564 self.require_type_meets(ty, span, code, ty::BoundSized);
1567 pub fn require_expr_have_sized_type(&self,
1569 code: traits::ObligationCauseCode<'tcx>)
1571 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1574 pub fn type_is_known_to_be_sized(&self,
1579 traits::type_known_to_meet_builtin_bound(self.infcx(),
1586 pub fn register_builtin_bound(&self,
1588 builtin_bound: ty::BuiltinBound,
1589 cause: traits::ObligationCause<'tcx>)
1591 self.inh.fulfillment_cx.borrow_mut()
1592 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1595 pub fn register_predicate(&self,
1596 obligation: traits::PredicateObligation<'tcx>)
1598 debug!("register_predicate({})",
1599 obligation.repr(self.tcx()));
1601 self.inh.fulfillment_cx
1603 .register_predicate_obligation(self.infcx(), obligation);
1606 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1607 let t = ast_ty_to_ty(self, self, ast_t);
1609 let mut bounds_checker = wf::BoundsChecker::new(self,
1611 CodeExtent::from_node_id(self.body_id),
1613 bounds_checker.check_ty(t);
1618 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1619 pat.repr(self.tcx())
1622 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1623 match self.inh.node_types.borrow().get(&ex.id) {
1626 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1632 /// Apply `adjustment` to the type of `expr`
1633 pub fn adjust_expr_ty(&self,
1635 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1638 let raw_ty = self.expr_ty(expr);
1639 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1640 ty::adjust_ty(self.tcx(),
1645 |method_call| self.inh.method_map.borrow()
1647 .map(|method| method.ty))
1650 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1651 match self.inh.node_types.borrow().get(&id) {
1653 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1655 self.tcx().sess.bug(
1656 &format!("no type for node {}: {} in fcx {}",
1657 id, self.tcx().map.node_to_string(id),
1663 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1664 self.inh.item_substs.borrow()
1667 pub fn opt_node_ty_substs<F>(&self,
1670 F: FnOnce(&ty::ItemSubsts<'tcx>),
1672 match self.inh.item_substs.borrow().get(&id) {
1678 pub fn mk_subty(&self,
1679 a_is_expected: bool,
1680 origin: infer::TypeOrigin,
1683 -> Result<(), ty::type_err<'tcx>> {
1684 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1687 pub fn mk_assignty(&self,
1691 -> Result<(), ty::type_err<'tcx>> {
1692 match infer::mk_coercety(self.infcx(),
1694 infer::ExprAssignable(expr.span),
1698 Err(ref e) => Err((*e)),
1699 Ok(Some(adjustment)) => {
1700 self.write_adjustment(expr.id, expr.span, adjustment);
1706 pub fn mk_eqty(&self,
1707 a_is_expected: bool,
1708 origin: infer::TypeOrigin,
1711 -> Result<(), ty::type_err<'tcx>> {
1712 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1715 pub fn mk_subr(&self,
1716 origin: infer::SubregionOrigin<'tcx>,
1719 infer::mk_subr(self.infcx(), origin, sub, sup)
1722 pub fn type_error_message<M>(&self,
1725 actual_ty: Ty<'tcx>,
1726 err: Option<&ty::type_err<'tcx>>) where
1727 M: FnOnce(String) -> String,
1729 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1732 pub fn report_mismatched_types(&self,
1736 err: &ty::type_err<'tcx>) {
1737 self.infcx().report_mismatched_types(sp, e, a, err)
1740 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1741 /// outlive the region `r`.
1742 pub fn register_region_obligation(&self,
1745 cause: traits::ObligationCause<'tcx>)
1747 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1748 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1751 pub fn add_default_region_param_bounds(&self,
1752 substs: &Substs<'tcx>,
1755 for &ty in substs.types.iter() {
1756 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1757 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1758 traits::MiscObligation);
1759 self.register_region_obligation(ty, default_bound, cause);
1763 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1764 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1765 /// trait/region obligations.
1767 /// For example, if there is a function:
1770 /// fn foo<'a,T:'a>(...)
1773 /// and a reference:
1779 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1780 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1781 pub fn add_obligations_for_parameters(&self,
1782 cause: traits::ObligationCause<'tcx>,
1783 generic_bounds: &ty::GenericBounds<'tcx>)
1785 assert!(!generic_bounds.has_escaping_regions());
1787 debug!("add_obligations_for_parameters(generic_bounds={})",
1788 generic_bounds.repr(self.tcx()));
1790 let obligations = traits::predicates_for_generics(self.tcx(),
1794 obligations.map_move(|o| self.register_predicate(o));
1797 // Only for fields! Returns <none> for methods>
1798 // Indifferent to privacy flags
1799 pub fn lookup_field_ty(&self,
1801 class_id: ast::DefId,
1802 items: &[ty::field_ty],
1803 fieldname: ast::Name,
1804 substs: &subst::Substs<'tcx>)
1807 let o_field = items.iter().find(|f| f.name == fieldname);
1808 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1809 .map(|t| self.normalize_associated_types_in(span, &t))
1812 pub fn lookup_tup_field_ty(&self,
1814 class_id: ast::DefId,
1815 items: &[ty::field_ty],
1817 substs: &subst::Substs<'tcx>)
1820 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1821 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1822 .map(|t| self.normalize_associated_types_in(span, &t))
1826 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1827 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1828 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1831 fn anon_regions(&self, span: Span, count: uint)
1832 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1833 Ok(range(0, count).map(|_| {
1834 self.infcx().next_region_var(infer::MiscVariable(span))
1839 #[derive(Copy, Show, PartialEq, Eq)]
1840 pub enum LvaluePreference {
1845 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1846 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1848 /// Note: this method does not modify the adjustments table. The caller is responsible for
1849 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1850 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1853 opt_expr: Option<&ast::Expr>,
1854 mut lvalue_pref: LvaluePreference,
1856 -> (Ty<'tcx>, uint, Option<T>)
1857 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1859 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1860 base_ty.repr(fcx.tcx()),
1861 opt_expr.repr(fcx.tcx()),
1864 let mut t = base_ty;
1865 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1866 let resolved_t = structurally_resolved_type(fcx, sp, t);
1868 if ty::type_is_error(resolved_t) {
1869 return (resolved_t, autoderefs, None);
1872 match should_stop(resolved_t, autoderefs) {
1873 Some(x) => return (resolved_t, autoderefs, Some(x)),
1877 // Otherwise, deref if type is derefable:
1878 let mt = match ty::deref(resolved_t, false) {
1879 Some(mt) => Some(mt),
1881 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1883 // Super subtle: it might seem as though we should
1884 // pass `opt_expr` to `try_overloaded_deref`, so that
1885 // the (implicit) autoref of using an overloaded deref
1886 // would get added to the adjustment table. However we
1887 // do not do that, because it's kind of a
1888 // "meta-adjustment" -- instead, we just leave it
1889 // unrecorded and know that there "will be" an
1890 // autoref. regionck and other bits of the code base,
1891 // when they encounter an overloaded autoderef, have
1892 // to do some reconstructive surgery. This is a pretty
1893 // complex mess that is begging for a proper MIR.
1894 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1900 if mt.mutbl == ast::MutImmutable {
1901 lvalue_pref = NoPreference;
1904 None => return (resolved_t, autoderefs, None)
1908 // We've reached the recursion limit, error gracefully.
1909 span_err!(fcx.tcx().sess, sp, E0055,
1910 "reached the recursion limit while auto-dereferencing {}",
1911 base_ty.repr(fcx.tcx()));
1912 (fcx.tcx().types.err, 0, None)
1915 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1917 method_call: Option<MethodCall>,
1918 base_expr: Option<&ast::Expr>,
1920 lvalue_pref: LvaluePreference)
1921 -> Option<ty::mt<'tcx>>
1923 // Try DerefMut first, if preferred.
1924 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1925 (PreferMutLvalue, Some(trait_did)) => {
1926 method::lookup_in_trait(fcx, span, base_expr,
1927 token::intern("deref_mut"), trait_did,
1933 // Otherwise, fall back to Deref.
1934 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1935 (None, Some(trait_did)) => {
1936 method::lookup_in_trait(fcx, span, base_expr,
1937 token::intern("deref"), trait_did,
1940 (method, _) => method
1943 make_overloaded_lvalue_return_type(fcx, method_call, method)
1946 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
1947 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
1948 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
1949 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1950 method_call: Option<MethodCall>,
1951 method: Option<MethodCallee<'tcx>>)
1952 -> Option<ty::mt<'tcx>>
1956 let ref_ty = // invoked methods have all LB regions instantiated
1957 ty::assert_no_late_bound_regions(
1958 fcx.tcx(), &ty::ty_fn_ret(method.ty));
1960 Some(method_call) => {
1961 fcx.inh.method_map.borrow_mut().insert(method_call,
1967 ty::FnConverging(ref_ty) => {
1968 ty::deref(ref_ty, true)
1970 ty::FnDiverging => {
1971 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
1979 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1980 base_expr: &ast::Expr,
1982 lvalue_pref: LvaluePreference,
1985 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
1987 // FIXME(#18741) -- this is almost but not quite the same as the
1988 // autoderef that normal method probing does. They could likely be
1991 let (ty, autoderefs, final_mt) =
1992 autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
1993 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
1994 step(adj_ty, autoderefref)
1997 if final_mt.is_some() {
2001 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2002 // do a final unsized coercion to yield [T].
2004 ty::ty_vec(element_ty, Some(n)) => {
2005 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2006 let autoderefref = ty::AutoDerefRef {
2007 autoderefs: autoderefs,
2008 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2010 step(adjusted_ty, autoderefref)
2018 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2019 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2020 /// This loop implements one step in that search; the autoderef loop is implemented by
2021 /// `autoderef_for_index`.
2022 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2023 method_call: MethodCall,
2025 base_expr: &ast::Expr,
2026 adjusted_ty: Ty<'tcx>,
2027 adjustment: ty::AutoDerefRef<'tcx>,
2028 lvalue_pref: LvaluePreference,
2030 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2032 let tcx = fcx.tcx();
2033 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2035 base_expr.repr(tcx),
2036 adjusted_ty.repr(tcx),
2038 index_ty.repr(tcx));
2040 let input_ty = fcx.infcx().next_ty_var();
2042 // First, try built-in indexing.
2043 match (ty::index(adjusted_ty), &index_ty.sty) {
2044 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2045 debug!("try_index_step: success, using built-in indexing");
2046 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2047 return Some((tcx.types.uint, ty));
2052 // Try `IndexMut` first, if preferred.
2053 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2054 (PreferMutLvalue, Some(trait_did)) => {
2055 method::lookup_in_trait_adjusted(fcx,
2058 token::intern("index_mut"),
2062 Some(vec![input_ty]))
2067 // Otherwise, fall back to `Index`.
2068 let method = match (method, tcx.lang_items.index_trait()) {
2069 (None, Some(trait_did)) => {
2070 method::lookup_in_trait_adjusted(fcx,
2073 token::intern("index"),
2077 Some(vec![input_ty]))
2079 (method, _) => method,
2082 // If some lookup succeeds, write callee into table and extract index/element
2083 // type from the method signature.
2084 // If some lookup succeeded, install method in table
2085 method.and_then(|method| {
2086 debug!("try_index_step: success, using overloaded indexing");
2087 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2088 map(|ret| (input_ty, ret.ty))
2092 /// Given the head of a `for` expression, looks up the `next` method in the
2093 /// `Iterator` trait. Panics if the expression does not implement `next`.
2095 /// The return type of this function represents the concrete element type
2096 /// `A` in the type `Iterator<A>` that the method returns.
2097 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2098 iterator_expr: &ast::Expr,
2099 loop_id: ast::NodeId)
2101 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2102 Ok(trait_did) => trait_did,
2103 Err(ref err_string) => {
2104 fcx.tcx().sess.span_err(iterator_expr.span,
2106 return fcx.tcx().types.err
2110 let expr_type = fcx.expr_ty(&*iterator_expr);
2111 let method = method::lookup_in_trait(fcx,
2113 Some(&*iterator_expr),
2114 token::intern("next"),
2119 // Regardless of whether the lookup succeeds, check the method arguments
2120 // so that we have *some* type for each argument.
2121 let method_type = match method {
2122 Some(ref method) => method.ty,
2124 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2126 if !ty::type_is_error(true_expr_type) {
2127 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2128 fcx.tcx().sess.span_err(iterator_expr.span,
2129 &format!("`for` loop expression has type `{}` which does \
2130 not implement the `Iterator` trait; \
2137 let return_type = check_method_argument_types(fcx,
2148 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2151 // We expect the return type to be `Option` or something like it.
2152 // Grab the first parameter of its type substitution.
2153 let return_type = match return_type {
2154 ty::FnConverging(return_type) =>
2155 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2156 ty::FnDiverging => fcx.tcx().types.err
2158 match return_type.sty {
2159 ty::ty_enum(_, ref substs)
2160 if !substs.types.is_empty_in(subst::TypeSpace) => {
2161 *substs.types.get(subst::TypeSpace, 0)
2167 fcx.tcx().sess.span_err(iterator_expr.span,
2168 &format!("`next` method of the `Iterator` \
2169 trait has an unexpected type `{}`",
2170 fcx.infcx().ty_to_string(return_type))
2176 None => fcx.tcx().types.err
2180 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2182 method_fn_ty: Ty<'tcx>,
2183 callee_expr: &ast::Expr,
2184 args_no_rcvr: &[P<ast::Expr>],
2185 autoref_args: AutorefArgs,
2186 tuple_arguments: TupleArgumentsFlag,
2187 expected: Expectation<'tcx>)
2188 -> ty::FnOutput<'tcx> {
2189 if ty::type_is_error(method_fn_ty) {
2190 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2192 let err_inputs = match tuple_arguments {
2193 DontTupleArguments => err_inputs,
2194 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2197 check_argument_types(fcx,
2205 ty::FnConverging(fcx.tcx().types.err)
2207 match method_fn_ty.sty {
2208 ty::ty_bare_fn(_, ref fty) => {
2209 // HACK(eddyb) ignore self in the definition (see above).
2210 let expected_arg_tys = expected_types_for_fn_args(fcx,
2214 &fty.sig.0.inputs[1..]);
2215 check_argument_types(fcx,
2217 &fty.sig.0.inputs[1..],
2218 &expected_arg_tys[],
2226 fcx.tcx().sess.span_bug(callee_expr.span,
2227 "method without bare fn type");
2233 /// Generic function that factors out common logic from function calls, method calls and overloaded
2235 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2237 fn_inputs: &[Ty<'tcx>],
2238 expected_arg_tys: &[Ty<'tcx>],
2239 args: &[P<ast::Expr>],
2240 autoref_args: AutorefArgs,
2242 tuple_arguments: TupleArgumentsFlag) {
2243 let tcx = fcx.ccx.tcx;
2245 // Grab the argument types, supplying fresh type variables
2246 // if the wrong number of arguments were supplied
2247 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2253 let mut expected_arg_tys = expected_arg_tys;
2254 let expected_arg_count = fn_inputs.len();
2255 let formal_tys = if tuple_arguments == TupleArguments {
2256 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2257 match tuple_type.sty {
2258 ty::ty_tup(ref arg_types) => {
2259 if arg_types.len() != args.len() {
2260 span_err!(tcx.sess, sp, E0057,
2261 "this function takes {} parameter{} but {} parameter{} supplied",
2263 if arg_types.len() == 1 {""} else {"s"},
2265 if args.len() == 1 {" was"} else {"s were"});
2266 expected_arg_tys = &[][];
2267 err_args(fcx.tcx(), args.len())
2269 expected_arg_tys = match expected_arg_tys.get(0) {
2270 Some(&ty) => match ty.sty {
2271 ty::ty_tup(ref tys) => &**tys,
2276 (*arg_types).clone()
2280 span_err!(tcx.sess, sp, E0059,
2281 "cannot use call notation; the first type parameter \
2282 for the function trait is neither a tuple nor unit");
2283 expected_arg_tys = &[][];
2284 err_args(fcx.tcx(), args.len())
2287 } else if expected_arg_count == supplied_arg_count {
2289 } else if variadic {
2290 if supplied_arg_count >= expected_arg_count {
2293 span_err!(tcx.sess, sp, E0060,
2294 "this function takes at least {} parameter{} \
2295 but {} parameter{} supplied",
2297 if expected_arg_count == 1 {""} else {"s"},
2299 if supplied_arg_count == 1 {" was"} else {"s were"});
2300 expected_arg_tys = &[][];
2301 err_args(fcx.tcx(), supplied_arg_count)
2304 span_err!(tcx.sess, sp, E0061,
2305 "this function takes {} parameter{} but {} parameter{} supplied",
2307 if expected_arg_count == 1 {""} else {"s"},
2309 if supplied_arg_count == 1 {" was"} else {"s were"});
2310 expected_arg_tys = &[][];
2311 err_args(fcx.tcx(), supplied_arg_count)
2314 debug!("check_argument_types: formal_tys={:?}",
2315 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2317 // Check the arguments.
2318 // We do this in a pretty awful way: first we typecheck any arguments
2319 // that are not anonymous functions, then we typecheck the anonymous
2320 // functions. This is so that we have more information about the types
2321 // of arguments when we typecheck the functions. This isn't really the
2322 // right way to do this.
2323 let xs = [false, true];
2324 for check_blocks in xs.iter() {
2325 let check_blocks = *check_blocks;
2326 debug!("check_blocks={}", check_blocks);
2328 // More awful hacks: before we check the blocks, try to do
2329 // an "opportunistic" vtable resolution of any trait
2330 // bounds on the call.
2332 vtable::select_new_fcx_obligations(fcx);
2335 // For variadic functions, we don't have a declared type for all of
2336 // the arguments hence we only do our usual type checking with
2337 // the arguments who's types we do know.
2338 let t = if variadic {
2340 } else if tuple_arguments == TupleArguments {
2345 for (i, arg) in args.iter().take(t).enumerate() {
2346 let is_block = match arg.node {
2347 ast::ExprClosure(..) => true,
2351 if is_block == check_blocks {
2352 debug!("checking the argument");
2353 let mut formal_ty = formal_tys[i];
2355 match autoref_args {
2356 AutorefArgs::Yes => {
2357 match formal_ty.sty {
2358 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2361 // So we hit this case when one implements the
2362 // operator traits but leaves an argument as
2363 // just T instead of &T. We'll catch it in the
2364 // mismatch impl/trait method phase no need to
2367 formal_ty = tcx.types.err;
2371 AutorefArgs::No => {}
2374 // The special-cased logic below has three functions:
2375 // 1. Provide as good of an expected type as possible.
2376 let expected = expected_arg_tys.get(i).map(|&ty| {
2377 Expectation::rvalue_hint(ty)
2380 check_expr_with_unifier(fcx, &**arg,
2381 expected.unwrap_or(ExpectHasType(formal_ty)),
2383 // 2. Coerce to the most detailed type that could be coerced
2384 // to, which is `expected_ty` if `rvalue_hint` returns an
2385 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2386 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2387 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2389 // 3. Relate the expected type and the formal one,
2390 // if the expected type was used for the coercion.
2391 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2397 // We also need to make sure we at least write the ty of the other
2398 // arguments which we skipped above.
2400 for arg in args.iter().skip(expected_arg_count) {
2401 check_expr(fcx, &**arg);
2403 // There are a few types which get autopromoted when passed via varargs
2404 // in C but we just error out instead and require explicit casts.
2405 let arg_ty = structurally_resolved_type(fcx, arg.span,
2406 fcx.expr_ty(&**arg));
2408 ty::ty_float(ast::TyF32) => {
2409 fcx.type_error_message(arg.span,
2411 format!("can't pass an {} to variadic \
2412 function, cast to c_double", t)
2415 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2416 fcx.type_error_message(arg.span, |t| {
2417 format!("can't pass {} to variadic \
2418 function, cast to c_int",
2422 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2423 fcx.type_error_message(arg.span, |t| {
2424 format!("can't pass {} to variadic \
2425 function, cast to c_uint",
2435 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2436 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2437 range(0, len).map(|_| tcx.types.err).collect()
2440 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2441 call_expr: &ast::Expr,
2442 output: ty::FnOutput<'tcx>) {
2443 fcx.write_ty(call_expr.id, match output {
2444 ty::FnConverging(output_ty) => output_ty,
2445 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2449 // AST fragment checking
2450 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2452 expected: Expectation<'tcx>)
2455 let tcx = fcx.ccx.tcx;
2458 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2459 ast::LitBinary(..) => {
2461 tcx.mk_region(ty::ReStatic),
2462 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2464 ast::LitByte(_) => tcx.types.u8,
2465 ast::LitChar(_) => tcx.types.char,
2466 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2467 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2468 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2469 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2471 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2472 ty::ty_char => Some(tcx.types.u8),
2473 ty::ty_ptr(..) => Some(tcx.types.uint),
2474 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2478 opt_ty.unwrap_or_else(
2479 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2481 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2482 ast::LitFloatUnsuffixed(_) => {
2483 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2485 ty::ty_float(_) => Some(ty),
2489 opt_ty.unwrap_or_else(
2490 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2492 ast::LitBool(_) => tcx.types.bool
2496 pub fn valid_range_bounds(ccx: &CrateCtxt,
2500 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2501 Some(val) => Some(val <= 0),
2506 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2508 expected: Ty<'tcx>) {
2509 check_expr_with_unifier(
2510 fcx, expr, ExpectHasType(expected), NoPreference,
2511 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2514 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2516 expected: Ty<'tcx>) {
2517 check_expr_with_unifier(
2518 fcx, expr, ExpectHasType(expected), NoPreference,
2519 || demand::coerce(fcx, expr.span, expected, expr));
2522 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2523 expected: Ty<'tcx>) {
2524 check_expr_with_unifier(
2525 fcx, expr, ExpectHasType(expected), NoPreference,
2529 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2531 expected: Expectation<'tcx>) {
2532 check_expr_with_unifier(
2533 fcx, expr, expected, NoPreference,
2537 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2539 expected: Expectation<'tcx>,
2540 lvalue_pref: LvaluePreference)
2542 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2545 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2546 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2549 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2550 lvalue_pref: LvaluePreference) {
2551 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2554 // determine the `self` type, using fresh variables for all variables
2555 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2556 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2558 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2559 span: Span, // (potential) receiver for this impl
2561 -> TypeAndSubsts<'tcx> {
2562 let tcx = fcx.tcx();
2564 let ity = ty::lookup_item_type(tcx, did);
2565 let (n_tps, rps, raw_ty) =
2566 (ity.generics.types.len(subst::TypeSpace),
2567 ity.generics.regions.get_slice(subst::TypeSpace),
2570 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2571 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2572 let substs = subst::Substs::new_type(tps, rps);
2573 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2575 TypeAndSubsts { substs: substs, ty: substd_ty }
2578 // Controls whether the arguments are automatically referenced. This is useful
2579 // for overloaded binary and unary operators.
2580 #[derive(Copy, PartialEq)]
2581 pub enum AutorefArgs {
2586 /// Controls whether the arguments are tupled. This is used for the call
2589 /// Tupling means that all call-side arguments are packed into a tuple and
2590 /// passed as a single parameter. For example, if tupling is enabled, this
2593 /// fn f(x: (int, int))
2595 /// Can be called as:
2602 #[derive(Clone, Eq, PartialEq)]
2603 enum TupleArgumentsFlag {
2608 /// Unifies the return type with the expected type early, for more coercions
2609 /// and forward type information on the argument expressions.
2610 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2612 expected_ret: Expectation<'tcx>,
2613 formal_ret: ty::FnOutput<'tcx>,
2614 formal_args: &[Ty<'tcx>])
2616 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2617 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2618 fcx.infcx().commit_regions_if_ok(|| {
2619 // Attempt to apply a subtyping relationship between the formal
2620 // return type (likely containing type variables if the function
2621 // is polymorphic) and the expected return type.
2622 // No argument expectations are produced if unification fails.
2623 let origin = infer::Misc(call_span);
2624 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2625 // FIXME(#15760) can't use try! here, FromError doesn't default
2626 // to identity so the resulting type is not constrained.
2627 if let Err(e) = ures {
2631 // Record all the argument types, with the substitutions
2632 // produced from the above subtyping unification.
2633 Ok(formal_args.iter().map(|ty| {
2634 fcx.infcx().resolve_type_vars_if_possible(ty)
2640 }).unwrap_or(vec![]);
2641 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2642 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2643 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2648 /// If an expression has any sub-expressions that result in a type error,
2649 /// inspecting that expression's type with `ty::type_is_error` will return
2650 /// true. Likewise, if an expression is known to diverge, inspecting its
2651 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2652 /// strict, _|_ can appear in the type of an expression that does not,
2653 /// itself, diverge: for example, fn() -> _|_.)
2654 /// Note that inspecting a type's structure *directly* may expose the fact
2655 /// that there are actually multiple representations for `ty_err`, so avoid
2656 /// that when err needs to be handled differently.
2657 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2659 expected: Expectation<'tcx>,
2660 lvalue_pref: LvaluePreference,
2664 debug!(">> typechecking: expr={} expected={}",
2665 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2667 // Checks a method call.
2668 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2670 method_name: ast::SpannedIdent,
2671 args: &[P<ast::Expr>],
2673 expected: Expectation<'tcx>,
2674 lvalue_pref: LvaluePreference) {
2675 let rcvr = &*args[0];
2676 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2678 // no need to check for bot/err -- callee does that
2679 let expr_t = structurally_resolved_type(fcx,
2681 fcx.expr_ty(&*rcvr));
2683 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2684 let fn_ty = match method::lookup(fcx,
2686 method_name.node.name,
2692 let method_ty = method.ty;
2693 let method_call = MethodCall::expr(expr.id);
2694 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2698 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
2699 fcx.write_error(expr.id);
2704 // Call the generic checker.
2705 let ret_ty = check_method_argument_types(fcx,
2714 write_call(fcx, expr, ret_ty);
2717 // A generic function for checking the then and else in an if
2719 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2720 cond_expr: &ast::Expr,
2721 then_blk: &ast::Block,
2722 opt_else_expr: Option<&ast::Expr>,
2725 expected: Expectation<'tcx>) {
2726 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2728 let expected = expected.adjust_for_branches(fcx);
2729 check_block_with_expected(fcx, then_blk, expected);
2730 let then_ty = fcx.node_ty(then_blk.id);
2732 let branches_ty = match opt_else_expr {
2733 Some(ref else_expr) => {
2734 check_expr_with_expectation(fcx, &**else_expr, expected);
2735 let else_ty = fcx.expr_ty(&**else_expr);
2736 infer::common_supertype(fcx.infcx(),
2737 infer::IfExpression(sp),
2743 infer::common_supertype(fcx.infcx(),
2744 infer::IfExpressionWithNoElse(sp),
2747 ty::mk_nil(fcx.tcx()))
2751 let cond_ty = fcx.expr_ty(cond_expr);
2752 let if_ty = if ty::type_is_error(cond_ty) {
2758 fcx.write_ty(id, if_ty);
2761 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2765 trait_did: Option<ast::DefId>,
2767 rhs: Option<&P<ast::Expr>>,
2769 autoref_args: AutorefArgs) -> Ty<'tcx> where
2772 let method = match trait_did {
2773 Some(trait_did) => {
2774 // We do eager coercions to make using operators
2777 // - If the input is of type &'a T (resp. &'a mut T),
2778 // then reborrow it to &'b T (resp. &'b mut T) where
2779 // 'b <= 'a. This makes things like `x == y`, where
2780 // `x` and `y` are both region pointers, work. We
2781 // could also solve this with variance or different
2782 // traits that don't force left and right to have same
2784 let (adj_ty, adjustment) = match lhs_ty.sty {
2785 ty::ty_rptr(r_in, mt) => {
2786 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2787 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2788 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2789 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2790 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2791 (adjusted_ty, adjustment)
2794 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2798 debug!("adjusted_ty={} adjustment={:?}",
2799 adj_ty.repr(fcx.tcx()),
2802 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2803 trait_did, adjustment, adj_ty, None)
2807 let args = match rhs {
2808 Some(rhs) => slice::ref_slice(rhs),
2813 let method_ty = method.ty;
2814 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2815 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2816 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2817 match check_method_argument_types(fcx,
2825 ty::FnConverging(result_type) => result_type,
2826 ty::FnDiverging => fcx.tcx().types.err
2831 // Check the args anyway
2832 // so we get all the error messages
2833 let expected_ty = fcx.tcx().types.err;
2834 check_method_argument_types(fcx,
2847 // could be either an expr_binop or an expr_assign_binop
2848 fn check_binop(fcx: &FnCtxt,
2853 is_binop_assignment: IsBinopAssignment) {
2854 let tcx = fcx.ccx.tcx;
2856 let lvalue_pref = match is_binop_assignment {
2857 BinopAssignment => PreferMutLvalue,
2858 SimpleBinop => NoPreference
2860 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2862 // Callee does bot / err checking
2863 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2864 fcx.expr_ty(&*lhs));
2866 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2867 // Shift is a special case: rhs must be uint, no matter what lhs is
2868 check_expr(fcx, &**rhs);
2869 let rhs_ty = fcx.expr_ty(&**rhs);
2870 let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
2871 if ty::type_is_integral(rhs_ty) {
2872 fcx.write_ty(expr.id, lhs_t);
2874 fcx.type_error_message(
2878 "right-hand-side of a shift operation must have integral type, \
2884 fcx.write_ty(expr.id, fcx.tcx().types.err);
2889 if ty::is_binopable(tcx, lhs_t, op) {
2890 let tvar = fcx.infcx().next_ty_var();
2891 demand::suptype(fcx, expr.span, tvar, lhs_t);
2892 check_expr_has_type(fcx, &**rhs, tvar);
2894 let result_t = match op {
2895 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2897 if ty::type_is_simd(tcx, lhs_t) {
2898 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2899 fcx.type_error_message(expr.span,
2901 format!("binary comparison \
2902 operation `{}` not \
2903 supported for floating \
2904 point SIMD vector `{}`",
2905 ast_util::binop_to_string(op),
2916 fcx.tcx().types.bool
2922 fcx.write_ty(expr.id, result_t);
2926 if op == ast::BiOr || op == ast::BiAnd {
2927 // This is an error; one of the operands must have the wrong
2929 fcx.write_error(expr.id);
2930 fcx.write_error(rhs.id);
2931 fcx.type_error_message(expr.span,
2933 format!("binary operation `{}` cannot be applied \
2935 ast_util::binop_to_string(op),
2942 // Check for overloaded operators if not an assignment.
2943 let result_t = if is_binop_assignment == SimpleBinop {
2944 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2946 fcx.type_error_message(expr.span,
2948 format!("binary assignment \
2950 cannot be applied to \
2952 ast_util::binop_to_string(op),
2957 check_expr(fcx, &**rhs);
2961 fcx.write_ty(expr.id, result_t);
2962 if ty::type_is_error(result_t) {
2963 fcx.write_ty(rhs.id, result_t);
2967 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2969 lhs_expr: &ast::Expr,
2970 lhs_resolved_t: Ty<'tcx>,
2972 rhs: &P<ast::Expr>) -> Ty<'tcx> {
2973 let tcx = fcx.ccx.tcx;
2974 let lang = &tcx.lang_items;
2975 let (name, trait_did) = match op {
2976 ast::BiAdd => ("add", lang.add_trait()),
2977 ast::BiSub => ("sub", lang.sub_trait()),
2978 ast::BiMul => ("mul", lang.mul_trait()),
2979 ast::BiDiv => ("div", lang.div_trait()),
2980 ast::BiRem => ("rem", lang.rem_trait()),
2981 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2982 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2983 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2984 ast::BiShl => ("shl", lang.shl_trait()),
2985 ast::BiShr => ("shr", lang.shr_trait()),
2986 ast::BiLt => ("lt", lang.ord_trait()),
2987 ast::BiLe => ("le", lang.ord_trait()),
2988 ast::BiGe => ("ge", lang.ord_trait()),
2989 ast::BiGt => ("gt", lang.ord_trait()),
2990 ast::BiEq => ("eq", lang.eq_trait()),
2991 ast::BiNe => ("ne", lang.eq_trait()),
2992 ast::BiAnd | ast::BiOr => {
2993 check_expr(fcx, &**rhs);
2994 return tcx.types.err;
2997 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2998 trait_did, lhs_expr, Some(rhs), || {
2999 fcx.type_error_message(ex.span, |actual| {
3000 format!("binary operation `{}` cannot be applied to type `{}`",
3001 ast_util::binop_to_string(op),
3003 }, lhs_resolved_t, None)
3004 }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3007 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3010 trait_did: Option<ast::DefId>,
3012 rhs_expr: &ast::Expr,
3014 op: ast::UnOp) -> Ty<'tcx> {
3015 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3016 trait_did, rhs_expr, None, || {
3017 fcx.type_error_message(ex.span, |actual| {
3018 format!("cannot apply unary operator `{}` to type `{}`",
3021 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3024 // Check field access expressions
3025 fn check_field(fcx: &FnCtxt,
3027 lvalue_pref: LvaluePreference,
3029 field: &ast::SpannedIdent) {
3030 let tcx = fcx.ccx.tcx;
3031 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3032 let expr_t = structurally_resolved_type(fcx, expr.span,
3034 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3035 let (_, autoderefs, field_ty) =
3036 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3038 ty::ty_struct(base_id, substs) => {
3039 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3040 let fields = ty::lookup_struct_fields(tcx, base_id);
3041 fcx.lookup_field_ty(expr.span, base_id, &fields[],
3042 field.node.name, &(*substs))
3049 fcx.write_ty(expr.id, field_ty);
3050 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3056 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3057 fcx.type_error_message(
3060 format!("attempted to take value of method `{}` on type \
3061 `{}`", token::get_ident(field.node), actual)
3065 tcx.sess.span_help(field.span,
3066 "maybe a `()` to call it is missing? \
3067 If not, try an anonymous function");
3069 fcx.type_error_message(
3072 format!("attempted access of field `{}` on \
3073 type `{}`, but no field with that \
3075 token::get_ident(field.node),
3081 fcx.write_error(expr.id);
3084 // Check tuple index expressions
3085 fn check_tup_field(fcx: &FnCtxt,
3087 lvalue_pref: LvaluePreference,
3089 idx: codemap::Spanned<uint>) {
3090 let tcx = fcx.ccx.tcx;
3091 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3092 let expr_t = structurally_resolved_type(fcx, expr.span,
3094 let mut tuple_like = false;
3095 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3096 let (_, autoderefs, field_ty) =
3097 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3099 ty::ty_struct(base_id, substs) => {
3100 tuple_like = ty::is_tuple_struct(tcx, base_id);
3102 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3103 let fields = ty::lookup_struct_fields(tcx, base_id);
3104 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3105 idx.node, &(*substs))
3110 ty::ty_tup(ref v) => {
3112 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3119 fcx.write_ty(expr.id, field_ty);
3120 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3125 fcx.type_error_message(
3129 format!("attempted out-of-bounds tuple index `{}` on \
3134 format!("attempted tuple index `{}` on type `{}`, but the \
3135 type was not a tuple or tuple struct",
3142 fcx.write_error(expr.id);
3145 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3146 struct_ty: Ty<'tcx>,
3148 class_id: ast::DefId,
3149 node_id: ast::NodeId,
3150 substitutions: &'tcx subst::Substs<'tcx>,
3151 field_types: &[ty::field_ty],
3152 ast_fields: &[ast::Field],
3153 check_completeness: bool,
3154 enum_id_opt: Option<ast::DefId>) {
3155 let tcx = fcx.ccx.tcx;
3157 let mut class_field_map = FnvHashMap::new();
3158 let mut fields_found = 0;
3159 for field in field_types.iter() {
3160 class_field_map.insert(field.name, (field.id, false));
3163 let mut error_happened = false;
3165 // Typecheck each field.
3166 for field in ast_fields.iter() {
3167 let mut expected_field_type = tcx.types.err;
3169 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3172 fcx.type_error_message(
3174 |actual| match enum_id_opt {
3176 let variant_type = ty::enum_variant_with_id(tcx,
3179 format!("struct variant `{}::{}` has no field named `{}`",
3180 actual, variant_type.name.as_str(),
3181 token::get_ident(field.ident.node))
3184 format!("structure `{}` has no field named `{}`",
3186 token::get_ident(field.ident.node))
3191 error_happened = true;
3193 Some((_, true)) => {
3194 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3195 "field `{}` specified more than once",
3196 token::get_ident(field.ident.node));
3197 error_happened = true;
3199 Some((field_id, false)) => {
3200 expected_field_type =
3201 ty::lookup_field_type(
3202 tcx, class_id, field_id, substitutions);
3203 expected_field_type =
3204 fcx.normalize_associated_types_in(
3205 field.span, &expected_field_type);
3206 class_field_map.insert(
3207 field.ident.node.name, (field_id, true));
3212 // Make sure to give a type to the field even if there's
3213 // an error, so we can continue typechecking
3214 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3218 fcx.write_error(node_id);
3221 if check_completeness && !error_happened {
3222 // Make sure the programmer specified all the fields.
3223 assert!(fields_found <= field_types.len());
3224 if fields_found < field_types.len() {
3225 let mut missing_fields = Vec::new();
3226 for class_field in field_types.iter() {
3227 let name = class_field.name;
3228 let (_, seen) = class_field_map[name];
3230 missing_fields.push(
3231 format!("`{}`", token::get_name(name).get()))
3235 span_err!(tcx.sess, span, E0063,
3236 "missing field{}: {}",
3237 if missing_fields.len() == 1 {""} else {"s"},
3238 missing_fields.connect(", "));
3242 if !error_happened {
3243 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3244 class_id, substitutions));
3248 fn check_struct_constructor(fcx: &FnCtxt,
3250 span: codemap::Span,
3251 class_id: ast::DefId,
3252 fields: &[ast::Field],
3253 base_expr: Option<&ast::Expr>) {
3254 let tcx = fcx.ccx.tcx;
3256 // Generate the struct type.
3258 ty: mut struct_type,
3259 substs: struct_substs
3260 } = fcx.instantiate_type(span, class_id);
3262 // Look up and check the fields.
3263 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3264 check_struct_or_variant_fields(fcx,
3269 fcx.ccx.tcx.mk_substs(struct_substs),
3272 base_expr.is_none(),
3274 if ty::type_is_error(fcx.node_ty(id)) {
3275 struct_type = tcx.types.err;
3278 // Check the base expression if necessary.
3281 Some(base_expr) => {
3282 check_expr_has_type(fcx, &*base_expr, struct_type);
3286 // Write in the resulting type.
3287 fcx.write_ty(id, struct_type);
3290 fn check_struct_enum_variant(fcx: &FnCtxt,
3292 span: codemap::Span,
3293 enum_id: ast::DefId,
3294 variant_id: ast::DefId,
3295 fields: &[ast::Field]) {
3296 let tcx = fcx.ccx.tcx;
3298 // Look up the number of type parameters and the raw type, and
3299 // determine whether the enum is region-parameterized.
3302 substs: substitutions
3303 } = fcx.instantiate_type(span, enum_id);
3305 // Look up and check the enum variant fields.
3306 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3307 check_struct_or_variant_fields(fcx,
3312 fcx.ccx.tcx.mk_substs(substitutions),
3317 fcx.write_ty(id, enum_type);
3320 fn check_struct_fields_on_error(fcx: &FnCtxt,
3322 fields: &[ast::Field],
3323 base_expr: &Option<P<ast::Expr>>) {
3324 // Make sure to still write the types
3325 // otherwise we might ICE
3326 fcx.write_error(id);
3327 for field in fields.iter() {
3328 check_expr(fcx, &*field.expr);
3331 Some(ref base) => check_expr(fcx, &**base),
3336 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3338 let tcx = fcx.ccx.tcx;
3341 ast::ExprBox(ref opt_place, ref subexpr) => {
3342 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3343 check_expr(fcx, &**subexpr);
3345 let mut checked = false;
3346 opt_place.as_ref().map(|place| match place.node {
3347 ast::ExprPath(ref path) => {
3348 // FIXME(pcwalton): For now we hardcode the two permissible
3349 // places: the exchange heap and the managed heap.
3350 let definition = lookup_def(fcx, path.span, place.id);
3351 let def_id = definition.def_id();
3352 let referent_ty = fcx.expr_ty(&**subexpr);
3353 if tcx.lang_items.exchange_heap() == Some(def_id) {
3354 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3362 span_err!(tcx.sess, expr.span, E0066,
3363 "only the managed heap and exchange heap are currently supported");
3364 fcx.write_ty(id, tcx.types.err);
3368 ast::ExprLit(ref lit) => {
3369 let typ = check_lit(fcx, &**lit, expected);
3370 fcx.write_ty(id, typ);
3372 ast::ExprBinary(op, ref lhs, ref rhs) => {
3373 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3375 let lhs_ty = fcx.expr_ty(&**lhs);
3376 let rhs_ty = fcx.expr_ty(&**rhs);
3377 if ty::type_is_error(lhs_ty) ||
3378 ty::type_is_error(rhs_ty) {
3379 fcx.write_error(id);
3382 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3383 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3385 let lhs_t = fcx.expr_ty(&**lhs);
3386 let result_t = fcx.expr_ty(expr);
3387 demand::suptype(fcx, expr.span, result_t, lhs_t);
3389 let tcx = fcx.tcx();
3390 if !ty::expr_is_lval(tcx, &**lhs) {
3391 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3394 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3396 // Overwrite result of check_binop...this preserves existing behavior
3397 // but seems quite dubious with regard to user-defined methods
3398 // and so forth. - Niko
3399 if !ty::type_is_error(result_t) {
3400 fcx.write_nil(expr.id);
3403 ast::ExprUnary(unop, ref oprnd) => {
3404 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3406 ast::UnUniq => match ty.sty {
3407 ty::ty_uniq(ty) => {
3408 Expectation::rvalue_hint(ty)
3414 ast::UnNot | ast::UnNeg => {
3422 let lvalue_pref = match unop {
3423 ast::UnDeref => lvalue_pref,
3426 check_expr_with_expectation_and_lvalue_pref(
3427 fcx, &**oprnd, expected_inner, lvalue_pref);
3428 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3430 if !ty::type_is_error(oprnd_t) {
3433 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3436 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3437 oprnd_t = match ty::deref(oprnd_t, true) {
3439 None => match try_overloaded_deref(fcx, expr.span,
3440 Some(MethodCall::expr(expr.id)),
3441 Some(&**oprnd), oprnd_t, lvalue_pref) {
3444 let is_newtype = match oprnd_t.sty {
3445 ty::ty_struct(did, substs) => {
3446 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3448 && fields[0].name ==
3449 token::special_idents::unnamed_field.name
3454 // This is an obsolete struct deref
3455 span_err!(tcx.sess, expr.span, E0068,
3456 "single-field tuple-structs can \
3457 no longer be dereferenced");
3459 fcx.type_error_message(expr.span, |actual| {
3460 format!("type `{}` cannot be \
3461 dereferenced", actual)
3470 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3472 if !(ty::type_is_integral(oprnd_t) ||
3473 oprnd_t.sty == ty::ty_bool) {
3474 oprnd_t = check_user_unop(fcx, "!", "not",
3475 tcx.lang_items.not_trait(),
3476 expr, &**oprnd, oprnd_t, unop);
3480 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3482 if !(ty::type_is_integral(oprnd_t) ||
3483 ty::type_is_fp(oprnd_t)) {
3484 oprnd_t = check_user_unop(fcx, "-", "neg",
3485 tcx.lang_items.neg_trait(),
3486 expr, &**oprnd, oprnd_t, unop);
3491 fcx.write_ty(id, oprnd_t);
3493 ast::ExprAddrOf(mutbl, ref oprnd) => {
3494 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3496 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3497 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3498 // Lvalues may legitimately have unsized types.
3499 // For example, dereferences of a fat pointer and
3500 // the last field of a struct can be unsized.
3501 ExpectHasType(mt.ty)
3503 Expectation::rvalue_hint(mt.ty)
3509 let lvalue_pref = match mutbl {
3510 ast::MutMutable => PreferMutLvalue,
3511 ast::MutImmutable => NoPreference
3513 check_expr_with_expectation_and_lvalue_pref(fcx,
3518 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3519 let oprnd_t = if ty::type_is_error(tm.ty) {
3522 // Note: at this point, we cannot say what the best lifetime
3523 // is to use for resulting pointer. We want to use the
3524 // shortest lifetime possible so as to avoid spurious borrowck
3525 // errors. Moreover, the longest lifetime will depend on the
3526 // precise details of the value whose address is being taken
3527 // (and how long it is valid), which we don't know yet until type
3528 // inference is complete.
3530 // Therefore, here we simply generate a region variable. The
3531 // region inferencer will then select the ultimate value.
3532 // Finally, borrowck is charged with guaranteeing that the
3533 // value whose address was taken can actually be made to live
3534 // as long as it needs to live.
3536 // String literals are already, implicitly converted to slices.
3537 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3538 // Empty slices live in static memory.
3539 ast::ExprVec(ref elements) if elements.len() == 0 => {
3540 // Note: we do not assign a lifetime of
3541 // static. This is because the resulting type
3542 // `&'static [T]` would require that T outlives
3544 let region = fcx.infcx().next_region_var(
3545 infer::AddrOfSlice(expr.span));
3546 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3549 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3550 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3554 fcx.write_ty(id, oprnd_t);
3556 ast::ExprPath(ref path) => {
3557 let defn = lookup_def(fcx, path.span, id);
3558 let pty = type_scheme_for_def(fcx, expr.span, defn);
3559 instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3561 // We always require that the type provided as the value for
3562 // a type parameter outlives the moment of instantiation.
3563 constrain_path_type_parameters(fcx, expr);
3565 ast::ExprQPath(ref qpath) => {
3566 // Require explicit type params for the trait.
3567 let self_ty = fcx.to_ty(&*qpath.self_type);
3568 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3570 let defn = lookup_def(fcx, expr.span, id);
3571 let pty = type_scheme_for_def(fcx, expr.span, defn);
3572 let mut path = qpath.trait_ref.path.clone();
3573 path.segments.push(qpath.item_path.clone());
3574 instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3576 // We always require that the type provided as the value for
3577 // a type parameter outlives the moment of instantiation.
3578 constrain_path_type_parameters(fcx, expr);
3580 ast::ExprInlineAsm(ref ia) => {
3581 for &(_, ref input) in ia.inputs.iter() {
3582 check_expr(fcx, &**input);
3584 for &(_, ref out, _) in ia.outputs.iter() {
3585 check_expr(fcx, &**out);
3589 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3590 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3591 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3592 ast::ExprRet(ref expr_opt) => {
3594 ty::FnConverging(result_type) => {
3597 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3598 result_type, ty::mk_nil(fcx.tcx())) {
3599 span_err!(tcx.sess, expr.span, E0069,
3600 "`return;` in function returning non-nil");
3603 check_expr_coercable_to_type(fcx, &**e, result_type);
3607 ty::FnDiverging => {
3608 if let Some(ref e) = *expr_opt {
3609 check_expr(fcx, &**e);
3611 span_err!(tcx.sess, expr.span, E0166,
3612 "`return` in a function declared as diverging");
3615 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3617 ast::ExprParen(ref a) => {
3618 check_expr_with_expectation_and_lvalue_pref(fcx,
3622 fcx.write_ty(id, fcx.expr_ty(&**a));
3624 ast::ExprAssign(ref lhs, ref rhs) => {
3625 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3627 let tcx = fcx.tcx();
3628 if !ty::expr_is_lval(tcx, &**lhs) {
3629 span_err!(tcx.sess, expr.span, E0070,
3630 "illegal left-hand side expression");
3633 let lhs_ty = fcx.expr_ty(&**lhs);
3634 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3635 let rhs_ty = fcx.expr_ty(&**rhs);
3637 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3639 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3640 fcx.write_error(id);
3645 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3646 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3647 id, expr.span, expected);
3649 ast::ExprIfLet(..) => {
3650 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3652 ast::ExprWhile(ref cond, ref body, _) => {
3653 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3654 check_block_no_value(fcx, &**body);
3655 let cond_ty = fcx.expr_ty(&**cond);
3656 let body_ty = fcx.node_ty(body.id);
3657 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3658 fcx.write_error(id);
3664 ast::ExprWhileLet(..) => {
3665 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3667 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3668 check_expr(fcx, &**head);
3669 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
3670 vtable::select_new_fcx_obligations(fcx);
3672 debug!("ExprForLoop each item has type {}",
3673 fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
3675 let pcx = pat_ctxt {
3677 map: pat_id_map(&tcx.def_map, &**pat),
3679 _match::check_pat(&pcx, &**pat, typ);
3681 check_block_no_value(fcx, &**block);
3684 ast::ExprLoop(ref body, _) => {
3685 check_block_no_value(fcx, &**body);
3686 if !may_break(tcx, expr.id, &**body) {
3687 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3692 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3693 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3695 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3696 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3698 ast::ExprBlock(ref b) => {
3699 check_block_with_expected(fcx, &**b, expected);
3700 fcx.write_ty(id, fcx.node_ty(b.id));
3702 ast::ExprCall(ref callee, ref args) => {
3703 callee::check_call(fcx, expr, &**callee, &args[], expected);
3705 ast::ExprMethodCall(ident, ref tps, ref args) => {
3706 check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3707 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3708 let args_err = arg_tys.fold(false,
3710 rest_err || ty::type_is_error(a)});
3712 fcx.write_error(id);
3715 ast::ExprCast(ref e, ref t) => {
3716 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3717 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3719 check_cast(fcx, expr, &**e, &**t);
3721 ast::ExprVec(ref args) => {
3722 let uty = expected.to_option(fcx).and_then(|uty| {
3724 ty::ty_vec(ty, _) => Some(ty),
3729 let typ = match uty {
3731 for e in args.iter() {
3732 check_expr_coercable_to_type(fcx, &**e, uty);
3737 let t: Ty = fcx.infcx().next_ty_var();
3738 for e in args.iter() {
3739 check_expr_has_type(fcx, &**e, t);
3744 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3745 fcx.write_ty(id, typ);
3747 ast::ExprRepeat(ref element, ref count_expr) => {
3748 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3749 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3751 let uty = match expected {
3752 ExpectHasType(uty) => {
3754 ty::ty_vec(ty, _) => Some(ty),
3761 let (element_ty, t) = match uty {
3763 check_expr_coercable_to_type(fcx, &**element, uty);
3767 let t: Ty = fcx.infcx().next_ty_var();
3768 check_expr_has_type(fcx, &**element, t);
3769 (fcx.expr_ty(&**element), t)
3774 // For [foo, ..n] where n > 1, `foo` must have
3776 fcx.require_type_meets(
3783 if ty::type_is_error(element_ty) {
3784 fcx.write_error(id);
3786 let t = ty::mk_vec(tcx, t, Some(count));
3787 fcx.write_ty(id, t);
3790 ast::ExprTup(ref elts) => {
3791 let flds = expected.only_has_type(fcx).and_then(|ty| {
3793 ty::ty_tup(ref flds) => Some(&flds[]),
3797 let mut err_field = false;
3799 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3800 let t = match flds {
3801 Some(ref fs) if i < fs.len() => {
3803 check_expr_coercable_to_type(fcx, &**e, ety);
3807 check_expr_with_expectation(fcx, &**e, NoExpectation);
3811 err_field = err_field || ty::type_is_error(t);
3815 fcx.write_error(id);
3817 let typ = ty::mk_tup(tcx, elt_ts);
3818 fcx.write_ty(id, typ);
3821 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3822 // Resolve the path.
3823 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3824 let struct_id = match def {
3825 Some(def::DefVariant(enum_id, variant_id, true)) => {
3826 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3827 variant_id, &fields[]);
3830 Some(def::DefTrait(def_id)) => {
3831 span_err!(tcx.sess, path.span, E0159,
3832 "use of trait `{}` as a struct constructor",
3833 pprust::path_to_string(path));
3834 check_struct_fields_on_error(fcx,
3841 // Verify that this was actually a struct.
3842 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3844 ty::ty_struct(struct_did, _) => {
3845 check_struct_constructor(fcx,
3850 base_expr.as_ref().map(|e| &**e));
3853 span_err!(tcx.sess, path.span, E0071,
3854 "`{}` does not name a structure",
3855 pprust::path_to_string(path));
3856 check_struct_fields_on_error(fcx,
3866 tcx.sess.span_bug(path.span,
3867 "structure constructor wasn't resolved")
3871 // Turn the path into a type and verify that that type unifies with
3872 // the resulting structure type. This is needed to handle type
3873 // parameters correctly.
3874 let actual_structure_type = fcx.expr_ty(&*expr);
3875 if !ty::type_is_error(actual_structure_type) {
3876 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3877 match fcx.mk_subty(false,
3878 infer::Misc(path.span),
3879 actual_structure_type,
3880 type_and_substs.ty) {
3882 Err(type_error) => {
3883 let type_error_description =
3884 ty::type_err_to_str(tcx, &type_error);
3887 .span_err(path.span,
3888 &format!("structure constructor specifies a \
3889 structure of type `{}`, but this \
3890 structure has type `{}`: {}",
3892 .ty_to_string(type_and_substs.ty),
3895 actual_structure_type),
3896 type_error_description)[]);
3897 ty::note_and_explain_type_err(tcx, &type_error);
3902 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3904 ast::ExprField(ref base, ref field) => {
3905 check_field(fcx, expr, lvalue_pref, &**base, field);
3907 ast::ExprTupField(ref base, idx) => {
3908 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3910 ast::ExprIndex(ref base, ref idx) => {
3911 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3912 let base_t = fcx.expr_ty(&**base);
3913 if ty::type_is_error(base_t) {
3914 fcx.write_ty(id, base_t);
3916 check_expr(fcx, &**idx);
3917 let idx_t = fcx.expr_ty(&**idx);
3918 if ty::type_is_error(idx_t) {
3919 fcx.write_ty(id, idx_t);
3921 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3924 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3926 MethodCall::expr(expr.id),
3936 Some((index_ty, element_ty)) => {
3937 // FIXME: we've already checked idx above, we should
3938 // probably just demand subtype or something here.
3939 check_expr_has_type(fcx, &**idx, index_ty);
3940 fcx.write_ty(id, element_ty);
3943 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3944 fcx.type_error_message(
3947 format!("cannot index a value of type `{}`",
3952 fcx.write_ty(id, fcx.tcx().types.err);
3958 ast::ExprRange(ref start, ref end) => {
3959 let t_start = start.as_ref().map(|e| {
3960 check_expr(fcx, &**e);
3963 let t_end = end.as_ref().map(|e| {
3964 check_expr(fcx, &**e);
3968 let idx_type = match (t_start, t_end) {
3969 (Some(ty), None) | (None, Some(ty)) => {
3972 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3973 ty::type_is_error(t_end)) => {
3974 Some(fcx.tcx().types.err)
3976 (Some(t_start), Some(t_end)) => {
3977 Some(infer::common_supertype(fcx.infcx(),
3978 infer::RangeExpression(expr.span),
3986 // Note that we don't check the type of start/end satisfy any
3987 // bounds because right now the range structs do not have any. If we add
3988 // some bounds, then we'll need to check `t_start` against them here.
3990 let range_type = match idx_type {
3991 Some(idx_type) if ty::type_is_error(idx_type) => {
3995 // Find the did from the appropriate lang item.
3996 let did = match (start, end) {
3997 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3998 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3999 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4001 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4005 if let Some(did) = did {
4006 let polytype = ty::lookup_item_type(tcx, did);
4007 let substs = Substs::new_type(vec![idx_type], vec![]);
4008 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4009 fcx.add_obligations_for_parameters(
4010 traits::ObligationCause::new(expr.span,
4012 traits::ItemObligation(did)),
4015 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4017 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4022 // Neither start nor end => FullRange
4023 if let Some(did) = tcx.lang_items.full_range_struct() {
4024 let substs = Substs::new_type(vec![], vec![]);
4025 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4027 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4033 fcx.write_ty(id, range_type);
4038 debug!("type of expr({}) {} is...", expr.id,
4039 syntax::print::pprust::expr_to_string(expr));
4040 debug!("... {}, expected is {}",
4041 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4042 expected.repr(tcx));
4047 fn constrain_path_type_parameters(fcx: &FnCtxt,
4050 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4051 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4055 impl<'tcx> Expectation<'tcx> {
4056 /// Provide an expectation for an rvalue expression given an *optional*
4057 /// hint, which is not required for type safety (the resulting type might
4058 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4059 /// is useful in determining the concrete type.
4061 /// The primary use case is where the expected type is a fat pointer,
4062 /// like `&[int]`. For example, consider the following statement:
4064 /// let x: &[int] = &[1, 2, 3];
4066 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4067 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4068 /// expectation `ExpectHasType([int])`, that would be too strong --
4069 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4070 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4071 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4072 /// which still is useful, because it informs integer literals and the like.
4073 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4074 /// for examples of where this comes up,.
4075 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4077 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4078 ExpectRvalueLikeUnsized(ty)
4080 _ => ExpectHasType(ty)
4084 // Resolves `expected` by a single level if it is a variable. If
4085 // there is no expected type or resolution is not possible (e.g.,
4086 // no constraints yet present), just returns `None`.
4087 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4092 ExpectCastableToType(t) => {
4093 ExpectCastableToType(
4094 fcx.infcx().resolve_type_vars_if_possible(&t))
4096 ExpectHasType(t) => {
4098 fcx.infcx().resolve_type_vars_if_possible(&t))
4100 ExpectRvalueLikeUnsized(t) => {
4101 ExpectRvalueLikeUnsized(
4102 fcx.infcx().resolve_type_vars_if_possible(&t))
4107 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4108 match self.resolve(fcx) {
4109 NoExpectation => None,
4110 ExpectCastableToType(ty) |
4112 ExpectRvalueLikeUnsized(ty) => Some(ty),
4116 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4117 match self.resolve(fcx) {
4118 ExpectHasType(ty) => Some(ty),
4124 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4125 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4127 NoExpectation => format!("NoExpectation"),
4128 ExpectHasType(t) => format!("ExpectHasType({})",
4130 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4132 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4138 pub fn check_decl_initializer(fcx: &FnCtxt,
4142 let local_ty = fcx.local_ty(init.span, nid);
4143 check_expr_coercable_to_type(fcx, init, local_ty)
4146 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4147 let tcx = fcx.ccx.tcx;
4149 let t = fcx.local_ty(local.span, local.id);
4150 fcx.write_ty(local.id, t);
4152 if let Some(ref init) = local.init {
4153 check_decl_initializer(fcx, local.id, &**init);
4154 let init_ty = fcx.expr_ty(&**init);
4155 if ty::type_is_error(init_ty) {
4156 fcx.write_ty(local.id, init_ty);
4160 let pcx = pat_ctxt {
4162 map: pat_id_map(&tcx.def_map, &*local.pat),
4164 _match::check_pat(&pcx, &*local.pat, t);
4165 let pat_ty = fcx.node_ty(local.pat.id);
4166 if ty::type_is_error(pat_ty) {
4167 fcx.write_ty(local.id, pat_ty);
4171 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4173 let mut saw_bot = false;
4174 let mut saw_err = false;
4176 ast::StmtDecl(ref decl, id) => {
4179 ast::DeclLocal(ref l) => {
4180 check_decl_local(fcx, &**l);
4181 let l_t = fcx.node_ty(l.id);
4182 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4183 saw_err = saw_err || ty::type_is_error(l_t);
4185 ast::DeclItem(_) => {/* ignore for now */ }
4188 ast::StmtExpr(ref expr, id) => {
4190 // Check with expected type of ()
4191 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4192 let expr_ty = fcx.expr_ty(&**expr);
4193 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4194 saw_err = saw_err || ty::type_is_error(expr_ty);
4196 ast::StmtSemi(ref expr, id) => {
4198 check_expr(fcx, &**expr);
4199 let expr_ty = fcx.expr_ty(&**expr);
4200 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4201 saw_err |= ty::type_is_error(expr_ty);
4203 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4206 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4209 fcx.write_error(node_id);
4212 fcx.write_nil(node_id)
4216 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4217 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4218 let blkty = fcx.node_ty(blk.id);
4219 if ty::type_is_error(blkty) {
4220 fcx.write_error(blk.id);
4222 let nilty = ty::mk_nil(fcx.tcx());
4223 demand::suptype(fcx, blk.span, nilty, blkty);
4227 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4229 expected: Expectation<'tcx>) {
4231 let mut fcx_ps = fcx.ps.borrow_mut();
4232 let unsafety_state = fcx_ps.recurse(blk);
4233 replace(&mut *fcx_ps, unsafety_state)
4236 let mut warned = false;
4237 let mut any_diverges = false;
4238 let mut any_err = false;
4239 for s in blk.stmts.iter() {
4240 check_stmt(fcx, &**s);
4241 let s_id = ast_util::stmt_id(&**s);
4242 let s_ty = fcx.node_ty(s_id);
4243 if any_diverges && !warned && match s.node {
4244 ast::StmtDecl(ref decl, _) => {
4246 ast::DeclLocal(_) => true,
4250 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4256 .add_lint(lint::builtin::UNREACHABLE_CODE,
4259 "unreachable statement".to_string());
4262 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4263 any_err = any_err || ty::type_is_error(s_ty);
4266 None => if any_err {
4267 fcx.write_error(blk.id);
4268 } else if any_diverges {
4269 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4271 fcx.write_nil(blk.id);
4274 if any_diverges && !warned {
4278 .add_lint(lint::builtin::UNREACHABLE_CODE,
4281 "unreachable expression".to_string());
4283 let ety = match expected {
4284 ExpectHasType(ety) => {
4285 check_expr_coercable_to_type(fcx, &**e, ety);
4289 check_expr_with_expectation(fcx, &**e, expected);
4295 fcx.write_error(blk.id);
4296 } else if any_diverges {
4297 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4299 fcx.write_ty(blk.id, ety);
4304 *fcx.ps.borrow_mut() = prev;
4307 /// Checks a constant appearing in a type. At the moment this is just the
4308 /// length expression in a fixed-length vector, but someday it might be
4309 /// extended to type-level numeric literals.
4310 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4312 expected_type: Ty<'tcx>) {
4313 let inh = static_inherited_fields(ccx);
4314 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4315 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4318 fn check_const(ccx: &CrateCtxt,
4322 let inh = static_inherited_fields(ccx);
4323 let rty = ty::node_id_to_type(ccx.tcx, id);
4324 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4325 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4326 check_const_with_ty(&fcx, sp, e, declty);
4329 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4333 // Gather locals in statics (because of block expressions).
4334 // This is technically unnecessary because locals in static items are forbidden,
4335 // but prevents type checking from blowing up before const checking can properly
4337 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4339 check_expr_with_hint(fcx, e, declty);
4340 demand::coerce(fcx, e.span, declty, e);
4341 vtable::select_all_fcx_obligations_or_error(fcx);
4342 regionck::regionck_expr(fcx, e);
4343 writeback::resolve_type_vars_in_expr(fcx, e);
4346 /// Checks whether a type can be represented in memory. In particular, it
4347 /// identifies types that contain themselves without indirection through a
4348 /// pointer, which would mean their size is unbounded. This is different from
4349 /// the question of whether a type can be instantiated. See the definition of
4350 /// `check_instantiable`.
4351 pub fn check_representable(tcx: &ty::ctxt,
4353 item_id: ast::NodeId,
4354 designation: &str) -> bool {
4355 let rty = ty::node_id_to_type(tcx, item_id);
4357 // Check that it is possible to represent this type. This call identifies
4358 // (1) types that contain themselves and (2) types that contain a different
4359 // recursive type. It is only necessary to throw an error on those that
4360 // contain themselves. For case 2, there must be an inner type that will be
4361 // caught by case 1.
4362 match ty::is_type_representable(tcx, sp, rty) {
4363 ty::SelfRecursive => {
4364 span_err!(tcx.sess, sp, E0072,
4365 "illegal recursive {} type; \
4366 wrap the inner value in a box to make it representable",
4370 ty::Representable | ty::ContainsRecursive => (),
4375 /// Checks whether a type can be created without an instance of itself.
4376 /// This is similar but different from the question of whether a type
4377 /// can be represented. For example, the following type:
4379 /// enum foo { None, Some(foo) }
4381 /// is instantiable but is not representable. Similarly, the type
4383 /// enum foo { Some(@foo) }
4385 /// is representable, but not instantiable.
4386 pub fn check_instantiable(tcx: &ty::ctxt,
4388 item_id: ast::NodeId)
4390 let item_ty = ty::node_id_to_type(tcx, item_id);
4391 if !ty::is_instantiable(tcx, item_ty) {
4392 span_err!(tcx.sess, sp, E0073,
4393 "this type cannot be instantiated without an \
4394 instance of itself");
4395 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4396 ppaux::ty_to_string(tcx, item_ty));
4403 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4404 let t = ty::node_id_to_type(tcx, id);
4405 if ty::type_needs_subst(t) {
4406 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4410 ty::ty_struct(did, substs) => {
4411 let fields = ty::lookup_struct_fields(tcx, did);
4412 if fields.is_empty() {
4413 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4416 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4417 if !fields.iter().all(
4418 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4419 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4422 if !ty::type_is_machine(e) {
4423 span_err!(tcx.sess, sp, E0077,
4424 "SIMD vector element type should be machine type");
4432 pub fn check_enum_variants(ccx: &CrateCtxt,
4434 vs: &[P<ast::Variant>],
4437 fn disr_in_range(ccx: &CrateCtxt,
4439 disr: ty::Disr) -> bool {
4440 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4442 ast::TyU8 => disr as u8 as Disr == disr,
4443 ast::TyU16 => disr as u16 as Disr == disr,
4444 ast::TyU32 => disr as u32 as Disr == disr,
4445 ast::TyU64 => disr as u64 as Disr == disr,
4446 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4449 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4451 ast::TyI8 => disr as i8 as Disr == disr,
4452 ast::TyI16 => disr as i16 as Disr == disr,
4453 ast::TyI32 => disr as i32 as Disr == disr,
4454 ast::TyI64 => disr as i64 as Disr == disr,
4455 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4459 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4460 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4464 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4465 vs: &[P<ast::Variant>],
4467 hint: attr::ReprAttr)
4468 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4470 let rty = ty::node_id_to_type(ccx.tcx, id);
4471 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4472 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4473 let mut prev_disr_val: Option<ty::Disr> = None;
4475 for v in vs.iter() {
4477 // If the discriminant value is specified explicitly in the enum check whether the
4478 // initialization expression is valid, otherwise use the last value plus one.
4479 let mut current_disr_val = match prev_disr_val {
4480 Some(prev_disr_val) => prev_disr_val + 1,
4481 None => ty::INITIAL_DISCRIMINANT_VALUE
4484 match v.node.disr_expr {
4486 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4488 let inh = static_inherited_fields(ccx);
4489 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4490 let declty = match hint {
4491 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4492 attr::ReprInt(_, attr::SignedInt(ity)) => {
4493 ty::mk_mach_int(fcx.tcx(), ity)
4495 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4496 ty::mk_mach_uint(fcx.tcx(), ity)
4499 check_const_with_ty(&fcx, e.span, &**e, declty);
4500 // check_expr (from check_const pass) doesn't guarantee
4501 // that the expression is in a form that eval_const_expr can
4502 // handle, so we may still get an internal compiler error
4504 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4505 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4506 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4508 span_err!(ccx.tcx.sess, e.span, E0079,
4509 "expected signed integer constant");
4512 span_err!(ccx.tcx.sess, e.span, E0080,
4513 "expected constant: {}", *err);
4520 // Check for duplicate discriminant values
4521 match disr_vals.iter().position(|&x| x == current_disr_val) {
4523 span_err!(ccx.tcx.sess, v.span, E0081,
4524 "discriminant value `{}` already exists", disr_vals[i]);
4525 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4526 "conflicting discriminant here")
4530 // Check for unrepresentable discriminant values
4532 attr::ReprAny | attr::ReprExtern => (),
4533 attr::ReprInt(sp, ity) => {
4534 if !disr_in_range(ccx, ity, current_disr_val) {
4535 span_err!(ccx.tcx.sess, v.span, E0082,
4536 "discriminant value outside specified type");
4537 span_note!(ccx.tcx.sess, sp,
4538 "discriminant type specified here");
4541 attr::ReprPacked => {
4542 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4545 disr_vals.push(current_disr_val);
4547 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4549 prev_disr_val = Some(current_disr_val);
4551 variants.push(variant_info);
4557 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4558 [].get(0).unwrap_or(&attr::ReprAny);
4560 if hint != attr::ReprAny && vs.len() <= 1 {
4562 span_err!(ccx.tcx.sess, sp, E0083,
4563 "unsupported representation for univariant enum");
4565 span_err!(ccx.tcx.sess, sp, E0084,
4566 "unsupported representation for zero-variant enum");
4570 let variants = do_check(ccx, vs, id, hint);
4572 // cache so that ty::enum_variants won't repeat this work
4573 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4575 check_representable(ccx.tcx, sp, id, "enum");
4577 // Check that it is possible to instantiate this enum:
4579 // This *sounds* like the same that as representable, but it's
4580 // not. See def'n of `check_instantiable()` for details.
4581 check_instantiable(ccx.tcx, sp, id);
4584 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4585 lookup_def_ccx(fcx.ccx, sp, id)
4588 // Returns the type parameter count and the type for the given definition.
4589 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4592 -> TypeScheme<'tcx> {
4594 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4595 let typ = fcx.local_ty(sp, nid);
4596 return no_params(typ);
4598 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4599 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4600 def::DefStruct(id) | def::DefConst(id) => {
4601 return ty::lookup_item_type(fcx.ccx.tcx, id);
4605 def::DefAssociatedTy(..) |
4606 def::DefAssociatedPath(..) |
4608 def::DefTyParam(..) => {
4609 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4611 def::DefMod(..) | def::DefForeignMod(..) => {
4612 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4614 def::DefUse(..) => {
4615 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4617 def::DefRegion(..) => {
4618 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4620 def::DefTyParamBinder(..) => {
4621 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4623 def::DefLabel(..) => {
4624 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4626 def::DefSelfTy(..) => {
4627 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4632 // Instantiates the given path, which must refer to an item with the given
4633 // number of type parameters and type.
4634 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4636 type_scheme: TypeScheme<'tcx>,
4637 opt_self_ty: Option<Ty<'tcx>>,
4640 node_id: ast::NodeId) {
4641 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4642 path.repr(fcx.tcx()),
4643 def.repr(fcx.tcx()),
4645 type_scheme.repr(fcx.tcx()));
4647 // We need to extract the type parameters supplied by the user in
4648 // the path `path`. Due to the current setup, this is a bit of a
4649 // tricky-process; the problem is that resolve only tells us the
4650 // end-point of the path resolution, and not the intermediate steps.
4651 // Luckily, we can (at least for now) deduce the intermediate steps
4652 // just from the end-point.
4654 // There are basically three cases to consider:
4656 // 1. Reference to a *type*, such as a struct or enum:
4658 // mod a { struct Foo<T> { ... } }
4660 // Because we don't allow types to be declared within one
4661 // another, a path that leads to a type will always look like
4662 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4663 // that only the final segment can have type parameters, and
4664 // they are located in the TypeSpace.
4666 // *Note:* Generally speaking, references to types don't
4667 // actually pass through this function, but rather the
4668 // `ast_ty_to_ty` function in `astconv`. However, in the case
4669 // of struct patterns (and maybe literals) we do invoke
4670 // `instantiate_path` to get the general type of an instance of
4671 // a struct. (In these cases, there are actually no type
4672 // parameters permitted at present, but perhaps we will allow
4673 // them in the future.)
4675 // 1b. Reference to a enum variant or tuple-like struct:
4677 // struct foo<T>(...)
4678 // enum E<T> { foo(...) }
4680 // In these cases, the parameters are declared in the type
4683 // 2. Reference to a *fn item*:
4687 // In this case, the path will again always have the form
4688 // `a::b::foo::<T>` where only the final segment should have
4689 // type parameters. However, in this case, those parameters are
4690 // declared on a value, and hence are in the `FnSpace`.
4692 // 3. Reference to a *method*:
4694 // impl<A> SomeStruct<A> {
4698 // Here we can have a path like
4699 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4700 // may appear in two places. The penultimate segment,
4701 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4702 // final segment, `foo::<B>` contains parameters in fn space.
4704 // The first step then is to categorize the segments appropriately.
4706 assert!(path.segments.len() >= 1);
4707 let mut segment_spaces: Vec<_>;
4709 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4710 def::DefSelfTy(..) |
4711 def::DefStruct(..) |
4712 def::DefVariant(..) |
4713 def::DefTyParamBinder(..) |
4715 def::DefAssociatedTy(..) |
4716 def::DefAssociatedPath(..) |
4718 def::DefPrimTy(..) |
4719 def::DefTyParam(..) => {
4720 // Everything but the final segment should have no
4721 // parameters at all.
4722 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4723 segment_spaces.push(Some(subst::TypeSpace));
4726 // Case 2. Reference to a top-level value.
4729 def::DefStatic(..) => {
4730 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4731 segment_spaces.push(Some(subst::FnSpace));
4734 // Case 3. Reference to a method.
4735 def::DefStaticMethod(_, providence) |
4736 def::DefMethod(_, _, providence) => {
4737 assert!(path.segments.len() >= 2);
4740 def::FromTrait(trait_did) => {
4741 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4743 def::FromImpl(_) => {}
4746 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4747 segment_spaces.push(Some(subst::TypeSpace));
4748 segment_spaces.push(Some(subst::FnSpace));
4751 // Other cases. Various nonsense that really shouldn't show up
4752 // here. If they do, an error will have been reported
4753 // elsewhere. (I hope)
4755 def::DefForeignMod(..) |
4758 def::DefRegion(..) |
4760 def::DefUpvar(..) => {
4761 segment_spaces = repeat(None).take(path.segments.len()).collect();
4764 assert_eq!(segment_spaces.len(), path.segments.len());
4766 debug!("segment_spaces={:?}", segment_spaces);
4768 // Next, examine the definition, and determine how many type
4769 // parameters we expect from each space.
4770 let type_defs = &type_scheme.generics.types;
4771 let region_defs = &type_scheme.generics.regions;
4773 // Now that we have categorized what space the parameters for each
4774 // segment belong to, let's sort out the parameters that the user
4775 // provided (if any) into their appropriate spaces. We'll also report
4776 // errors if type parameters are provided in an inappropriate place.
4777 let mut substs = Substs::empty();
4778 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4781 report_error_if_segment_contains_type_parameters(fcx, segment);
4785 push_explicit_parameters_from_segment_to_substs(fcx,
4795 if let Some(self_ty) = opt_self_ty {
4796 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4797 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4798 substs.types.push(subst::SelfSpace, self_ty);
4801 // Now we have to compare the types that the user *actually*
4802 // provided against the types that were *expected*. If the user
4803 // did not provide any types, then we want to substitute inference
4804 // variables. If the user provided some types, we may still need
4805 // to add defaults. If the user provided *too many* types, that's
4807 for &space in ParamSpace::all().iter() {
4808 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4809 assert_eq!(substs.types.len(space), type_defs.len(space));
4811 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4812 assert_eq!(substs.regions().len(space), region_defs.len(space));
4815 // The things we are substituting into the type should not contain
4816 // escaping late-bound regions, and nor should the base type scheme.
4817 assert!(!substs.has_regions_escaping_depth(0));
4818 assert!(!type_scheme.has_escaping_regions());
4820 // Add all the obligations that are required, substituting and
4821 // normalized appropriately.
4822 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4823 fcx.add_obligations_for_parameters(
4824 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4827 // Substitute the values for the type parameters into the type of
4828 // the referenced item.
4829 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4831 fcx.write_ty(node_id, ty_substituted);
4832 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4835 fn report_error_if_segment_contains_type_parameters(
4837 segment: &ast::PathSegment)
4839 for typ in segment.parameters.types().iter() {
4840 span_err!(fcx.tcx().sess, typ.span, E0085,
4841 "type parameters may not appear here");
4845 for lifetime in segment.parameters.lifetimes().iter() {
4846 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4847 "lifetime parameters may not appear here");
4852 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4853 /// parameters are provided, then reports an error and clears the output vector.
4855 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4856 /// use inference variables. This seems less likely to lead to derived errors.
4858 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4859 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4860 /// here because we can easily use the precise span of the N+1'th parameter.
4861 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4862 fcx: &FnCtxt<'a, 'tcx>,
4863 space: subst::ParamSpace,
4865 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4866 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4867 segment: &ast::PathSegment,
4868 substs: &mut Substs<'tcx>)
4870 match segment.parameters {
4871 ast::AngleBracketedParameters(ref data) => {
4872 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4873 fcx, space, type_defs, region_defs, data, substs);
4876 ast::ParenthesizedParameters(ref data) => {
4877 fcx.tcx().sess.span_err(
4879 "parenthesized parameters may only be used with a trait");
4880 push_explicit_parenthesized_parameters_from_segment_to_substs(
4881 fcx, space, span, type_defs, data, substs);
4886 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4887 fcx: &FnCtxt<'a, 'tcx>,
4888 space: subst::ParamSpace,
4889 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4890 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4891 data: &ast::AngleBracketedParameterData,
4892 substs: &mut Substs<'tcx>)
4895 let type_count = type_defs.len(space);
4896 assert_eq!(substs.types.len(space), 0);
4897 for (i, typ) in data.types.iter().enumerate() {
4898 let t = fcx.to_ty(&**typ);
4900 substs.types.push(space, t);
4901 } else if i == type_count {
4902 span_err!(fcx.tcx().sess, typ.span, E0087,
4903 "too many type parameters provided: \
4904 expected at most {} parameter(s), \
4905 found {} parameter(s)",
4906 type_count, data.types.len());
4907 substs.types.truncate(space, 0);
4913 if data.bindings.len() > 0 {
4914 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4915 "unexpected binding of associated item in expression path \
4916 (only allowed in type paths)");
4920 let region_count = region_defs.len(space);
4921 assert_eq!(substs.regions().len(space), 0);
4922 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4923 let r = ast_region_to_region(fcx.tcx(), lifetime);
4924 if i < region_count {
4925 substs.mut_regions().push(space, r);
4926 } else if i == region_count {
4927 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4928 "too many lifetime parameters provided: \
4929 expected {} parameter(s), found {} parameter(s)",
4931 data.lifetimes.len());
4932 substs.mut_regions().truncate(space, 0);
4940 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4941 /// but intended for `Foo(A,B) -> C` form. This expands to
4942 /// roughly the same thing as `Foo<(A,B),C>`. One important
4943 /// difference has to do with the treatment of anonymous
4944 /// regions, which are translated into bound regions (NYI).
4945 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4946 fcx: &FnCtxt<'a, 'tcx>,
4947 space: subst::ParamSpace,
4949 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4950 data: &ast::ParenthesizedParameterData,
4951 substs: &mut Substs<'tcx>)
4953 let type_count = type_defs.len(space);
4955 span_err!(fcx.tcx().sess, span, E0167,
4956 "parenthesized form always supplies 2 type parameters, \
4957 but only {} parameter(s) were expected",
4961 let input_tys: Vec<Ty> =
4962 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4965 ty::mk_tup(fcx.tcx(), input_tys);
4967 if type_count >= 1 {
4968 substs.types.push(space, tuple_ty);
4971 let output_ty: Option<Ty> =
4972 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4975 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4977 if type_count >= 2 {
4978 substs.types.push(space, output_ty);
4982 fn adjust_type_parameters<'a, 'tcx>(
4983 fcx: &FnCtxt<'a, 'tcx>,
4986 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4987 substs: &mut Substs<'tcx>)
4989 let provided_len = substs.types.len(space);
4990 let desired = defs.get_slice(space);
4991 let required_len = desired.iter()
4992 .take_while(|d| d.default.is_none())
4995 debug!("adjust_type_parameters(space={:?}, \
5004 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5005 assert!(provided_len <= desired.len());
5007 // Nothing specified at all: supply inference variables for
5009 if provided_len == 0 {
5010 substs.types.replace(space,
5011 fcx.infcx().next_ty_vars(desired.len()));
5015 // Too few parameters specified: report an error and use Err
5017 if provided_len < required_len {
5019 if desired.len() != required_len { "at least " } else { "" };
5020 span_err!(fcx.tcx().sess, span, E0089,
5021 "too few type parameters provided: expected {}{} parameter(s) \
5022 , found {} parameter(s)",
5023 qualifier, required_len, provided_len);
5024 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5028 // Otherwise, add in any optional parameters that the user
5029 // omitted. The case of *too many* parameters is handled
5031 // push_explicit_parameters_from_segment_to_substs(). Note
5032 // that the *default* type are expressed in terms of all prior
5033 // parameters, so we have to substitute as we go with the
5034 // partial substitution that we have built up.
5035 for i in range(provided_len, desired.len()) {
5036 let default = desired[i].default.unwrap();
5037 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5038 substs.types.push(space, default);
5040 assert_eq!(substs.types.len(space), desired.len());
5042 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5045 fn adjust_region_parameters(
5049 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5050 substs: &mut Substs)
5052 let provided_len = substs.mut_regions().len(space);
5053 let desired = defs.get_slice(space);
5055 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5056 assert!(provided_len <= desired.len());
5058 // If nothing was provided, just use inference variables.
5059 if provided_len == 0 {
5060 substs.mut_regions().replace(
5062 fcx.infcx().region_vars_for_defs(span, desired));
5066 // If just the right number were provided, everybody is happy.
5067 if provided_len == desired.len() {
5071 // Otherwise, too few were provided. Report an error and then
5072 // use inference variables.
5073 span_err!(fcx.tcx().sess, span, E0090,
5074 "too few lifetime parameters provided: expected {} parameter(s), \
5075 found {} parameter(s)",
5076 desired.len(), provided_len);
5078 substs.mut_regions().replace(
5080 fcx.infcx().region_vars_for_defs(span, desired));
5084 // Resolves `typ` by a single level if `typ` is a type variable. If no
5085 // resolution is possible, then an error is reported.
5086 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5087 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5088 // If `ty` is a type variable, see whether we already know what it is.
5089 ty = fcx.infcx().shallow_resolve(ty);
5091 // If not, try resolve pending fcx obligations. Those can shed light.
5093 // FIXME(#18391) -- This current strategy can lead to bad performance in
5094 // extreme cases. We probably ought to smarter in general about
5095 // only resolving when we need help and only resolving obligations
5096 // will actually help.
5097 if ty::type_is_ty_var(ty) {
5098 vtable::select_fcx_obligations_where_possible(fcx);
5099 ty = fcx.infcx().shallow_resolve(ty);
5103 if ty::type_is_ty_var(ty) {
5104 fcx.type_error_message(sp, |_actual| {
5105 "the type of this value must be known in this \
5106 context".to_string()
5108 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5109 ty = fcx.tcx().types.err;
5115 // Returns true if b contains a break that can exit from b
5116 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5117 // First: is there an unlabeled break immediately
5119 (loop_query(&*b, |e| {
5121 ast::ExprBreak(_) => true,
5125 // Second: is there a labeled break with label
5126 // <id> nested anywhere inside the loop?
5127 (block_query(b, |e| {
5129 ast::ExprBreak(Some(_)) => {
5130 match cx.def_map.borrow().get(&e.id) {
5131 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5139 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5141 tps: &OwnedSlice<ast::TyParam>,
5143 debug!("check_bounds_are_used(n_tps={}, ty={})",
5144 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5146 // make a vector of booleans initially false, set to true when used
5147 if tps.len() == 0u { return; }
5148 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5150 ty::walk_ty(ty, |t| {
5152 ty::ty_param(ParamTy {idx, ..}) => {
5153 debug!("Found use of ty param num {}", idx);
5154 tps_used[idx as uint] = true;
5160 for (i, b) in tps_used.iter().enumerate() {
5162 span_err!(ccx.tcx.sess, span, E0091,
5163 "type parameter `{}` is unused",
5164 token::get_ident(tps[i].ident));
5169 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5170 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5171 let name = token::intern(format!("P{}", n).as_slice());
5172 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5176 let name = token::get_ident(it.ident);
5177 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5178 let split : Vec<&str> = name.get().split('_').collect();
5179 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5181 //We only care about the operation here
5182 let (n_tps, inputs, output) = match split[1] {
5183 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5187 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5189 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5192 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5193 "min" | "umax" | "umin" => {
5194 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5198 (0, Vec::new(), ty::mk_nil(tcx))
5201 span_err!(tcx.sess, it.span, E0092,
5202 "unrecognized atomic operation function: `{}`", op);
5206 (n_tps, inputs, ty::FnConverging(output))
5207 } else if name.get() == "abort" || name.get() == "unreachable" {
5208 (0, Vec::new(), ty::FnDiverging)
5210 let (n_tps, inputs, output) = match name.get() {
5211 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5213 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5214 "init" => (1u, Vec::new(), param(ccx, 0)),
5215 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5216 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5217 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5218 "move_val_init" => {
5221 ty::mk_mut_rptr(tcx,
5222 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5229 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5230 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5233 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5235 Err(s) => { tcx.sess.span_fatal(it.span, &s[]); }
5237 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5239 mutbl: ast::MutImmutable
5241 (1u, Vec::new(), td_ptr)
5244 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5248 ty::mk_struct(ccx.tcx, did,
5249 ccx.tcx.mk_substs(subst::Substs::empty()))),
5251 tcx.sess.span_fatal(it.span, &msg[]);
5258 ty::mk_ptr(tcx, ty::mt {
5260 mutbl: ast::MutImmutable
5264 ty::mk_ptr(tcx, ty::mt {
5266 mutbl: ast::MutImmutable
5269 "copy_memory" | "copy_nonoverlapping_memory" |
5270 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5273 ty::mk_ptr(tcx, ty::mt {
5275 mutbl: ast::MutMutable
5277 ty::mk_ptr(tcx, ty::mt {
5279 mutbl: ast::MutImmutable
5285 "set_memory" | "volatile_set_memory" => {
5288 ty::mk_ptr(tcx, ty::mt {
5290 mutbl: ast::MutMutable
5297 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5298 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5301 vec!( tcx.types.f32, tcx.types.i32 ),
5306 vec!( tcx.types.f64, tcx.types.i32 ),
5309 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5310 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5311 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5312 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5315 vec!( tcx.types.f32, tcx.types.f32 ),
5320 vec!( tcx.types.f64, tcx.types.f64 ),
5323 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5324 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5325 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5326 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5327 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5328 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5329 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5330 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5331 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5332 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5335 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5340 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5343 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5344 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5345 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5346 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5347 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5348 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5349 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5350 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5351 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5352 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5353 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5354 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5355 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5356 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5357 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5358 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5359 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5360 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5361 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5362 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5363 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5364 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5365 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5366 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5367 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5368 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5369 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5370 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5371 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5372 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5373 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5376 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5378 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5380 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5381 (0, vec!(tcx.types.i8, tcx.types.i8),
5382 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5384 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5385 (0, vec!(tcx.types.i16, tcx.types.i16),
5386 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5388 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5389 (0, vec!(tcx.types.i32, tcx.types.i32),
5390 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5392 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5393 (0, vec!(tcx.types.i64, tcx.types.i64),
5394 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5396 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5397 (0, vec!(tcx.types.u8, tcx.types.u8),
5398 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5400 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5401 (0, vec!(tcx.types.u16, tcx.types.u16),
5402 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5404 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5405 (0, vec!(tcx.types.u32, tcx.types.u32),
5406 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5408 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5409 (0, vec!(tcx.types.u64, tcx.types.u64),
5410 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5412 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5414 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5417 span_err!(tcx.sess, it.span, E0093,
5418 "unrecognized intrinsic function: `{}`", *other);
5422 (n_tps, inputs, ty::FnConverging(output))
5424 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5425 unsafety: ast::Unsafety::Unsafe,
5426 abi: abi::RustIntrinsic,
5427 sig: ty::Binder(FnSig {
5433 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5434 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5435 if i_n_tps != n_tps {
5436 span_err!(tcx.sess, it.span, E0094,
5437 "intrinsic has wrong number of type \
5438 parameters: found {}, expected {}",
5441 require_same_types(tcx,
5448 format!("intrinsic has wrong type: expected `{}`",
5449 ppaux::ty_to_string(ccx.tcx, fty))