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()),
377 param_env: param_env,
378 node_types: RefCell::new(NodeMap()),
379 item_substs: RefCell::new(NodeMap()),
380 adjustments: RefCell::new(NodeMap()),
381 method_map: RefCell::new(FnvHashMap()),
382 object_cast_map: RefCell::new(NodeMap()),
383 upvar_borrow_map: RefCell::new(FnvHashMap()),
384 unboxed_closures: RefCell::new(DefIdMap()),
385 fn_sig_map: RefCell::new(NodeMap()),
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()));
1600 self.inh.fulfillment_cx
1602 .register_predicate_obligation(self.infcx(), obligation);
1605 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1606 let t = ast_ty_to_ty(self, self, ast_t);
1608 let mut bounds_checker = wf::BoundsChecker::new(self,
1610 CodeExtent::from_node_id(self.body_id),
1612 bounds_checker.check_ty(t);
1617 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1618 pat.repr(self.tcx())
1621 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1622 match self.inh.node_types.borrow().get(&ex.id) {
1625 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1631 /// Apply `adjustment` to the type of `expr`
1632 pub fn adjust_expr_ty(&self,
1634 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1637 let raw_ty = self.expr_ty(expr);
1638 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1639 ty::adjust_ty(self.tcx(),
1644 |method_call| self.inh.method_map.borrow()
1646 .map(|method| method.ty))
1649 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1650 match self.inh.node_types.borrow().get(&id) {
1652 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1654 self.tcx().sess.bug(
1655 &format!("no type for node {}: {} in fcx {}",
1656 id, self.tcx().map.node_to_string(id),
1662 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1663 self.inh.item_substs.borrow()
1666 pub fn opt_node_ty_substs<F>(&self,
1669 F: FnOnce(&ty::ItemSubsts<'tcx>),
1671 match self.inh.item_substs.borrow().get(&id) {
1677 pub fn mk_subty(&self,
1678 a_is_expected: bool,
1679 origin: infer::TypeOrigin,
1682 -> Result<(), ty::type_err<'tcx>> {
1683 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1686 pub fn mk_assignty(&self,
1690 -> Result<(), ty::type_err<'tcx>> {
1691 match infer::mk_coercety(self.infcx(),
1693 infer::ExprAssignable(expr.span),
1697 Err(ref e) => Err((*e)),
1698 Ok(Some(adjustment)) => {
1699 self.write_adjustment(expr.id, expr.span, adjustment);
1705 pub fn mk_eqty(&self,
1706 a_is_expected: bool,
1707 origin: infer::TypeOrigin,
1710 -> Result<(), ty::type_err<'tcx>> {
1711 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1714 pub fn mk_subr(&self,
1715 origin: infer::SubregionOrigin<'tcx>,
1718 infer::mk_subr(self.infcx(), origin, sub, sup)
1721 pub fn type_error_message<M>(&self,
1724 actual_ty: Ty<'tcx>,
1725 err: Option<&ty::type_err<'tcx>>) where
1726 M: FnOnce(String) -> String,
1728 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1731 pub fn report_mismatched_types(&self,
1735 err: &ty::type_err<'tcx>) {
1736 self.infcx().report_mismatched_types(sp, e, a, err)
1739 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1740 /// outlive the region `r`.
1741 pub fn register_region_obligation(&self,
1744 cause: traits::ObligationCause<'tcx>)
1746 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1747 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1750 pub fn add_default_region_param_bounds(&self,
1751 substs: &Substs<'tcx>,
1754 for &ty in substs.types.iter() {
1755 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1756 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1757 traits::MiscObligation);
1758 self.register_region_obligation(ty, default_bound, cause);
1762 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1763 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1764 /// trait/region obligations.
1766 /// For example, if there is a function:
1769 /// fn foo<'a,T:'a>(...)
1772 /// and a reference:
1778 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1779 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1780 pub fn add_obligations_for_parameters(&self,
1781 cause: traits::ObligationCause<'tcx>,
1782 generic_bounds: &ty::GenericBounds<'tcx>)
1784 assert!(!generic_bounds.has_escaping_regions());
1786 debug!("add_obligations_for_parameters(generic_bounds={})",
1787 generic_bounds.repr(self.tcx()));
1789 let obligations = traits::predicates_for_generics(self.tcx(),
1793 obligations.map_move(|o| self.register_predicate(o));
1796 // Only for fields! Returns <none> for methods>
1797 // Indifferent to privacy flags
1798 pub fn lookup_field_ty(&self,
1800 class_id: ast::DefId,
1801 items: &[ty::field_ty],
1802 fieldname: ast::Name,
1803 substs: &subst::Substs<'tcx>)
1806 let o_field = items.iter().find(|f| f.name == fieldname);
1807 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1808 .map(|t| self.normalize_associated_types_in(span, &t))
1811 pub fn lookup_tup_field_ty(&self,
1813 class_id: ast::DefId,
1814 items: &[ty::field_ty],
1816 substs: &subst::Substs<'tcx>)
1819 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1820 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1821 .map(|t| self.normalize_associated_types_in(span, &t))
1825 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1826 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1827 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1830 fn anon_regions(&self, span: Span, count: uint)
1831 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1832 Ok(range(0, count).map(|_| {
1833 self.infcx().next_region_var(infer::MiscVariable(span))
1838 #[derive(Copy, Show, PartialEq, Eq)]
1839 pub enum LvaluePreference {
1844 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1845 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1847 /// Note: this method does not modify the adjustments table. The caller is responsible for
1848 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1849 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1852 opt_expr: Option<&ast::Expr>,
1853 mut lvalue_pref: LvaluePreference,
1855 -> (Ty<'tcx>, uint, Option<T>)
1856 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1858 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1859 base_ty.repr(fcx.tcx()),
1860 opt_expr.repr(fcx.tcx()),
1863 let mut t = base_ty;
1864 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1865 let resolved_t = structurally_resolved_type(fcx, sp, t);
1867 if ty::type_is_error(resolved_t) {
1868 return (resolved_t, autoderefs, None);
1871 match should_stop(resolved_t, autoderefs) {
1872 Some(x) => return (resolved_t, autoderefs, Some(x)),
1876 // Otherwise, deref if type is derefable:
1877 let mt = match ty::deref(resolved_t, false) {
1878 Some(mt) => Some(mt),
1880 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1882 // Super subtle: it might seem as though we should
1883 // pass `opt_expr` to `try_overloaded_deref`, so that
1884 // the (implicit) autoref of using an overloaded deref
1885 // would get added to the adjustment table. However we
1886 // do not do that, because it's kind of a
1887 // "meta-adjustment" -- instead, we just leave it
1888 // unrecorded and know that there "will be" an
1889 // autoref. regionck and other bits of the code base,
1890 // when they encounter an overloaded autoderef, have
1891 // to do some reconstructive surgery. This is a pretty
1892 // complex mess that is begging for a proper MIR.
1893 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1899 if mt.mutbl == ast::MutImmutable {
1900 lvalue_pref = NoPreference;
1903 None => return (resolved_t, autoderefs, None)
1907 // We've reached the recursion limit, error gracefully.
1908 span_err!(fcx.tcx().sess, sp, E0055,
1909 "reached the recursion limit while auto-dereferencing {}",
1910 base_ty.repr(fcx.tcx()));
1911 (fcx.tcx().types.err, 0, None)
1914 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1916 method_call: Option<MethodCall>,
1917 base_expr: Option<&ast::Expr>,
1919 lvalue_pref: LvaluePreference)
1920 -> Option<ty::mt<'tcx>>
1922 // Try DerefMut first, if preferred.
1923 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1924 (PreferMutLvalue, Some(trait_did)) => {
1925 method::lookup_in_trait(fcx, span, base_expr,
1926 token::intern("deref_mut"), trait_did,
1932 // Otherwise, fall back to Deref.
1933 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1934 (None, Some(trait_did)) => {
1935 method::lookup_in_trait(fcx, span, base_expr,
1936 token::intern("deref"), trait_did,
1939 (method, _) => method
1942 make_overloaded_lvalue_return_type(fcx, method_call, method)
1945 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
1946 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
1947 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
1948 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1949 method_call: Option<MethodCall>,
1950 method: Option<MethodCallee<'tcx>>)
1951 -> Option<ty::mt<'tcx>>
1955 let ref_ty = // invoked methods have all LB regions instantiated
1956 ty::assert_no_late_bound_regions(
1957 fcx.tcx(), &ty::ty_fn_ret(method.ty));
1959 Some(method_call) => {
1960 fcx.inh.method_map.borrow_mut().insert(method_call,
1966 ty::FnConverging(ref_ty) => {
1967 ty::deref(ref_ty, true)
1969 ty::FnDiverging => {
1970 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
1978 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1979 base_expr: &ast::Expr,
1981 lvalue_pref: LvaluePreference,
1984 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
1986 // FIXME(#18741) -- this is almost but not quite the same as the
1987 // autoderef that normal method probing does. They could likely be
1990 let (ty, autoderefs, final_mt) =
1991 autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
1992 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
1993 step(adj_ty, autoderefref)
1996 if final_mt.is_some() {
2000 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2001 // do a final unsized coercion to yield [T].
2003 ty::ty_vec(element_ty, Some(n)) => {
2004 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2005 let autoderefref = ty::AutoDerefRef {
2006 autoderefs: autoderefs,
2007 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2009 step(adjusted_ty, autoderefref)
2017 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2018 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2019 /// This loop implements one step in that search; the autoderef loop is implemented by
2020 /// `autoderef_for_index`.
2021 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2022 method_call: MethodCall,
2024 base_expr: &ast::Expr,
2025 adjusted_ty: Ty<'tcx>,
2026 adjustment: ty::AutoDerefRef<'tcx>,
2027 lvalue_pref: LvaluePreference,
2029 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2031 let tcx = fcx.tcx();
2032 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2034 base_expr.repr(tcx),
2035 adjusted_ty.repr(tcx),
2037 index_ty.repr(tcx));
2039 let input_ty = fcx.infcx().next_ty_var();
2041 // First, try built-in indexing.
2042 match (ty::index(adjusted_ty), &index_ty.sty) {
2043 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2044 debug!("try_index_step: success, using built-in indexing");
2045 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2046 return Some((tcx.types.uint, ty));
2051 // Try `IndexMut` first, if preferred.
2052 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2053 (PreferMutLvalue, Some(trait_did)) => {
2054 method::lookup_in_trait_adjusted(fcx,
2057 token::intern("index_mut"),
2061 Some(vec![input_ty]))
2066 // Otherwise, fall back to `Index`.
2067 let method = match (method, tcx.lang_items.index_trait()) {
2068 (None, Some(trait_did)) => {
2069 method::lookup_in_trait_adjusted(fcx,
2072 token::intern("index"),
2076 Some(vec![input_ty]))
2078 (method, _) => method,
2081 // If some lookup succeeds, write callee into table and extract index/element
2082 // type from the method signature.
2083 // If some lookup succeeded, install method in table
2084 method.and_then(|method| {
2085 debug!("try_index_step: success, using overloaded indexing");
2086 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2087 map(|ret| (input_ty, ret.ty))
2091 /// Given the head of a `for` expression, looks up the `next` method in the
2092 /// `Iterator` trait. Panics if the expression does not implement `next`.
2094 /// The return type of this function represents the concrete element type
2095 /// `A` in the type `Iterator<A>` that the method returns.
2096 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2097 iterator_expr: &ast::Expr,
2098 loop_id: ast::NodeId)
2100 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2101 Ok(trait_did) => trait_did,
2102 Err(ref err_string) => {
2103 fcx.tcx().sess.span_err(iterator_expr.span,
2105 return fcx.tcx().types.err
2109 let expr_type = fcx.expr_ty(&*iterator_expr);
2110 let method = method::lookup_in_trait(fcx,
2112 Some(&*iterator_expr),
2113 token::intern("next"),
2118 // Regardless of whether the lookup succeeds, check the method arguments
2119 // so that we have *some* type for each argument.
2120 let method_type = match method {
2121 Some(ref method) => method.ty,
2123 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2125 if !ty::type_is_error(true_expr_type) {
2126 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2127 fcx.tcx().sess.span_err(iterator_expr.span,
2128 &format!("`for` loop expression has type `{}` which does \
2129 not implement the `Iterator` trait; \
2136 let return_type = check_method_argument_types(fcx,
2147 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2150 // We expect the return type to be `Option` or something like it.
2151 // Grab the first parameter of its type substitution.
2152 let return_type = match return_type {
2153 ty::FnConverging(return_type) =>
2154 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2155 ty::FnDiverging => fcx.tcx().types.err
2157 match return_type.sty {
2158 ty::ty_enum(_, ref substs)
2159 if !substs.types.is_empty_in(subst::TypeSpace) => {
2160 *substs.types.get(subst::TypeSpace, 0)
2166 fcx.tcx().sess.span_err(iterator_expr.span,
2167 &format!("`next` method of the `Iterator` \
2168 trait has an unexpected type `{}`",
2169 fcx.infcx().ty_to_string(return_type))
2175 None => fcx.tcx().types.err
2179 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2181 method_fn_ty: Ty<'tcx>,
2182 callee_expr: &ast::Expr,
2183 args_no_rcvr: &[P<ast::Expr>],
2184 autoref_args: AutorefArgs,
2185 tuple_arguments: TupleArgumentsFlag,
2186 expected: Expectation<'tcx>)
2187 -> ty::FnOutput<'tcx> {
2188 if ty::type_is_error(method_fn_ty) {
2189 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2191 let err_inputs = match tuple_arguments {
2192 DontTupleArguments => err_inputs,
2193 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2196 check_argument_types(fcx,
2204 ty::FnConverging(fcx.tcx().types.err)
2206 match method_fn_ty.sty {
2207 ty::ty_bare_fn(_, ref fty) => {
2208 // HACK(eddyb) ignore self in the definition (see above).
2209 let expected_arg_tys = expected_types_for_fn_args(fcx,
2213 &fty.sig.0.inputs[1..]);
2214 check_argument_types(fcx,
2216 &fty.sig.0.inputs[1..],
2217 &expected_arg_tys[],
2225 fcx.tcx().sess.span_bug(callee_expr.span,
2226 "method without bare fn type");
2232 /// Generic function that factors out common logic from function calls, method calls and overloaded
2234 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2236 fn_inputs: &[Ty<'tcx>],
2237 expected_arg_tys: &[Ty<'tcx>],
2238 args: &[P<ast::Expr>],
2239 autoref_args: AutorefArgs,
2241 tuple_arguments: TupleArgumentsFlag) {
2242 let tcx = fcx.ccx.tcx;
2244 // Grab the argument types, supplying fresh type variables
2245 // if the wrong number of arguments were supplied
2246 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2252 let mut expected_arg_tys = expected_arg_tys;
2253 let expected_arg_count = fn_inputs.len();
2254 let formal_tys = if tuple_arguments == TupleArguments {
2255 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2256 match tuple_type.sty {
2257 ty::ty_tup(ref arg_types) => {
2258 if arg_types.len() != args.len() {
2259 span_err!(tcx.sess, sp, E0057,
2260 "this function takes {} parameter{} but {} parameter{} supplied",
2262 if arg_types.len() == 1 {""} else {"s"},
2264 if args.len() == 1 {" was"} else {"s were"});
2265 expected_arg_tys = &[][];
2266 err_args(fcx.tcx(), args.len())
2268 expected_arg_tys = match expected_arg_tys.get(0) {
2269 Some(&ty) => match ty.sty {
2270 ty::ty_tup(ref tys) => &**tys,
2275 (*arg_types).clone()
2279 span_err!(tcx.sess, sp, E0059,
2280 "cannot use call notation; the first type parameter \
2281 for the function trait is neither a tuple nor unit");
2282 expected_arg_tys = &[][];
2283 err_args(fcx.tcx(), args.len())
2286 } else if expected_arg_count == supplied_arg_count {
2288 } else if variadic {
2289 if supplied_arg_count >= expected_arg_count {
2292 span_err!(tcx.sess, sp, E0060,
2293 "this function takes at least {} parameter{} \
2294 but {} parameter{} supplied",
2296 if expected_arg_count == 1 {""} else {"s"},
2298 if supplied_arg_count == 1 {" was"} else {"s were"});
2299 expected_arg_tys = &[][];
2300 err_args(fcx.tcx(), supplied_arg_count)
2303 span_err!(tcx.sess, sp, E0061,
2304 "this function takes {} parameter{} but {} parameter{} supplied",
2306 if expected_arg_count == 1 {""} else {"s"},
2308 if supplied_arg_count == 1 {" was"} else {"s were"});
2309 expected_arg_tys = &[][];
2310 err_args(fcx.tcx(), supplied_arg_count)
2313 debug!("check_argument_types: formal_tys={:?}",
2314 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2316 // Check the arguments.
2317 // We do this in a pretty awful way: first we typecheck any arguments
2318 // that are not anonymous functions, then we typecheck the anonymous
2319 // functions. This is so that we have more information about the types
2320 // of arguments when we typecheck the functions. This isn't really the
2321 // right way to do this.
2322 let xs = [false, true];
2323 for check_blocks in xs.iter() {
2324 let check_blocks = *check_blocks;
2325 debug!("check_blocks={}", check_blocks);
2327 // More awful hacks: before we check the blocks, try to do
2328 // an "opportunistic" vtable resolution of any trait
2329 // bounds on the call.
2331 vtable::select_new_fcx_obligations(fcx);
2334 // For variadic functions, we don't have a declared type for all of
2335 // the arguments hence we only do our usual type checking with
2336 // the arguments who's types we do know.
2337 let t = if variadic {
2339 } else if tuple_arguments == TupleArguments {
2344 for (i, arg) in args.iter().take(t).enumerate() {
2345 let is_block = match arg.node {
2346 ast::ExprClosure(..) => true,
2350 if is_block == check_blocks {
2351 debug!("checking the argument");
2352 let mut formal_ty = formal_tys[i];
2354 match autoref_args {
2355 AutorefArgs::Yes => {
2356 match formal_ty.sty {
2357 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2360 // So we hit this case when one implements the
2361 // operator traits but leaves an argument as
2362 // just T instead of &T. We'll catch it in the
2363 // mismatch impl/trait method phase no need to
2366 formal_ty = tcx.types.err;
2370 AutorefArgs::No => {}
2373 // The special-cased logic below has three functions:
2374 // 1. Provide as good of an expected type as possible.
2375 let expected = expected_arg_tys.get(i).map(|&ty| {
2376 Expectation::rvalue_hint(ty)
2379 check_expr_with_unifier(fcx, &**arg,
2380 expected.unwrap_or(ExpectHasType(formal_ty)),
2382 // 2. Coerce to the most detailed type that could be coerced
2383 // to, which is `expected_ty` if `rvalue_hint` returns an
2384 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2385 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2386 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2388 // 3. Relate the expected type and the formal one,
2389 // if the expected type was used for the coercion.
2390 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2396 // We also need to make sure we at least write the ty of the other
2397 // arguments which we skipped above.
2399 for arg in args.iter().skip(expected_arg_count) {
2400 check_expr(fcx, &**arg);
2402 // There are a few types which get autopromoted when passed via varargs
2403 // in C but we just error out instead and require explicit casts.
2404 let arg_ty = structurally_resolved_type(fcx, arg.span,
2405 fcx.expr_ty(&**arg));
2407 ty::ty_float(ast::TyF32) => {
2408 fcx.type_error_message(arg.span,
2410 format!("can't pass an {} to variadic \
2411 function, cast to c_double", t)
2414 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2415 fcx.type_error_message(arg.span, |t| {
2416 format!("can't pass {} to variadic \
2417 function, cast to c_int",
2421 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2422 fcx.type_error_message(arg.span, |t| {
2423 format!("can't pass {} to variadic \
2424 function, cast to c_uint",
2434 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2435 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2436 range(0, len).map(|_| tcx.types.err).collect()
2439 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2440 call_expr: &ast::Expr,
2441 output: ty::FnOutput<'tcx>) {
2442 fcx.write_ty(call_expr.id, match output {
2443 ty::FnConverging(output_ty) => output_ty,
2444 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2448 // AST fragment checking
2449 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2451 expected: Expectation<'tcx>)
2454 let tcx = fcx.ccx.tcx;
2457 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2458 ast::LitBinary(..) => {
2460 tcx.mk_region(ty::ReStatic),
2461 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2463 ast::LitByte(_) => tcx.types.u8,
2464 ast::LitChar(_) => tcx.types.char,
2465 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2466 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2467 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2468 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2470 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2471 ty::ty_char => Some(tcx.types.u8),
2472 ty::ty_ptr(..) => Some(tcx.types.uint),
2473 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2477 opt_ty.unwrap_or_else(
2478 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2480 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2481 ast::LitFloatUnsuffixed(_) => {
2482 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2484 ty::ty_float(_) => Some(ty),
2488 opt_ty.unwrap_or_else(
2489 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2491 ast::LitBool(_) => tcx.types.bool
2495 pub fn valid_range_bounds(ccx: &CrateCtxt,
2499 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2500 Some(val) => Some(val <= 0),
2505 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2507 expected: Ty<'tcx>) {
2508 check_expr_with_unifier(
2509 fcx, expr, ExpectHasType(expected), NoPreference,
2510 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2513 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2515 expected: Ty<'tcx>) {
2516 check_expr_with_unifier(
2517 fcx, expr, ExpectHasType(expected), NoPreference,
2518 || demand::coerce(fcx, expr.span, expected, expr));
2521 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2522 expected: Ty<'tcx>) {
2523 check_expr_with_unifier(
2524 fcx, expr, ExpectHasType(expected), NoPreference,
2528 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2530 expected: Expectation<'tcx>) {
2531 check_expr_with_unifier(
2532 fcx, expr, expected, NoPreference,
2536 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2538 expected: Expectation<'tcx>,
2539 lvalue_pref: LvaluePreference)
2541 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2544 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2545 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2548 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2549 lvalue_pref: LvaluePreference) {
2550 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2553 // determine the `self` type, using fresh variables for all variables
2554 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2555 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2557 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2558 span: Span, // (potential) receiver for this impl
2560 -> TypeAndSubsts<'tcx> {
2561 let tcx = fcx.tcx();
2563 let ity = ty::lookup_item_type(tcx, did);
2564 let (n_tps, rps, raw_ty) =
2565 (ity.generics.types.len(subst::TypeSpace),
2566 ity.generics.regions.get_slice(subst::TypeSpace),
2569 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2570 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2571 let substs = subst::Substs::new_type(tps, rps);
2572 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2574 TypeAndSubsts { substs: substs, ty: substd_ty }
2577 // Controls whether the arguments are automatically referenced. This is useful
2578 // for overloaded binary and unary operators.
2579 #[derive(Copy, PartialEq)]
2580 pub enum AutorefArgs {
2585 /// Controls whether the arguments are tupled. This is used for the call
2588 /// Tupling means that all call-side arguments are packed into a tuple and
2589 /// passed as a single parameter. For example, if tupling is enabled, this
2592 /// fn f(x: (int, int))
2594 /// Can be called as:
2601 #[derive(Clone, Eq, PartialEq)]
2602 enum TupleArgumentsFlag {
2607 /// Unifies the return type with the expected type early, for more coercions
2608 /// and forward type information on the argument expressions.
2609 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2611 expected_ret: Expectation<'tcx>,
2612 formal_ret: ty::FnOutput<'tcx>,
2613 formal_args: &[Ty<'tcx>])
2615 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2616 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2617 fcx.infcx().commit_regions_if_ok(|| {
2618 // Attempt to apply a subtyping relationship between the formal
2619 // return type (likely containing type variables if the function
2620 // is polymorphic) and the expected return type.
2621 // No argument expectations are produced if unification fails.
2622 let origin = infer::Misc(call_span);
2623 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2624 // FIXME(#15760) can't use try! here, FromError doesn't default
2625 // to identity so the resulting type is not constrained.
2626 if let Err(e) = ures {
2630 // Record all the argument types, with the substitutions
2631 // produced from the above subtyping unification.
2632 Ok(formal_args.iter().map(|ty| {
2633 fcx.infcx().resolve_type_vars_if_possible(ty)
2639 }).unwrap_or(vec![]);
2640 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2641 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2642 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2647 /// If an expression has any sub-expressions that result in a type error,
2648 /// inspecting that expression's type with `ty::type_is_error` will return
2649 /// true. Likewise, if an expression is known to diverge, inspecting its
2650 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2651 /// strict, _|_ can appear in the type of an expression that does not,
2652 /// itself, diverge: for example, fn() -> _|_.)
2653 /// Note that inspecting a type's structure *directly* may expose the fact
2654 /// that there are actually multiple representations for `ty_err`, so avoid
2655 /// that when err needs to be handled differently.
2656 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2658 expected: Expectation<'tcx>,
2659 lvalue_pref: LvaluePreference,
2663 debug!(">> typechecking: expr={} expected={}",
2664 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2666 // Checks a method call.
2667 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2669 method_name: ast::SpannedIdent,
2670 args: &[P<ast::Expr>],
2672 expected: Expectation<'tcx>,
2673 lvalue_pref: LvaluePreference) {
2674 let rcvr = &*args[0];
2675 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2677 // no need to check for bot/err -- callee does that
2678 let expr_t = structurally_resolved_type(fcx,
2680 fcx.expr_ty(&*rcvr));
2682 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2683 let fn_ty = match method::lookup(fcx,
2685 method_name.node.name,
2691 let method_ty = method.ty;
2692 let method_call = MethodCall::expr(expr.id);
2693 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2697 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
2698 fcx.write_error(expr.id);
2703 // Call the generic checker.
2704 let ret_ty = check_method_argument_types(fcx,
2713 write_call(fcx, expr, ret_ty);
2716 // A generic function for checking the then and else in an if
2718 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2719 cond_expr: &ast::Expr,
2720 then_blk: &ast::Block,
2721 opt_else_expr: Option<&ast::Expr>,
2724 expected: Expectation<'tcx>) {
2725 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2727 let expected = expected.adjust_for_branches(fcx);
2728 check_block_with_expected(fcx, then_blk, expected);
2729 let then_ty = fcx.node_ty(then_blk.id);
2731 let branches_ty = match opt_else_expr {
2732 Some(ref else_expr) => {
2733 check_expr_with_expectation(fcx, &**else_expr, expected);
2734 let else_ty = fcx.expr_ty(&**else_expr);
2735 infer::common_supertype(fcx.infcx(),
2736 infer::IfExpression(sp),
2742 infer::common_supertype(fcx.infcx(),
2743 infer::IfExpressionWithNoElse(sp),
2746 ty::mk_nil(fcx.tcx()))
2750 let cond_ty = fcx.expr_ty(cond_expr);
2751 let if_ty = if ty::type_is_error(cond_ty) {
2757 fcx.write_ty(id, if_ty);
2760 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2764 trait_did: Option<ast::DefId>,
2766 rhs: Option<&P<ast::Expr>>,
2768 autoref_args: AutorefArgs) -> Ty<'tcx> where
2771 let method = match trait_did {
2772 Some(trait_did) => {
2773 // We do eager coercions to make using operators
2776 // - If the input is of type &'a T (resp. &'a mut T),
2777 // then reborrow it to &'b T (resp. &'b mut T) where
2778 // 'b <= 'a. This makes things like `x == y`, where
2779 // `x` and `y` are both region pointers, work. We
2780 // could also solve this with variance or different
2781 // traits that don't force left and right to have same
2783 let (adj_ty, adjustment) = match lhs_ty.sty {
2784 ty::ty_rptr(r_in, mt) => {
2785 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2786 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2787 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2788 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2789 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2790 (adjusted_ty, adjustment)
2793 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2797 debug!("adjusted_ty={} adjustment={:?}",
2798 adj_ty.repr(fcx.tcx()),
2801 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2802 trait_did, adjustment, adj_ty, None)
2806 let args = match rhs {
2807 Some(rhs) => slice::ref_slice(rhs),
2812 let method_ty = method.ty;
2813 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2814 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2815 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2816 match check_method_argument_types(fcx,
2824 ty::FnConverging(result_type) => result_type,
2825 ty::FnDiverging => fcx.tcx().types.err
2830 // Check the args anyway
2831 // so we get all the error messages
2832 let expected_ty = fcx.tcx().types.err;
2833 check_method_argument_types(fcx,
2846 // could be either an expr_binop or an expr_assign_binop
2847 fn check_binop(fcx: &FnCtxt,
2852 is_binop_assignment: IsBinopAssignment) {
2853 let tcx = fcx.ccx.tcx;
2855 let lvalue_pref = match is_binop_assignment {
2856 BinopAssignment => PreferMutLvalue,
2857 SimpleBinop => NoPreference
2859 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2861 // Callee does bot / err checking
2862 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2863 fcx.expr_ty(&*lhs));
2865 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2866 // Shift is a special case: rhs must be uint, no matter what lhs is
2867 check_expr(fcx, &**rhs);
2868 let rhs_ty = fcx.expr_ty(&**rhs);
2869 let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
2870 if ty::type_is_integral(rhs_ty) {
2871 fcx.write_ty(expr.id, lhs_t);
2873 fcx.type_error_message(
2877 "right-hand-side of a shift operation must have integral type, \
2883 fcx.write_ty(expr.id, fcx.tcx().types.err);
2888 if ty::is_binopable(tcx, lhs_t, op) {
2889 let tvar = fcx.infcx().next_ty_var();
2890 demand::suptype(fcx, expr.span, tvar, lhs_t);
2891 check_expr_has_type(fcx, &**rhs, tvar);
2893 let result_t = match op {
2894 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2896 if ty::type_is_simd(tcx, lhs_t) {
2897 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2898 fcx.type_error_message(expr.span,
2900 format!("binary comparison \
2901 operation `{}` not \
2902 supported for floating \
2903 point SIMD vector `{}`",
2904 ast_util::binop_to_string(op),
2915 fcx.tcx().types.bool
2921 fcx.write_ty(expr.id, result_t);
2925 if op == ast::BiOr || op == ast::BiAnd {
2926 // This is an error; one of the operands must have the wrong
2928 fcx.write_error(expr.id);
2929 fcx.write_error(rhs.id);
2930 fcx.type_error_message(expr.span,
2932 format!("binary operation `{}` cannot be applied \
2934 ast_util::binop_to_string(op),
2941 // Check for overloaded operators if not an assignment.
2942 let result_t = if is_binop_assignment == SimpleBinop {
2943 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2945 fcx.type_error_message(expr.span,
2947 format!("binary assignment \
2949 cannot be applied to \
2951 ast_util::binop_to_string(op),
2956 check_expr(fcx, &**rhs);
2960 fcx.write_ty(expr.id, result_t);
2961 if ty::type_is_error(result_t) {
2962 fcx.write_ty(rhs.id, result_t);
2966 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2968 lhs_expr: &ast::Expr,
2969 lhs_resolved_t: Ty<'tcx>,
2971 rhs: &P<ast::Expr>) -> Ty<'tcx> {
2972 let tcx = fcx.ccx.tcx;
2973 let lang = &tcx.lang_items;
2974 let (name, trait_did) = match op {
2975 ast::BiAdd => ("add", lang.add_trait()),
2976 ast::BiSub => ("sub", lang.sub_trait()),
2977 ast::BiMul => ("mul", lang.mul_trait()),
2978 ast::BiDiv => ("div", lang.div_trait()),
2979 ast::BiRem => ("rem", lang.rem_trait()),
2980 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2981 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2982 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2983 ast::BiShl => ("shl", lang.shl_trait()),
2984 ast::BiShr => ("shr", lang.shr_trait()),
2985 ast::BiLt => ("lt", lang.ord_trait()),
2986 ast::BiLe => ("le", lang.ord_trait()),
2987 ast::BiGe => ("ge", lang.ord_trait()),
2988 ast::BiGt => ("gt", lang.ord_trait()),
2989 ast::BiEq => ("eq", lang.eq_trait()),
2990 ast::BiNe => ("ne", lang.eq_trait()),
2991 ast::BiAnd | ast::BiOr => {
2992 check_expr(fcx, &**rhs);
2993 return tcx.types.err;
2996 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2997 trait_did, lhs_expr, Some(rhs), || {
2998 fcx.type_error_message(ex.span, |actual| {
2999 format!("binary operation `{}` cannot be applied to type `{}`",
3000 ast_util::binop_to_string(op),
3002 }, lhs_resolved_t, None)
3003 }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3006 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3009 trait_did: Option<ast::DefId>,
3011 rhs_expr: &ast::Expr,
3013 op: ast::UnOp) -> Ty<'tcx> {
3014 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3015 trait_did, rhs_expr, None, || {
3016 fcx.type_error_message(ex.span, |actual| {
3017 format!("cannot apply unary operator `{}` to type `{}`",
3020 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3023 // Check field access expressions
3024 fn check_field(fcx: &FnCtxt,
3026 lvalue_pref: LvaluePreference,
3028 field: &ast::SpannedIdent) {
3029 let tcx = fcx.ccx.tcx;
3030 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3031 let expr_t = structurally_resolved_type(fcx, expr.span,
3033 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3034 let (_, autoderefs, field_ty) =
3035 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3037 ty::ty_struct(base_id, substs) => {
3038 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3039 let fields = ty::lookup_struct_fields(tcx, base_id);
3040 fcx.lookup_field_ty(expr.span, base_id, &fields[],
3041 field.node.name, &(*substs))
3048 fcx.write_ty(expr.id, field_ty);
3049 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3055 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3056 fcx.type_error_message(
3059 format!("attempted to take value of method `{}` on type \
3060 `{}`", token::get_ident(field.node), actual)
3064 tcx.sess.span_help(field.span,
3065 "maybe a `()` to call it is missing? \
3066 If not, try an anonymous function");
3068 fcx.type_error_message(
3071 format!("attempted access of field `{}` on \
3072 type `{}`, but no field with that \
3074 token::get_ident(field.node),
3080 fcx.write_error(expr.id);
3083 // Check tuple index expressions
3084 fn check_tup_field(fcx: &FnCtxt,
3086 lvalue_pref: LvaluePreference,
3088 idx: codemap::Spanned<uint>) {
3089 let tcx = fcx.ccx.tcx;
3090 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3091 let expr_t = structurally_resolved_type(fcx, expr.span,
3093 let mut tuple_like = false;
3094 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3095 let (_, autoderefs, field_ty) =
3096 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3098 ty::ty_struct(base_id, substs) => {
3099 tuple_like = ty::is_tuple_struct(tcx, base_id);
3101 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3102 let fields = ty::lookup_struct_fields(tcx, base_id);
3103 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3104 idx.node, &(*substs))
3109 ty::ty_tup(ref v) => {
3111 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3118 fcx.write_ty(expr.id, field_ty);
3119 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3124 fcx.type_error_message(
3128 format!("attempted out-of-bounds tuple index `{}` on \
3133 format!("attempted tuple index `{}` on type `{}`, but the \
3134 type was not a tuple or tuple struct",
3141 fcx.write_error(expr.id);
3144 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3145 struct_ty: Ty<'tcx>,
3147 class_id: ast::DefId,
3148 node_id: ast::NodeId,
3149 substitutions: &'tcx subst::Substs<'tcx>,
3150 field_types: &[ty::field_ty],
3151 ast_fields: &[ast::Field],
3152 check_completeness: bool,
3153 enum_id_opt: Option<ast::DefId>) {
3154 let tcx = fcx.ccx.tcx;
3156 let mut class_field_map = FnvHashMap();
3157 let mut fields_found = 0;
3158 for field in field_types.iter() {
3159 class_field_map.insert(field.name, (field.id, false));
3162 let mut error_happened = false;
3164 // Typecheck each field.
3165 for field in ast_fields.iter() {
3166 let mut expected_field_type = tcx.types.err;
3168 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3171 fcx.type_error_message(
3173 |actual| match enum_id_opt {
3175 let variant_type = ty::enum_variant_with_id(tcx,
3178 format!("struct variant `{}::{}` has no field named `{}`",
3179 actual, variant_type.name.as_str(),
3180 token::get_ident(field.ident.node))
3183 format!("structure `{}` has no field named `{}`",
3185 token::get_ident(field.ident.node))
3190 error_happened = true;
3192 Some((_, true)) => {
3193 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3194 "field `{}` specified more than once",
3195 token::get_ident(field.ident.node));
3196 error_happened = true;
3198 Some((field_id, false)) => {
3199 expected_field_type =
3200 ty::lookup_field_type(
3201 tcx, class_id, field_id, substitutions);
3202 expected_field_type =
3203 fcx.normalize_associated_types_in(
3204 field.span, &expected_field_type);
3205 class_field_map.insert(
3206 field.ident.node.name, (field_id, true));
3211 // Make sure to give a type to the field even if there's
3212 // an error, so we can continue typechecking
3213 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3217 fcx.write_error(node_id);
3220 if check_completeness && !error_happened {
3221 // Make sure the programmer specified all the fields.
3222 assert!(fields_found <= field_types.len());
3223 if fields_found < field_types.len() {
3224 let mut missing_fields = Vec::new();
3225 for class_field in field_types.iter() {
3226 let name = class_field.name;
3227 let (_, seen) = class_field_map[name];
3229 missing_fields.push(
3230 format!("`{}`", token::get_name(name).get()))
3234 span_err!(tcx.sess, span, E0063,
3235 "missing field{}: {}",
3236 if missing_fields.len() == 1 {""} else {"s"},
3237 missing_fields.connect(", "));
3241 if !error_happened {
3242 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3243 class_id, substitutions));
3247 fn check_struct_constructor(fcx: &FnCtxt,
3249 span: codemap::Span,
3250 class_id: ast::DefId,
3251 fields: &[ast::Field],
3252 base_expr: Option<&ast::Expr>) {
3253 let tcx = fcx.ccx.tcx;
3255 // Generate the struct type.
3257 ty: mut struct_type,
3258 substs: struct_substs
3259 } = fcx.instantiate_type(span, class_id);
3261 // Look up and check the fields.
3262 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3263 check_struct_or_variant_fields(fcx,
3268 fcx.ccx.tcx.mk_substs(struct_substs),
3271 base_expr.is_none(),
3273 if ty::type_is_error(fcx.node_ty(id)) {
3274 struct_type = tcx.types.err;
3277 // Check the base expression if necessary.
3280 Some(base_expr) => {
3281 check_expr_has_type(fcx, &*base_expr, struct_type);
3285 // Write in the resulting type.
3286 fcx.write_ty(id, struct_type);
3289 fn check_struct_enum_variant(fcx: &FnCtxt,
3291 span: codemap::Span,
3292 enum_id: ast::DefId,
3293 variant_id: ast::DefId,
3294 fields: &[ast::Field]) {
3295 let tcx = fcx.ccx.tcx;
3297 // Look up the number of type parameters and the raw type, and
3298 // determine whether the enum is region-parameterized.
3301 substs: substitutions
3302 } = fcx.instantiate_type(span, enum_id);
3304 // Look up and check the enum variant fields.
3305 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3306 check_struct_or_variant_fields(fcx,
3311 fcx.ccx.tcx.mk_substs(substitutions),
3316 fcx.write_ty(id, enum_type);
3319 fn check_struct_fields_on_error(fcx: &FnCtxt,
3321 fields: &[ast::Field],
3322 base_expr: &Option<P<ast::Expr>>) {
3323 // Make sure to still write the types
3324 // otherwise we might ICE
3325 fcx.write_error(id);
3326 for field in fields.iter() {
3327 check_expr(fcx, &*field.expr);
3330 Some(ref base) => check_expr(fcx, &**base),
3335 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3337 let tcx = fcx.ccx.tcx;
3340 ast::ExprBox(ref opt_place, ref subexpr) => {
3341 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3342 check_expr(fcx, &**subexpr);
3344 let mut checked = false;
3345 opt_place.as_ref().map(|place| match place.node {
3346 ast::ExprPath(ref path) => {
3347 // FIXME(pcwalton): For now we hardcode the two permissible
3348 // places: the exchange heap and the managed heap.
3349 let definition = lookup_def(fcx, path.span, place.id);
3350 let def_id = definition.def_id();
3351 let referent_ty = fcx.expr_ty(&**subexpr);
3352 if tcx.lang_items.exchange_heap() == Some(def_id) {
3353 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3361 span_err!(tcx.sess, expr.span, E0066,
3362 "only the managed heap and exchange heap are currently supported");
3363 fcx.write_ty(id, tcx.types.err);
3367 ast::ExprLit(ref lit) => {
3368 let typ = check_lit(fcx, &**lit, expected);
3369 fcx.write_ty(id, typ);
3371 ast::ExprBinary(op, ref lhs, ref rhs) => {
3372 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3374 let lhs_ty = fcx.expr_ty(&**lhs);
3375 let rhs_ty = fcx.expr_ty(&**rhs);
3376 if ty::type_is_error(lhs_ty) ||
3377 ty::type_is_error(rhs_ty) {
3378 fcx.write_error(id);
3381 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3382 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3384 let lhs_t = fcx.expr_ty(&**lhs);
3385 let result_t = fcx.expr_ty(expr);
3386 demand::suptype(fcx, expr.span, result_t, lhs_t);
3388 let tcx = fcx.tcx();
3389 if !ty::expr_is_lval(tcx, &**lhs) {
3390 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3393 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3395 // Overwrite result of check_binop...this preserves existing behavior
3396 // but seems quite dubious with regard to user-defined methods
3397 // and so forth. - Niko
3398 if !ty::type_is_error(result_t) {
3399 fcx.write_nil(expr.id);
3402 ast::ExprUnary(unop, ref oprnd) => {
3403 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3405 ast::UnUniq => match ty.sty {
3406 ty::ty_uniq(ty) => {
3407 Expectation::rvalue_hint(ty)
3413 ast::UnNot | ast::UnNeg => {
3421 let lvalue_pref = match unop {
3422 ast::UnDeref => lvalue_pref,
3425 check_expr_with_expectation_and_lvalue_pref(
3426 fcx, &**oprnd, expected_inner, lvalue_pref);
3427 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3429 if !ty::type_is_error(oprnd_t) {
3432 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3435 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3436 oprnd_t = match ty::deref(oprnd_t, true) {
3438 None => match try_overloaded_deref(fcx, expr.span,
3439 Some(MethodCall::expr(expr.id)),
3440 Some(&**oprnd), oprnd_t, lvalue_pref) {
3443 let is_newtype = match oprnd_t.sty {
3444 ty::ty_struct(did, substs) => {
3445 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3447 && fields[0].name ==
3448 token::special_idents::unnamed_field.name
3453 // This is an obsolete struct deref
3454 span_err!(tcx.sess, expr.span, E0068,
3455 "single-field tuple-structs can \
3456 no longer be dereferenced");
3458 fcx.type_error_message(expr.span, |actual| {
3459 format!("type `{}` cannot be \
3460 dereferenced", actual)
3469 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3471 if !(ty::type_is_integral(oprnd_t) ||
3472 oprnd_t.sty == ty::ty_bool) {
3473 oprnd_t = check_user_unop(fcx, "!", "not",
3474 tcx.lang_items.not_trait(),
3475 expr, &**oprnd, oprnd_t, unop);
3479 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3481 if !(ty::type_is_integral(oprnd_t) ||
3482 ty::type_is_fp(oprnd_t)) {
3483 oprnd_t = check_user_unop(fcx, "-", "neg",
3484 tcx.lang_items.neg_trait(),
3485 expr, &**oprnd, oprnd_t, unop);
3490 fcx.write_ty(id, oprnd_t);
3492 ast::ExprAddrOf(mutbl, ref oprnd) => {
3493 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3495 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3496 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3497 // Lvalues may legitimately have unsized types.
3498 // For example, dereferences of a fat pointer and
3499 // the last field of a struct can be unsized.
3500 ExpectHasType(mt.ty)
3502 Expectation::rvalue_hint(mt.ty)
3508 let lvalue_pref = match mutbl {
3509 ast::MutMutable => PreferMutLvalue,
3510 ast::MutImmutable => NoPreference
3512 check_expr_with_expectation_and_lvalue_pref(fcx,
3517 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3518 let oprnd_t = if ty::type_is_error(tm.ty) {
3521 // Note: at this point, we cannot say what the best lifetime
3522 // is to use for resulting pointer. We want to use the
3523 // shortest lifetime possible so as to avoid spurious borrowck
3524 // errors. Moreover, the longest lifetime will depend on the
3525 // precise details of the value whose address is being taken
3526 // (and how long it is valid), which we don't know yet until type
3527 // inference is complete.
3529 // Therefore, here we simply generate a region variable. The
3530 // region inferencer will then select the ultimate value.
3531 // Finally, borrowck is charged with guaranteeing that the
3532 // value whose address was taken can actually be made to live
3533 // as long as it needs to live.
3535 // String literals are already, implicitly converted to slices.
3536 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3537 // Empty slices live in static memory.
3538 ast::ExprVec(ref elements) if elements.len() == 0 => {
3539 // Note: we do not assign a lifetime of
3540 // static. This is because the resulting type
3541 // `&'static [T]` would require that T outlives
3543 let region = fcx.infcx().next_region_var(
3544 infer::AddrOfSlice(expr.span));
3545 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3548 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3549 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3553 fcx.write_ty(id, oprnd_t);
3555 ast::ExprPath(ref path) => {
3556 let defn = lookup_def(fcx, path.span, id);
3557 let pty = type_scheme_for_def(fcx, expr.span, defn);
3558 instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3560 // We always require that the type provided as the value for
3561 // a type parameter outlives the moment of instantiation.
3562 constrain_path_type_parameters(fcx, expr);
3564 ast::ExprQPath(ref qpath) => {
3565 // Require explicit type params for the trait.
3566 let self_ty = fcx.to_ty(&*qpath.self_type);
3567 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3569 let defn = lookup_def(fcx, expr.span, id);
3570 let pty = type_scheme_for_def(fcx, expr.span, defn);
3571 let mut path = qpath.trait_ref.path.clone();
3572 path.segments.push(qpath.item_path.clone());
3573 instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3575 // We always require that the type provided as the value for
3576 // a type parameter outlives the moment of instantiation.
3577 constrain_path_type_parameters(fcx, expr);
3579 ast::ExprInlineAsm(ref ia) => {
3580 for &(_, ref input) in ia.inputs.iter() {
3581 check_expr(fcx, &**input);
3583 for &(_, ref out, _) in ia.outputs.iter() {
3584 check_expr(fcx, &**out);
3588 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3589 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3590 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3591 ast::ExprRet(ref expr_opt) => {
3593 ty::FnConverging(result_type) => {
3596 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3597 result_type, ty::mk_nil(fcx.tcx())) {
3598 span_err!(tcx.sess, expr.span, E0069,
3599 "`return;` in function returning non-nil");
3602 check_expr_coercable_to_type(fcx, &**e, result_type);
3606 ty::FnDiverging => {
3607 if let Some(ref e) = *expr_opt {
3608 check_expr(fcx, &**e);
3610 span_err!(tcx.sess, expr.span, E0166,
3611 "`return` in a function declared as diverging");
3614 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3616 ast::ExprParen(ref a) => {
3617 check_expr_with_expectation_and_lvalue_pref(fcx,
3621 fcx.write_ty(id, fcx.expr_ty(&**a));
3623 ast::ExprAssign(ref lhs, ref rhs) => {
3624 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3626 let tcx = fcx.tcx();
3627 if !ty::expr_is_lval(tcx, &**lhs) {
3628 span_err!(tcx.sess, expr.span, E0070,
3629 "illegal left-hand side expression");
3632 let lhs_ty = fcx.expr_ty(&**lhs);
3633 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3634 let rhs_ty = fcx.expr_ty(&**rhs);
3636 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3638 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3639 fcx.write_error(id);
3644 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3645 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3646 id, expr.span, expected);
3648 ast::ExprIfLet(..) => {
3649 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3651 ast::ExprWhile(ref cond, ref body, _) => {
3652 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3653 check_block_no_value(fcx, &**body);
3654 let cond_ty = fcx.expr_ty(&**cond);
3655 let body_ty = fcx.node_ty(body.id);
3656 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3657 fcx.write_error(id);
3663 ast::ExprWhileLet(..) => {
3664 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3666 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3667 check_expr(fcx, &**head);
3668 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
3669 vtable::select_new_fcx_obligations(fcx);
3671 debug!("ExprForLoop each item has type {}",
3672 fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
3674 let pcx = pat_ctxt {
3676 map: pat_id_map(&tcx.def_map, &**pat),
3678 _match::check_pat(&pcx, &**pat, typ);
3680 check_block_no_value(fcx, &**block);
3683 ast::ExprLoop(ref body, _) => {
3684 check_block_no_value(fcx, &**body);
3685 if !may_break(tcx, expr.id, &**body) {
3686 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3691 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3692 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3694 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3695 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3697 ast::ExprBlock(ref b) => {
3698 check_block_with_expected(fcx, &**b, expected);
3699 fcx.write_ty(id, fcx.node_ty(b.id));
3701 ast::ExprCall(ref callee, ref args) => {
3702 callee::check_call(fcx, expr, &**callee, &args[], expected);
3704 ast::ExprMethodCall(ident, ref tps, ref args) => {
3705 check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3706 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3707 let args_err = arg_tys.fold(false,
3709 rest_err || ty::type_is_error(a)});
3711 fcx.write_error(id);
3714 ast::ExprCast(ref e, ref t) => {
3715 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3716 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3718 check_cast(fcx, expr, &**e, &**t);
3720 ast::ExprVec(ref args) => {
3721 let uty = expected.to_option(fcx).and_then(|uty| {
3723 ty::ty_vec(ty, _) => Some(ty),
3728 let typ = match uty {
3730 for e in args.iter() {
3731 check_expr_coercable_to_type(fcx, &**e, uty);
3736 let t: Ty = fcx.infcx().next_ty_var();
3737 for e in args.iter() {
3738 check_expr_has_type(fcx, &**e, t);
3743 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3744 fcx.write_ty(id, typ);
3746 ast::ExprRepeat(ref element, ref count_expr) => {
3747 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3748 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3750 let uty = match expected {
3751 ExpectHasType(uty) => {
3753 ty::ty_vec(ty, _) => Some(ty),
3760 let (element_ty, t) = match uty {
3762 check_expr_coercable_to_type(fcx, &**element, uty);
3766 let t: Ty = fcx.infcx().next_ty_var();
3767 check_expr_has_type(fcx, &**element, t);
3768 (fcx.expr_ty(&**element), t)
3773 // For [foo, ..n] where n > 1, `foo` must have
3775 fcx.require_type_meets(
3782 if ty::type_is_error(element_ty) {
3783 fcx.write_error(id);
3785 let t = ty::mk_vec(tcx, t, Some(count));
3786 fcx.write_ty(id, t);
3789 ast::ExprTup(ref elts) => {
3790 let flds = expected.only_has_type(fcx).and_then(|ty| {
3792 ty::ty_tup(ref flds) => Some(&flds[]),
3796 let mut err_field = false;
3798 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3799 let t = match flds {
3800 Some(ref fs) if i < fs.len() => {
3802 check_expr_coercable_to_type(fcx, &**e, ety);
3806 check_expr_with_expectation(fcx, &**e, NoExpectation);
3810 err_field = err_field || ty::type_is_error(t);
3814 fcx.write_error(id);
3816 let typ = ty::mk_tup(tcx, elt_ts);
3817 fcx.write_ty(id, typ);
3820 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3821 // Resolve the path.
3822 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3823 let struct_id = match def {
3824 Some(def::DefVariant(enum_id, variant_id, true)) => {
3825 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3826 variant_id, &fields[]);
3829 Some(def::DefTrait(def_id)) => {
3830 span_err!(tcx.sess, path.span, E0159,
3831 "use of trait `{}` as a struct constructor",
3832 pprust::path_to_string(path));
3833 check_struct_fields_on_error(fcx,
3840 // Verify that this was actually a struct.
3841 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3843 ty::ty_struct(struct_did, _) => {
3844 check_struct_constructor(fcx,
3849 base_expr.as_ref().map(|e| &**e));
3852 span_err!(tcx.sess, path.span, E0071,
3853 "`{}` does not name a structure",
3854 pprust::path_to_string(path));
3855 check_struct_fields_on_error(fcx,
3865 tcx.sess.span_bug(path.span,
3866 "structure constructor wasn't resolved")
3870 // Turn the path into a type and verify that that type unifies with
3871 // the resulting structure type. This is needed to handle type
3872 // parameters correctly.
3873 let actual_structure_type = fcx.expr_ty(&*expr);
3874 if !ty::type_is_error(actual_structure_type) {
3875 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3876 match fcx.mk_subty(false,
3877 infer::Misc(path.span),
3878 actual_structure_type,
3879 type_and_substs.ty) {
3881 Err(type_error) => {
3882 let type_error_description =
3883 ty::type_err_to_str(tcx, &type_error);
3886 .span_err(path.span,
3887 &format!("structure constructor specifies a \
3888 structure of type `{}`, but this \
3889 structure has type `{}`: {}",
3891 .ty_to_string(type_and_substs.ty),
3894 actual_structure_type),
3895 type_error_description)[]);
3896 ty::note_and_explain_type_err(tcx, &type_error);
3901 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3903 ast::ExprField(ref base, ref field) => {
3904 check_field(fcx, expr, lvalue_pref, &**base, field);
3906 ast::ExprTupField(ref base, idx) => {
3907 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3909 ast::ExprIndex(ref base, ref idx) => {
3910 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3911 let base_t = fcx.expr_ty(&**base);
3912 if ty::type_is_error(base_t) {
3913 fcx.write_ty(id, base_t);
3915 check_expr(fcx, &**idx);
3916 let idx_t = fcx.expr_ty(&**idx);
3917 if ty::type_is_error(idx_t) {
3918 fcx.write_ty(id, idx_t);
3920 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3923 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3925 MethodCall::expr(expr.id),
3935 Some((index_ty, element_ty)) => {
3936 // FIXME: we've already checked idx above, we should
3937 // probably just demand subtype or something here.
3938 check_expr_has_type(fcx, &**idx, index_ty);
3939 fcx.write_ty(id, element_ty);
3942 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3943 fcx.type_error_message(
3946 format!("cannot index a value of type `{}`",
3951 fcx.write_ty(id, fcx.tcx().types.err);
3957 ast::ExprRange(ref start, ref end) => {
3958 let t_start = start.as_ref().map(|e| {
3959 check_expr(fcx, &**e);
3962 let t_end = end.as_ref().map(|e| {
3963 check_expr(fcx, &**e);
3967 let idx_type = match (t_start, t_end) {
3968 (Some(ty), None) | (None, Some(ty)) => {
3971 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3972 ty::type_is_error(t_end)) => {
3973 Some(fcx.tcx().types.err)
3975 (Some(t_start), Some(t_end)) => {
3976 Some(infer::common_supertype(fcx.infcx(),
3977 infer::RangeExpression(expr.span),
3985 // Note that we don't check the type of start/end satisfy any
3986 // bounds because right now the range structs do not have any. If we add
3987 // some bounds, then we'll need to check `t_start` against them here.
3989 let range_type = match idx_type {
3990 Some(idx_type) if ty::type_is_error(idx_type) => {
3994 // Find the did from the appropriate lang item.
3995 let did = match (start, end) {
3996 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3997 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3998 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4000 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4004 if let Some(did) = did {
4005 let polytype = ty::lookup_item_type(tcx, did);
4006 let substs = Substs::new_type(vec![idx_type], vec![]);
4007 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4008 fcx.add_obligations_for_parameters(
4009 traits::ObligationCause::new(expr.span,
4011 traits::ItemObligation(did)),
4014 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4016 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4021 // Neither start nor end => FullRange
4022 if let Some(did) = tcx.lang_items.full_range_struct() {
4023 let substs = Substs::new_type(vec![], vec![]);
4024 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4026 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4032 fcx.write_ty(id, range_type);
4037 debug!("type of expr({}) {} is...", expr.id,
4038 syntax::print::pprust::expr_to_string(expr));
4039 debug!("... {}, expected is {}",
4040 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4041 expected.repr(tcx));
4046 fn constrain_path_type_parameters(fcx: &FnCtxt,
4049 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4050 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4054 impl<'tcx> Expectation<'tcx> {
4055 /// Provide an expectation for an rvalue expression given an *optional*
4056 /// hint, which is not required for type safety (the resulting type might
4057 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4058 /// is useful in determining the concrete type.
4060 /// The primary use case is where the expected type is a fat pointer,
4061 /// like `&[int]`. For example, consider the following statement:
4063 /// let x: &[int] = &[1, 2, 3];
4065 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4066 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4067 /// expectation `ExpectHasType([int])`, that would be too strong --
4068 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4069 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4070 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4071 /// which still is useful, because it informs integer literals and the like.
4072 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4073 /// for examples of where this comes up,.
4074 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4076 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4077 ExpectRvalueLikeUnsized(ty)
4079 _ => ExpectHasType(ty)
4083 // Resolves `expected` by a single level if it is a variable. If
4084 // there is no expected type or resolution is not possible (e.g.,
4085 // no constraints yet present), just returns `None`.
4086 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4091 ExpectCastableToType(t) => {
4092 ExpectCastableToType(
4093 fcx.infcx().resolve_type_vars_if_possible(&t))
4095 ExpectHasType(t) => {
4097 fcx.infcx().resolve_type_vars_if_possible(&t))
4099 ExpectRvalueLikeUnsized(t) => {
4100 ExpectRvalueLikeUnsized(
4101 fcx.infcx().resolve_type_vars_if_possible(&t))
4106 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4107 match self.resolve(fcx) {
4108 NoExpectation => None,
4109 ExpectCastableToType(ty) |
4111 ExpectRvalueLikeUnsized(ty) => Some(ty),
4115 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4116 match self.resolve(fcx) {
4117 ExpectHasType(ty) => Some(ty),
4123 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4124 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4126 NoExpectation => format!("NoExpectation"),
4127 ExpectHasType(t) => format!("ExpectHasType({})",
4129 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4131 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4137 pub fn check_decl_initializer(fcx: &FnCtxt,
4141 let local_ty = fcx.local_ty(init.span, nid);
4142 check_expr_coercable_to_type(fcx, init, local_ty)
4145 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4146 let tcx = fcx.ccx.tcx;
4148 let t = fcx.local_ty(local.span, local.id);
4149 fcx.write_ty(local.id, t);
4151 if let Some(ref init) = local.init {
4152 check_decl_initializer(fcx, local.id, &**init);
4153 let init_ty = fcx.expr_ty(&**init);
4154 if ty::type_is_error(init_ty) {
4155 fcx.write_ty(local.id, init_ty);
4159 let pcx = pat_ctxt {
4161 map: pat_id_map(&tcx.def_map, &*local.pat),
4163 _match::check_pat(&pcx, &*local.pat, t);
4164 let pat_ty = fcx.node_ty(local.pat.id);
4165 if ty::type_is_error(pat_ty) {
4166 fcx.write_ty(local.id, pat_ty);
4170 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4172 let mut saw_bot = false;
4173 let mut saw_err = false;
4175 ast::StmtDecl(ref decl, id) => {
4178 ast::DeclLocal(ref l) => {
4179 check_decl_local(fcx, &**l);
4180 let l_t = fcx.node_ty(l.id);
4181 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4182 saw_err = saw_err || ty::type_is_error(l_t);
4184 ast::DeclItem(_) => {/* ignore for now */ }
4187 ast::StmtExpr(ref expr, id) => {
4189 // Check with expected type of ()
4190 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4191 let expr_ty = fcx.expr_ty(&**expr);
4192 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4193 saw_err = saw_err || ty::type_is_error(expr_ty);
4195 ast::StmtSemi(ref expr, id) => {
4197 check_expr(fcx, &**expr);
4198 let expr_ty = fcx.expr_ty(&**expr);
4199 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4200 saw_err |= ty::type_is_error(expr_ty);
4202 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4205 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4208 fcx.write_error(node_id);
4211 fcx.write_nil(node_id)
4215 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4216 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4217 let blkty = fcx.node_ty(blk.id);
4218 if ty::type_is_error(blkty) {
4219 fcx.write_error(blk.id);
4221 let nilty = ty::mk_nil(fcx.tcx());
4222 demand::suptype(fcx, blk.span, nilty, blkty);
4226 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4228 expected: Expectation<'tcx>) {
4230 let mut fcx_ps = fcx.ps.borrow_mut();
4231 let unsafety_state = fcx_ps.recurse(blk);
4232 replace(&mut *fcx_ps, unsafety_state)
4235 let mut warned = false;
4236 let mut any_diverges = false;
4237 let mut any_err = false;
4238 for s in blk.stmts.iter() {
4239 check_stmt(fcx, &**s);
4240 let s_id = ast_util::stmt_id(&**s);
4241 let s_ty = fcx.node_ty(s_id);
4242 if any_diverges && !warned && match s.node {
4243 ast::StmtDecl(ref decl, _) => {
4245 ast::DeclLocal(_) => true,
4249 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4255 .add_lint(lint::builtin::UNREACHABLE_CODE,
4258 "unreachable statement".to_string());
4261 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4262 any_err = any_err || ty::type_is_error(s_ty);
4265 None => if any_err {
4266 fcx.write_error(blk.id);
4267 } else if any_diverges {
4268 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4270 fcx.write_nil(blk.id);
4273 if any_diverges && !warned {
4277 .add_lint(lint::builtin::UNREACHABLE_CODE,
4280 "unreachable expression".to_string());
4282 let ety = match expected {
4283 ExpectHasType(ety) => {
4284 check_expr_coercable_to_type(fcx, &**e, ety);
4288 check_expr_with_expectation(fcx, &**e, expected);
4294 fcx.write_error(blk.id);
4295 } else if any_diverges {
4296 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4298 fcx.write_ty(blk.id, ety);
4303 *fcx.ps.borrow_mut() = prev;
4306 /// Checks a constant appearing in a type. At the moment this is just the
4307 /// length expression in a fixed-length vector, but someday it might be
4308 /// extended to type-level numeric literals.
4309 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4311 expected_type: Ty<'tcx>) {
4312 let inh = static_inherited_fields(ccx);
4313 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4314 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4317 fn check_const(ccx: &CrateCtxt,
4321 let inh = static_inherited_fields(ccx);
4322 let rty = ty::node_id_to_type(ccx.tcx, id);
4323 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4324 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4325 check_const_with_ty(&fcx, sp, e, declty);
4328 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4332 // Gather locals in statics (because of block expressions).
4333 // This is technically unnecessary because locals in static items are forbidden,
4334 // but prevents type checking from blowing up before const checking can properly
4336 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4338 check_expr_with_hint(fcx, e, declty);
4339 demand::coerce(fcx, e.span, declty, e);
4340 vtable::select_all_fcx_obligations_or_error(fcx);
4341 regionck::regionck_expr(fcx, e);
4342 writeback::resolve_type_vars_in_expr(fcx, e);
4345 /// Checks whether a type can be represented in memory. In particular, it
4346 /// identifies types that contain themselves without indirection through a
4347 /// pointer, which would mean their size is unbounded. This is different from
4348 /// the question of whether a type can be instantiated. See the definition of
4349 /// `check_instantiable`.
4350 pub fn check_representable(tcx: &ty::ctxt,
4352 item_id: ast::NodeId,
4353 designation: &str) -> bool {
4354 let rty = ty::node_id_to_type(tcx, item_id);
4356 // Check that it is possible to represent this type. This call identifies
4357 // (1) types that contain themselves and (2) types that contain a different
4358 // recursive type. It is only necessary to throw an error on those that
4359 // contain themselves. For case 2, there must be an inner type that will be
4360 // caught by case 1.
4361 match ty::is_type_representable(tcx, sp, rty) {
4362 ty::SelfRecursive => {
4363 span_err!(tcx.sess, sp, E0072,
4364 "illegal recursive {} type; \
4365 wrap the inner value in a box to make it representable",
4369 ty::Representable | ty::ContainsRecursive => (),
4374 /// Checks whether a type can be created without an instance of itself.
4375 /// This is similar but different from the question of whether a type
4376 /// can be represented. For example, the following type:
4378 /// enum foo { None, Some(foo) }
4380 /// is instantiable but is not representable. Similarly, the type
4382 /// enum foo { Some(@foo) }
4384 /// is representable, but not instantiable.
4385 pub fn check_instantiable(tcx: &ty::ctxt,
4387 item_id: ast::NodeId)
4389 let item_ty = ty::node_id_to_type(tcx, item_id);
4390 if !ty::is_instantiable(tcx, item_ty) {
4391 span_err!(tcx.sess, sp, E0073,
4392 "this type cannot be instantiated without an \
4393 instance of itself");
4394 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4395 ppaux::ty_to_string(tcx, item_ty));
4402 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4403 let t = ty::node_id_to_type(tcx, id);
4404 if ty::type_needs_subst(t) {
4405 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4409 ty::ty_struct(did, substs) => {
4410 let fields = ty::lookup_struct_fields(tcx, did);
4411 if fields.is_empty() {
4412 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4415 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4416 if !fields.iter().all(
4417 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4418 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4421 if !ty::type_is_machine(e) {
4422 span_err!(tcx.sess, sp, E0077,
4423 "SIMD vector element type should be machine type");
4431 pub fn check_enum_variants(ccx: &CrateCtxt,
4433 vs: &[P<ast::Variant>],
4436 fn disr_in_range(ccx: &CrateCtxt,
4438 disr: ty::Disr) -> bool {
4439 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4441 ast::TyU8 => disr as u8 as Disr == disr,
4442 ast::TyU16 => disr as u16 as Disr == disr,
4443 ast::TyU32 => disr as u32 as Disr == disr,
4444 ast::TyU64 => disr as u64 as Disr == disr,
4445 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4448 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4450 ast::TyI8 => disr as i8 as Disr == disr,
4451 ast::TyI16 => disr as i16 as Disr == disr,
4452 ast::TyI32 => disr as i32 as Disr == disr,
4453 ast::TyI64 => disr as i64 as Disr == disr,
4454 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4458 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4459 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4463 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4464 vs: &[P<ast::Variant>],
4466 hint: attr::ReprAttr)
4467 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4469 let rty = ty::node_id_to_type(ccx.tcx, id);
4470 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4471 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4472 let mut prev_disr_val: Option<ty::Disr> = None;
4474 for v in vs.iter() {
4476 // If the discriminant value is specified explicitly in the enum check whether the
4477 // initialization expression is valid, otherwise use the last value plus one.
4478 let mut current_disr_val = match prev_disr_val {
4479 Some(prev_disr_val) => prev_disr_val + 1,
4480 None => ty::INITIAL_DISCRIMINANT_VALUE
4483 match v.node.disr_expr {
4485 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4487 let inh = static_inherited_fields(ccx);
4488 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4489 let declty = match hint {
4490 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4491 attr::ReprInt(_, attr::SignedInt(ity)) => {
4492 ty::mk_mach_int(fcx.tcx(), ity)
4494 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4495 ty::mk_mach_uint(fcx.tcx(), ity)
4498 check_const_with_ty(&fcx, e.span, &**e, declty);
4499 // check_expr (from check_const pass) doesn't guarantee
4500 // that the expression is in a form that eval_const_expr can
4501 // handle, so we may still get an internal compiler error
4503 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4504 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4505 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4507 span_err!(ccx.tcx.sess, e.span, E0079,
4508 "expected signed integer constant");
4511 span_err!(ccx.tcx.sess, e.span, E0080,
4512 "expected constant: {}", *err);
4519 // Check for duplicate discriminant values
4520 match disr_vals.iter().position(|&x| x == current_disr_val) {
4522 span_err!(ccx.tcx.sess, v.span, E0081,
4523 "discriminant value `{}` already exists", disr_vals[i]);
4524 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4525 "conflicting discriminant here")
4529 // Check for unrepresentable discriminant values
4531 attr::ReprAny | attr::ReprExtern => (),
4532 attr::ReprInt(sp, ity) => {
4533 if !disr_in_range(ccx, ity, current_disr_val) {
4534 span_err!(ccx.tcx.sess, v.span, E0082,
4535 "discriminant value outside specified type");
4536 span_note!(ccx.tcx.sess, sp,
4537 "discriminant type specified here");
4540 attr::ReprPacked => {
4541 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4544 disr_vals.push(current_disr_val);
4546 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4548 prev_disr_val = Some(current_disr_val);
4550 variants.push(variant_info);
4556 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4557 [].get(0).unwrap_or(&attr::ReprAny);
4559 if hint != attr::ReprAny && vs.len() <= 1 {
4561 span_err!(ccx.tcx.sess, sp, E0083,
4562 "unsupported representation for univariant enum");
4564 span_err!(ccx.tcx.sess, sp, E0084,
4565 "unsupported representation for zero-variant enum");
4569 let variants = do_check(ccx, vs, id, hint);
4571 // cache so that ty::enum_variants won't repeat this work
4572 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4574 check_representable(ccx.tcx, sp, id, "enum");
4576 // Check that it is possible to instantiate this enum:
4578 // This *sounds* like the same that as representable, but it's
4579 // not. See def'n of `check_instantiable()` for details.
4580 check_instantiable(ccx.tcx, sp, id);
4583 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4584 lookup_def_ccx(fcx.ccx, sp, id)
4587 // Returns the type parameter count and the type for the given definition.
4588 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4591 -> TypeScheme<'tcx> {
4593 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4594 let typ = fcx.local_ty(sp, nid);
4595 return no_params(typ);
4597 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4598 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4599 def::DefStruct(id) | def::DefConst(id) => {
4600 return ty::lookup_item_type(fcx.ccx.tcx, id);
4604 def::DefAssociatedTy(..) |
4605 def::DefAssociatedPath(..) |
4607 def::DefTyParam(..) => {
4608 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4610 def::DefMod(..) | def::DefForeignMod(..) => {
4611 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4613 def::DefUse(..) => {
4614 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4616 def::DefRegion(..) => {
4617 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4619 def::DefTyParamBinder(..) => {
4620 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4622 def::DefLabel(..) => {
4623 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4625 def::DefSelfTy(..) => {
4626 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4631 // Instantiates the given path, which must refer to an item with the given
4632 // number of type parameters and type.
4633 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4635 type_scheme: TypeScheme<'tcx>,
4636 opt_self_ty: Option<Ty<'tcx>>,
4639 node_id: ast::NodeId) {
4640 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4641 path.repr(fcx.tcx()),
4642 def.repr(fcx.tcx()),
4644 type_scheme.repr(fcx.tcx()));
4646 // We need to extract the type parameters supplied by the user in
4647 // the path `path`. Due to the current setup, this is a bit of a
4648 // tricky-process; the problem is that resolve only tells us the
4649 // end-point of the path resolution, and not the intermediate steps.
4650 // Luckily, we can (at least for now) deduce the intermediate steps
4651 // just from the end-point.
4653 // There are basically three cases to consider:
4655 // 1. Reference to a *type*, such as a struct or enum:
4657 // mod a { struct Foo<T> { ... } }
4659 // Because we don't allow types to be declared within one
4660 // another, a path that leads to a type will always look like
4661 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4662 // that only the final segment can have type parameters, and
4663 // they are located in the TypeSpace.
4665 // *Note:* Generally speaking, references to types don't
4666 // actually pass through this function, but rather the
4667 // `ast_ty_to_ty` function in `astconv`. However, in the case
4668 // of struct patterns (and maybe literals) we do invoke
4669 // `instantiate_path` to get the general type of an instance of
4670 // a struct. (In these cases, there are actually no type
4671 // parameters permitted at present, but perhaps we will allow
4672 // them in the future.)
4674 // 1b. Reference to a enum variant or tuple-like struct:
4676 // struct foo<T>(...)
4677 // enum E<T> { foo(...) }
4679 // In these cases, the parameters are declared in the type
4682 // 2. Reference to a *fn item*:
4686 // In this case, the path will again always have the form
4687 // `a::b::foo::<T>` where only the final segment should have
4688 // type parameters. However, in this case, those parameters are
4689 // declared on a value, and hence are in the `FnSpace`.
4691 // 3. Reference to a *method*:
4693 // impl<A> SomeStruct<A> {
4697 // Here we can have a path like
4698 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4699 // may appear in two places. The penultimate segment,
4700 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4701 // final segment, `foo::<B>` contains parameters in fn space.
4703 // The first step then is to categorize the segments appropriately.
4705 assert!(path.segments.len() >= 1);
4706 let mut segment_spaces: Vec<_>;
4708 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4709 def::DefSelfTy(..) |
4710 def::DefStruct(..) |
4711 def::DefVariant(..) |
4712 def::DefTyParamBinder(..) |
4714 def::DefAssociatedTy(..) |
4715 def::DefAssociatedPath(..) |
4717 def::DefPrimTy(..) |
4718 def::DefTyParam(..) => {
4719 // Everything but the final segment should have no
4720 // parameters at all.
4721 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4722 segment_spaces.push(Some(subst::TypeSpace));
4725 // Case 2. Reference to a top-level value.
4728 def::DefStatic(..) => {
4729 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4730 segment_spaces.push(Some(subst::FnSpace));
4733 // Case 3. Reference to a method.
4734 def::DefStaticMethod(_, providence) |
4735 def::DefMethod(_, _, providence) => {
4736 assert!(path.segments.len() >= 2);
4739 def::FromTrait(trait_did) => {
4740 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4742 def::FromImpl(_) => {}
4745 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4746 segment_spaces.push(Some(subst::TypeSpace));
4747 segment_spaces.push(Some(subst::FnSpace));
4750 // Other cases. Various nonsense that really shouldn't show up
4751 // here. If they do, an error will have been reported
4752 // elsewhere. (I hope)
4754 def::DefForeignMod(..) |
4757 def::DefRegion(..) |
4759 def::DefUpvar(..) => {
4760 segment_spaces = repeat(None).take(path.segments.len()).collect();
4763 assert_eq!(segment_spaces.len(), path.segments.len());
4765 debug!("segment_spaces={:?}", segment_spaces);
4767 // Next, examine the definition, and determine how many type
4768 // parameters we expect from each space.
4769 let type_defs = &type_scheme.generics.types;
4770 let region_defs = &type_scheme.generics.regions;
4772 // Now that we have categorized what space the parameters for each
4773 // segment belong to, let's sort out the parameters that the user
4774 // provided (if any) into their appropriate spaces. We'll also report
4775 // errors if type parameters are provided in an inappropriate place.
4776 let mut substs = Substs::empty();
4777 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4780 report_error_if_segment_contains_type_parameters(fcx, segment);
4784 push_explicit_parameters_from_segment_to_substs(fcx,
4794 if let Some(self_ty) = opt_self_ty {
4795 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4796 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4797 substs.types.push(subst::SelfSpace, self_ty);
4800 // Now we have to compare the types that the user *actually*
4801 // provided against the types that were *expected*. If the user
4802 // did not provide any types, then we want to substitute inference
4803 // variables. If the user provided some types, we may still need
4804 // to add defaults. If the user provided *too many* types, that's
4806 for &space in ParamSpace::all().iter() {
4807 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4808 assert_eq!(substs.types.len(space), type_defs.len(space));
4810 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4811 assert_eq!(substs.regions().len(space), region_defs.len(space));
4814 // The things we are substituting into the type should not contain
4815 // escaping late-bound regions, and nor should the base type scheme.
4816 assert!(!substs.has_regions_escaping_depth(0));
4817 assert!(!type_scheme.has_escaping_regions());
4819 // Add all the obligations that are required, substituting and
4820 // normalized appropriately.
4821 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4822 fcx.add_obligations_for_parameters(
4823 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4826 // Substitute the values for the type parameters into the type of
4827 // the referenced item.
4828 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4830 fcx.write_ty(node_id, ty_substituted);
4831 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4834 fn report_error_if_segment_contains_type_parameters(
4836 segment: &ast::PathSegment)
4838 for typ in segment.parameters.types().iter() {
4839 span_err!(fcx.tcx().sess, typ.span, E0085,
4840 "type parameters may not appear here");
4844 for lifetime in segment.parameters.lifetimes().iter() {
4845 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4846 "lifetime parameters may not appear here");
4851 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4852 /// parameters are provided, then reports an error and clears the output vector.
4854 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4855 /// use inference variables. This seems less likely to lead to derived errors.
4857 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4858 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4859 /// here because we can easily use the precise span of the N+1'th parameter.
4860 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4861 fcx: &FnCtxt<'a, 'tcx>,
4862 space: subst::ParamSpace,
4864 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4865 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4866 segment: &ast::PathSegment,
4867 substs: &mut Substs<'tcx>)
4869 match segment.parameters {
4870 ast::AngleBracketedParameters(ref data) => {
4871 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4872 fcx, space, type_defs, region_defs, data, substs);
4875 ast::ParenthesizedParameters(ref data) => {
4876 fcx.tcx().sess.span_err(
4878 "parenthesized parameters may only be used with a trait");
4879 push_explicit_parenthesized_parameters_from_segment_to_substs(
4880 fcx, space, span, type_defs, data, substs);
4885 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4886 fcx: &FnCtxt<'a, 'tcx>,
4887 space: subst::ParamSpace,
4888 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4889 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4890 data: &ast::AngleBracketedParameterData,
4891 substs: &mut Substs<'tcx>)
4894 let type_count = type_defs.len(space);
4895 assert_eq!(substs.types.len(space), 0);
4896 for (i, typ) in data.types.iter().enumerate() {
4897 let t = fcx.to_ty(&**typ);
4899 substs.types.push(space, t);
4900 } else if i == type_count {
4901 span_err!(fcx.tcx().sess, typ.span, E0087,
4902 "too many type parameters provided: \
4903 expected at most {} parameter(s), \
4904 found {} parameter(s)",
4905 type_count, data.types.len());
4906 substs.types.truncate(space, 0);
4912 if data.bindings.len() > 0 {
4913 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4914 "unexpected binding of associated item in expression path \
4915 (only allowed in type paths)");
4919 let region_count = region_defs.len(space);
4920 assert_eq!(substs.regions().len(space), 0);
4921 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4922 let r = ast_region_to_region(fcx.tcx(), lifetime);
4923 if i < region_count {
4924 substs.mut_regions().push(space, r);
4925 } else if i == region_count {
4926 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4927 "too many lifetime parameters provided: \
4928 expected {} parameter(s), found {} parameter(s)",
4930 data.lifetimes.len());
4931 substs.mut_regions().truncate(space, 0);
4939 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4940 /// but intended for `Foo(A,B) -> C` form. This expands to
4941 /// roughly the same thing as `Foo<(A,B),C>`. One important
4942 /// difference has to do with the treatment of anonymous
4943 /// regions, which are translated into bound regions (NYI).
4944 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4945 fcx: &FnCtxt<'a, 'tcx>,
4946 space: subst::ParamSpace,
4948 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4949 data: &ast::ParenthesizedParameterData,
4950 substs: &mut Substs<'tcx>)
4952 let type_count = type_defs.len(space);
4954 span_err!(fcx.tcx().sess, span, E0167,
4955 "parenthesized form always supplies 2 type parameters, \
4956 but only {} parameter(s) were expected",
4960 let input_tys: Vec<Ty> =
4961 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4964 ty::mk_tup(fcx.tcx(), input_tys);
4966 if type_count >= 1 {
4967 substs.types.push(space, tuple_ty);
4970 let output_ty: Option<Ty> =
4971 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4974 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4976 if type_count >= 2 {
4977 substs.types.push(space, output_ty);
4981 fn adjust_type_parameters<'a, 'tcx>(
4982 fcx: &FnCtxt<'a, 'tcx>,
4985 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4986 substs: &mut Substs<'tcx>)
4988 let provided_len = substs.types.len(space);
4989 let desired = defs.get_slice(space);
4990 let required_len = desired.iter()
4991 .take_while(|d| d.default.is_none())
4994 debug!("adjust_type_parameters(space={:?}, \
5003 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5004 assert!(provided_len <= desired.len());
5006 // Nothing specified at all: supply inference variables for
5008 if provided_len == 0 {
5009 substs.types.replace(space,
5010 fcx.infcx().next_ty_vars(desired.len()));
5014 // Too few parameters specified: report an error and use Err
5016 if provided_len < required_len {
5018 if desired.len() != required_len { "at least " } else { "" };
5019 span_err!(fcx.tcx().sess, span, E0089,
5020 "too few type parameters provided: expected {}{} parameter(s) \
5021 , found {} parameter(s)",
5022 qualifier, required_len, provided_len);
5023 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5027 // Otherwise, add in any optional parameters that the user
5028 // omitted. The case of *too many* parameters is handled
5030 // push_explicit_parameters_from_segment_to_substs(). Note
5031 // that the *default* type are expressed in terms of all prior
5032 // parameters, so we have to substitute as we go with the
5033 // partial substitution that we have built up.
5034 for i in range(provided_len, desired.len()) {
5035 let default = desired[i].default.unwrap();
5036 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5037 substs.types.push(space, default);
5039 assert_eq!(substs.types.len(space), desired.len());
5041 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5044 fn adjust_region_parameters(
5048 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5049 substs: &mut Substs)
5051 let provided_len = substs.mut_regions().len(space);
5052 let desired = defs.get_slice(space);
5054 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5055 assert!(provided_len <= desired.len());
5057 // If nothing was provided, just use inference variables.
5058 if provided_len == 0 {
5059 substs.mut_regions().replace(
5061 fcx.infcx().region_vars_for_defs(span, desired));
5065 // If just the right number were provided, everybody is happy.
5066 if provided_len == desired.len() {
5070 // Otherwise, too few were provided. Report an error and then
5071 // use inference variables.
5072 span_err!(fcx.tcx().sess, span, E0090,
5073 "too few lifetime parameters provided: expected {} parameter(s), \
5074 found {} parameter(s)",
5075 desired.len(), provided_len);
5077 substs.mut_regions().replace(
5079 fcx.infcx().region_vars_for_defs(span, desired));
5083 // Resolves `typ` by a single level if `typ` is a type variable. If no
5084 // resolution is possible, then an error is reported.
5085 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5086 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5087 // If `ty` is a type variable, see whether we already know what it is.
5088 ty = fcx.infcx().shallow_resolve(ty);
5090 // If not, try resolve pending fcx obligations. Those can shed light.
5092 // FIXME(#18391) -- This current strategy can lead to bad performance in
5093 // extreme cases. We probably ought to smarter in general about
5094 // only resolving when we need help and only resolving obligations
5095 // will actually help.
5096 if ty::type_is_ty_var(ty) {
5097 vtable::select_fcx_obligations_where_possible(fcx);
5098 ty = fcx.infcx().shallow_resolve(ty);
5102 if ty::type_is_ty_var(ty) {
5103 fcx.type_error_message(sp, |_actual| {
5104 "the type of this value must be known in this \
5105 context".to_string()
5107 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5108 ty = fcx.tcx().types.err;
5114 // Returns true if b contains a break that can exit from b
5115 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5116 // First: is there an unlabeled break immediately
5118 (loop_query(&*b, |e| {
5120 ast::ExprBreak(_) => true,
5124 // Second: is there a labeled break with label
5125 // <id> nested anywhere inside the loop?
5126 (block_query(b, |e| {
5128 ast::ExprBreak(Some(_)) => {
5129 match cx.def_map.borrow().get(&e.id) {
5130 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5138 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5140 tps: &OwnedSlice<ast::TyParam>,
5142 debug!("check_bounds_are_used(n_tps={}, ty={})",
5143 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5145 // make a vector of booleans initially false, set to true when used
5146 if tps.len() == 0u { return; }
5147 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5149 ty::walk_ty(ty, |t| {
5151 ty::ty_param(ParamTy {idx, ..}) => {
5152 debug!("Found use of ty param num {}", idx);
5153 tps_used[idx as uint] = true;
5159 for (i, b) in tps_used.iter().enumerate() {
5161 span_err!(ccx.tcx.sess, span, E0091,
5162 "type parameter `{}` is unused",
5163 token::get_ident(tps[i].ident));
5168 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5169 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5170 let name = token::intern(format!("P{}", n).as_slice());
5171 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5175 let name = token::get_ident(it.ident);
5176 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5177 let split : Vec<&str> = name.get().split('_').collect();
5178 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5180 //We only care about the operation here
5181 let (n_tps, inputs, output) = match split[1] {
5182 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5186 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5188 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5191 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5192 "min" | "umax" | "umin" => {
5193 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5197 (0, Vec::new(), ty::mk_nil(tcx))
5200 span_err!(tcx.sess, it.span, E0092,
5201 "unrecognized atomic operation function: `{}`", op);
5205 (n_tps, inputs, ty::FnConverging(output))
5206 } else if name.get() == "abort" || name.get() == "unreachable" {
5207 (0, Vec::new(), ty::FnDiverging)
5209 let (n_tps, inputs, output) = match name.get() {
5210 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5212 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5213 "init" => (1u, Vec::new(), param(ccx, 0)),
5214 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5215 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5216 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5217 "move_val_init" => {
5220 ty::mk_mut_rptr(tcx,
5221 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5228 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5229 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5232 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5234 Err(s) => { tcx.sess.span_fatal(it.span, &s[]); }
5236 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5238 mutbl: ast::MutImmutable
5240 (1u, Vec::new(), td_ptr)
5243 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5247 ty::mk_struct(ccx.tcx, did,
5248 ccx.tcx.mk_substs(subst::Substs::empty()))),
5250 tcx.sess.span_fatal(it.span, &msg[]);
5257 ty::mk_ptr(tcx, ty::mt {
5259 mutbl: ast::MutImmutable
5263 ty::mk_ptr(tcx, ty::mt {
5265 mutbl: ast::MutImmutable
5268 "copy_memory" | "copy_nonoverlapping_memory" |
5269 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5272 ty::mk_ptr(tcx, ty::mt {
5274 mutbl: ast::MutMutable
5276 ty::mk_ptr(tcx, ty::mt {
5278 mutbl: ast::MutImmutable
5284 "set_memory" | "volatile_set_memory" => {
5287 ty::mk_ptr(tcx, ty::mt {
5289 mutbl: ast::MutMutable
5296 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5297 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5300 vec!( tcx.types.f32, tcx.types.i32 ),
5305 vec!( tcx.types.f64, tcx.types.i32 ),
5308 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5309 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5310 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5311 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5314 vec!( tcx.types.f32, tcx.types.f32 ),
5319 vec!( tcx.types.f64, tcx.types.f64 ),
5322 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5323 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5324 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5325 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5326 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5327 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5328 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5329 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5330 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5331 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5334 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5339 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5342 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5343 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5344 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5345 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5346 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5347 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5348 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5349 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5350 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5351 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5352 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5353 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5354 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5355 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5356 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5357 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5358 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5359 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5360 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5361 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5362 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5363 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5364 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5365 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5366 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5367 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5368 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5369 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5370 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5371 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5372 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5375 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5377 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5379 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5380 (0, vec!(tcx.types.i8, tcx.types.i8),
5381 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5383 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5384 (0, vec!(tcx.types.i16, tcx.types.i16),
5385 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5387 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5388 (0, vec!(tcx.types.i32, tcx.types.i32),
5389 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5391 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5392 (0, vec!(tcx.types.i64, tcx.types.i64),
5393 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5395 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5396 (0, vec!(tcx.types.u8, tcx.types.u8),
5397 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5399 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5400 (0, vec!(tcx.types.u16, tcx.types.u16),
5401 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5403 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5404 (0, vec!(tcx.types.u32, tcx.types.u32),
5405 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5407 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5408 (0, vec!(tcx.types.u64, tcx.types.u64),
5409 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5411 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5413 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5416 span_err!(tcx.sess, it.span, E0093,
5417 "unrecognized intrinsic function: `{}`", *other);
5421 (n_tps, inputs, ty::FnConverging(output))
5423 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5424 unsafety: ast::Unsafety::Unsafe,
5425 abi: abi::RustIntrinsic,
5426 sig: ty::Binder(FnSig {
5432 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5433 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5434 if i_n_tps != n_tps {
5435 span_err!(tcx.sess, it.span, E0094,
5436 "intrinsic has wrong number of type \
5437 parameters: found {}, expected {}",
5440 require_same_types(tcx,
5447 format!("intrinsic has wrong type: expected `{}`",
5448 ppaux::ty_to_string(ccx.tcx, fty))