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};
108 use util::common::{block_query, indenter, loop_query};
109 use util::ppaux::{self, Repr};
110 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
112 use std::cell::{Cell, Ref, RefCell};
113 use std::mem::replace;
115 use std::iter::repeat;
117 use syntax::{self, abi, attr};
118 use syntax::attr::AttrMetaMethods;
119 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
120 use syntax::ast_util::{self, local_def, PostExpansionMethod};
121 use syntax::codemap::{self, Span};
122 use syntax::owned_slice::OwnedSlice;
123 use syntax::parse::token;
124 use syntax::print::pprust;
126 use syntax::visit::{self, Visitor};
142 /// closures defined within the function. For example:
145 /// bar(move|| { ... })
148 /// Here, the function `foo()` and the closure passed to
149 /// `bar()` will each have their own `FnCtxt`, but they will
150 /// share the inherited fields.
151 pub struct Inherited<'a, 'tcx: 'a> {
152 infcx: infer::InferCtxt<'a, 'tcx>,
153 locals: RefCell<NodeMap<Ty<'tcx>>>,
154 param_env: ty::ParameterEnvironment<'a, 'tcx>,
157 node_types: RefCell<NodeMap<Ty<'tcx>>>,
158 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
159 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
160 method_map: MethodMap<'tcx>,
161 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
162 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
163 object_cast_map: ObjectCastMap<'tcx>,
165 // A mapping from each fn's id to its signature, with all bound
166 // regions replaced with free ones. Unlike the other tables, this
167 // one is never copied into the tcx: it is only used by regionck.
168 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
170 // Tracks trait obligations incurred during this function body.
171 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
174 /// When type-checking an expression, we propagate downward
175 /// whatever type hint we are able in the form of an `Expectation`.
177 enum Expectation<'tcx> {
178 /// We know nothing about what type this expression should have.
181 /// This expression should have the type given (or some subtype)
182 ExpectHasType(Ty<'tcx>),
184 /// This expression will be cast to the `Ty`
185 ExpectCastableToType(Ty<'tcx>),
187 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
188 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
189 ExpectRvalueLikeUnsized(Ty<'tcx>),
192 impl<'tcx> Expectation<'tcx> {
193 // Disregard "castable to" expectations because they
194 // can lead us astray. Consider for example `if cond
195 // {22} else {c} as u8` -- if we propagate the
196 // "castable to u8" constraint to 22, it will pick the
197 // type 22u8, which is overly constrained (c might not
198 // be a u8). In effect, the problem is that the
199 // "castable to" expectation is not the tightest thing
200 // we can say, so we want to drop it in this case.
201 // The tightest thing we can say is "must unify with
202 // else branch". Note that in the case of a "has type"
203 // constraint, this limitation does not hold.
205 // If the expected type is just a type variable, then don't use
206 // an expected type. Otherwise, we might write parts of the type
207 // when checking the 'then' block which are incompatible with the
209 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
211 ExpectHasType(ety) => {
212 let ety = fcx.infcx().shallow_resolve(ety);
213 if !ty::type_is_ty_var(ety) {
219 ExpectRvalueLikeUnsized(ety) => {
220 ExpectRvalueLikeUnsized(ety)
227 #[derive(Copy, Clone)]
228 pub struct UnsafetyState {
229 pub def: ast::NodeId,
230 pub unsafety: ast::Unsafety,
235 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
236 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
239 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
240 match self.unsafety {
241 // If this unsafe, then if the outer function was already marked as
242 // unsafe we shouldn't attribute the unsafe'ness to the block. This
243 // way the block can be warned about instead of ignoring this
244 // extraneous block (functions are never warned about).
245 ast::Unsafety::Unsafe if self.from_fn => *self,
248 let (unsafety, def) = match blk.rules {
249 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
250 ast::DefaultBlock => (unsafety, self.def),
252 UnsafetyState{ def: def,
260 /// Whether `check_binop` is part of an assignment or not.
261 /// Used to know whether we allow user overloads and to print
262 /// better messages on error.
264 enum IsBinopAssignment{
270 pub struct FnCtxt<'a, 'tcx: 'a> {
271 body_id: ast::NodeId,
273 // This flag is set to true if, during the writeback phase, we encounter
274 // a type error in this function.
275 writeback_errors: Cell<bool>,
277 // Number of errors that had been reported when we started
278 // checking this function. On exit, if we find that *more* errors
279 // have been reported, we will skip regionck and other work that
280 // expects the types within the function to be consistent.
281 err_count_on_creation: uint,
283 ret_ty: ty::FnOutput<'tcx>,
285 ps: RefCell<UnsafetyState>,
287 inh: &'a Inherited<'a, 'tcx>,
289 ccx: &'a CrateCtxt<'a, 'tcx>,
292 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
293 fn tcx(&self) -> &ty::ctxt<'tcx> {
296 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
297 let ty = self.node_ty(id);
298 self.resolve_type_vars_or_error(&ty)
300 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
301 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
302 self.resolve_type_vars_or_error(&ty)
304 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
305 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
306 traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
308 fn node_method_ty(&self, method_call: ty::MethodCall)
309 -> Option<Ty<'tcx>> {
310 self.inh.method_map.borrow()
312 .map(|method| method.ty)
313 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
315 fn node_method_origin(&self, method_call: ty::MethodCall)
316 -> Option<ty::MethodOrigin<'tcx>>
318 self.inh.method_map.borrow()
320 .map(|method| method.origin.clone())
322 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
323 &self.inh.adjustments
325 fn is_method_call(&self, id: ast::NodeId) -> bool {
326 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
328 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
329 self.param_env().temporary_scope(rvalue_id)
331 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
332 self.inh.upvar_borrow_map.borrow().get(&upvar_id).cloned()
334 fn capture_mode(&self, closure_expr_id: ast::NodeId)
335 -> ast::CaptureClause {
336 self.ccx.tcx.capture_mode(closure_expr_id)
340 impl<'a, 'tcx> ty::UnboxedClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
341 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
345 fn unboxed_closure_kind(&self,
347 -> ty::UnboxedClosureKind
349 self.inh.unboxed_closures.borrow()[def_id].kind
352 fn unboxed_closure_type(&self,
354 substs: &subst::Substs<'tcx>)
355 -> ty::ClosureTy<'tcx>
357 self.inh.unboxed_closures.borrow()[def_id].closure_type.subst(self.tcx(), substs)
360 fn unboxed_closure_upvars(&self,
362 substs: &Substs<'tcx>)
363 -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
365 ty::unboxed_closure_upvars(self, def_id, substs)
369 impl<'a, 'tcx> Inherited<'a, 'tcx> {
370 fn new(tcx: &'a ty::ctxt<'tcx>,
371 param_env: ty::ParameterEnvironment<'a, 'tcx>)
372 -> Inherited<'a, 'tcx> {
374 infcx: infer::new_infer_ctxt(tcx),
375 locals: RefCell::new(NodeMap()),
376 param_env: param_env,
377 node_types: RefCell::new(NodeMap()),
378 item_substs: RefCell::new(NodeMap()),
379 adjustments: RefCell::new(NodeMap()),
380 method_map: RefCell::new(FnvHashMap()),
381 object_cast_map: RefCell::new(NodeMap()),
382 upvar_borrow_map: RefCell::new(FnvHashMap()),
383 unboxed_closures: RefCell::new(DefIdMap()),
384 fn_sig_map: RefCell::new(NodeMap()),
385 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
389 fn normalize_associated_types_in<T>(&self,
390 typer: &ty::UnboxedClosureTyper<'tcx>,
392 body_id: ast::NodeId,
395 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
397 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
398 assoc::normalize_associated_types_in(&self.infcx,
400 &mut *fulfillment_cx, span,
407 // Used by check_const and check_enum_variants
408 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
409 inh: &'a Inherited<'a, 'tcx>,
410 rty: ty::FnOutput<'tcx>,
411 body_id: ast::NodeId)
412 -> FnCtxt<'a, 'tcx> {
415 writeback_errors: Cell::new(false),
416 err_count_on_creation: ccx.tcx.sess.err_count(),
418 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
424 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
425 -> Inherited<'a, 'tcx> {
426 // It's kind of a kludge to manufacture a fake function context
427 // and statement context, but we might as well do write the code only once
428 let param_env = ty::empty_parameter_environment(ccx.tcx);
429 Inherited::new(ccx.tcx, param_env)
432 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
434 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
435 fn visit_item(&mut self, i: &ast::Item) {
436 check_item(self.ccx, i);
437 visit::walk_item(self, i);
440 fn visit_ty(&mut self, t: &ast::Ty) {
442 ast::TyFixedLengthVec(_, ref expr) => {
443 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
448 visit::walk_ty(self, t);
452 pub fn check_item_types(ccx: &CrateCtxt) {
453 let krate = ccx.tcx.map.krate();
454 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
455 visit::walk_crate(&mut visit, krate);
457 // If types are not well-formed, it leads to all manner of errors
458 // downstream, so stop reporting errors at this point.
459 ccx.tcx.sess.abort_if_errors();
461 let mut visit = CheckItemTypesVisitor { ccx: ccx };
462 visit::walk_crate(&mut visit, krate);
464 ccx.tcx.sess.abort_if_errors();
467 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
472 param_env: ty::ParameterEnvironment<'a, 'tcx>) {
474 ty::ty_bare_fn(_, ref fn_ty) => {
475 let inh = Inherited::new(ccx.tcx, param_env);
477 // Compute the fty from point of view of inside fn.
479 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
481 liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig);
483 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
485 let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
486 decl, id, body, &inh);
488 vtable::select_all_fcx_obligations_or_error(&fcx);
489 upvar::closure_analyze_fn(&fcx, id, decl, body);
490 regionck::regionck_fn(&fcx, id, decl, body);
491 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
493 _ => ccx.tcx.sess.impossible_case(body.span,
494 "check_bare_fn: function type expected")
498 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
499 fcx: &'a FnCtxt<'a, 'tcx>
502 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
503 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
506 // infer the variable's type
507 let var_ty = self.fcx.infcx().next_ty_var();
508 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
512 // take type that the user specified
513 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
520 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
521 // Add explicitly-declared locals.
522 fn visit_local(&mut self, local: &ast::Local) {
523 let o_ty = match local.ty {
524 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
527 self.assign(local.span, local.id, o_ty);
528 debug!("Local variable {} is assigned type {}",
529 self.fcx.pat_to_string(&*local.pat),
530 self.fcx.infcx().ty_to_string(
531 self.fcx.inh.locals.borrow()[local.id].clone()));
532 visit::walk_local(self, local);
535 // Add pattern bindings.
536 fn visit_pat(&mut self, p: &ast::Pat) {
537 if let ast::PatIdent(_, ref path1, _) = p.node {
538 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
539 let var_ty = self.assign(p.span, p.id, None);
541 self.fcx.require_type_is_sized(var_ty, p.span,
542 traits::VariableType(p.id));
544 debug!("Pattern binding {} is assigned to {} with type {}",
545 token::get_ident(path1.node),
546 self.fcx.infcx().ty_to_string(
547 self.fcx.inh.locals.borrow()[p.id].clone()),
548 var_ty.repr(self.fcx.tcx()));
551 visit::walk_pat(self, p);
554 fn visit_block(&mut self, b: &ast::Block) {
555 // non-obvious: the `blk` variable maps to region lb, so
556 // we have to keep this up-to-date. This
557 // is... unfortunate. It'd be nice to not need this.
558 visit::walk_block(self, b);
561 // Since an expr occurs as part of the type fixed size arrays we
562 // need to record the type for that node
563 fn visit_ty(&mut self, t: &ast::Ty) {
565 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
566 self.visit_ty(&**ty);
567 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
569 _ => visit::walk_ty(self, t)
573 // Don't descend into fns and items
574 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
575 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
576 fn visit_item(&mut self, _: &ast::Item) { }
580 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
581 /// body and returns the function context used for that purpose, since in the case of a fn item
582 /// there is still a bit more to do.
585 /// * inherited: other fields inherited from the enclosing fn (if any)
586 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
587 unsafety: ast::Unsafety,
588 unsafety_id: ast::NodeId,
589 fn_sig: &ty::FnSig<'tcx>,
593 inherited: &'a Inherited<'a, 'tcx>)
597 let err_count_on_creation = tcx.sess.err_count();
599 let arg_tys = &fn_sig.inputs[];
600 let ret_ty = fn_sig.output;
602 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
607 // Create the function context. This is either derived from scratch or,
608 // in the case of function expressions, based on the outer context.
611 writeback_errors: Cell::new(false),
612 err_count_on_creation: err_count_on_creation,
614 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
619 // Remember return type so that regionck can access it later.
620 let mut fn_sig_tys: Vec<Ty> =
625 if let ty::FnConverging(ret_ty) = ret_ty {
626 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
627 fn_sig_tys.push(ret_ty);
630 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
632 fn_sig_tys.repr(tcx));
634 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
637 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
639 // Add formal parameters.
640 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
641 // Create type variables for each argument.
642 pat_util::pat_bindings(
645 |_bm, pat_id, sp, _path| {
646 let var_ty = visit.assign(sp, pat_id, None);
647 fcx.require_type_is_sized(var_ty, sp,
648 traits::VariableType(pat_id));
651 // Check the pattern.
654 map: pat_id_map(&tcx.def_map, &*input.pat),
656 _match::check_pat(&pcx, &*input.pat, *arg_ty);
659 visit.visit_block(body);
662 check_block_with_expected(&fcx, body, match ret_ty {
663 ty::FnConverging(result_type) => ExpectHasType(result_type),
664 ty::FnDiverging => NoExpectation
667 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
668 fcx.write_ty(input.id, *arg);
674 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
677 check_representable(tcx, span, id, "struct");
678 check_instantiable(tcx, span, id);
680 if ty::lookup_simd(tcx, local_def(id)) {
681 check_simd(tcx, span, id);
685 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
686 debug!("check_item(it.id={}, it.ident={})",
688 ty::item_path_str(ccx.tcx, local_def(it.id)));
689 let _indenter = indenter();
692 ast::ItemStatic(_, _, ref e) |
693 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
694 ast::ItemEnum(ref enum_definition, _) => {
695 check_enum_variants(ccx,
697 &enum_definition.variants[],
700 ast::ItemFn(ref decl, _, _, _, ref body) => {
701 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
702 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
703 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
705 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
706 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
708 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
710 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
711 Some(impl_trait_ref) => {
712 check_impl_items_against_trait(ccx,
715 impl_items.as_slice());
720 for impl_item in impl_items.iter() {
722 ast::MethodImplItem(ref m) => {
723 check_method_body(ccx, &impl_pty.generics, &**m);
725 ast::TypeImplItem(_) => {
726 // Nothing to do here.
732 ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
733 check_trait_on_unimplemented(ccx, generics, it);
734 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
735 for trait_method in trait_methods.iter() {
736 match *trait_method {
737 RequiredMethod(..) => {
738 // Nothing to do, since required methods don't have
741 ProvidedMethod(ref m) => {
742 check_method_body(ccx, &trait_def.generics, &**m);
744 TypeTraitItem(_) => {
750 ast::ItemStruct(..) => {
751 check_struct(ccx, it.id, it.span);
753 ast::ItemTy(ref t, ref generics) => {
754 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
755 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
757 ast::ItemForeignMod(ref m) => {
758 if m.abi == abi::RustIntrinsic {
759 for item in m.items.iter() {
760 check_intrinsic_type(ccx, &**item);
763 for item in m.items.iter() {
764 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
765 if !pty.generics.types.is_empty() {
766 span_err!(ccx.tcx.sess, item.span, E0044,
767 "foreign items may not have type parameters");
770 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
771 if fn_decl.variadic && m.abi != abi::C {
772 span_err!(ccx.tcx.sess, item.span, E0045,
773 "variadic function must have C calling convention");
779 _ => {/* nothing to do */ }
783 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
784 generics: &ast::Generics,
786 if let Some(ref attr) = item.attrs.iter().find(|&: a| {
787 a.check_name("rustc_on_unimplemented")
789 if let Some(ref istring) = attr.value_str() {
790 let mut parser = Parser::new(istring.get());
791 let types = generics.ty_params.as_slice();
792 for token in parser {
794 Piece::String(_) => (), // Normal string, no need to check it
795 Piece::NextArgument(a) => match a.position {
796 // `{Self}` is allowed
797 Position::ArgumentNamed(s) if s == "Self" => (),
798 // So is `{A}` if A is a type parameter
799 Position::ArgumentNamed(s) => match types.iter().find(|t| {
800 t.ident.as_str() == s
804 ccx.tcx.sess.span_err(attr.span,
805 format!("there is no type parameter \
807 s, item.ident.as_str())
811 // `{:1}` and `{}` are not to be used
812 Position::ArgumentIs(_) | Position::ArgumentNext => {
813 ccx.tcx.sess.span_err(attr.span,
814 "only named substitution \
815 parameters are allowed");
821 ccx.tcx.sess.span_err(attr.span,
822 "this attribute must have a value, \
823 eg `#[rustc_on_unimplemented = \"foo\"]`")
828 /// Type checks a method body.
832 /// * `item_generics`: generics defined on the impl/trait that contains
834 /// * `self_bound`: bound for the `Self` type parameter, if any
835 /// * `method`: the method definition
836 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
837 item_generics: &ty::Generics<'tcx>,
838 method: &ast::Method) {
839 debug!("check_method_body(item_generics={}, method.id={})",
840 item_generics.repr(ccx.tcx),
842 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
844 let fty = ty::node_id_to_type(ccx.tcx, method.id);
845 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
848 &*method.pe_fn_decl(),
855 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
857 impl_trait_ref: &ty::TraitRef<'tcx>,
858 impl_items: &[ast::ImplItem]) {
859 // Locate trait methods
861 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
863 // Check existing impl methods to see if they are both present in trait
864 // and compatible with trait signature
865 for impl_item in impl_items.iter() {
867 ast::MethodImplItem(ref impl_method) => {
868 let impl_method_def_id = local_def(impl_method.id);
869 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
872 // If this is an impl of a trait method, find the
873 // corresponding method definition in the trait.
874 let opt_trait_method_ty =
876 .find(|ti| ti.name() == impl_item_ty.name());
877 match opt_trait_method_ty {
878 Some(trait_method_ty) => {
879 match (trait_method_ty, &impl_item_ty) {
880 (&ty::MethodTraitItem(ref trait_method_ty),
881 &ty::MethodTraitItem(ref impl_method_ty)) => {
882 compare_impl_method(ccx.tcx,
885 impl_method.pe_body().id,
890 // This is span_bug as it should have already been
891 // caught in resolve.
894 format!("item `{}` is of a different kind from its trait `{}`",
895 token::get_name(impl_item_ty.name()),
896 impl_trait_ref.repr(tcx)).as_slice());
901 // This is span_bug as it should have already been
902 // caught in resolve.
905 format!("method `{}` is not a member of trait `{}`",
906 token::get_name(impl_item_ty.name()),
907 impl_trait_ref.repr(tcx)).as_slice());
911 ast::TypeImplItem(ref typedef) => {
912 let typedef_def_id = local_def(typedef.id);
913 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
916 // If this is an impl of an associated type, find the
917 // corresponding type definition in the trait.
918 let opt_associated_type =
920 .find(|ti| ti.name() == typedef_ty.name());
921 match opt_associated_type {
922 Some(associated_type) => {
923 match (associated_type, &typedef_ty) {
924 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
926 // This is `span_bug` as it should have
927 // already been caught in resolve.
930 format!("item `{}` is of a different kind from its trait `{}`",
931 token::get_name(typedef_ty.name()),
932 impl_trait_ref.repr(tcx)).as_slice());
937 // This is `span_bug` as it should have already been
938 // caught in resolve.
942 "associated type `{}` is not a member of \
944 token::get_name(typedef_ty.name()),
945 impl_trait_ref.repr(tcx)).as_slice());
952 // Check for missing items from trait
953 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
954 let mut missing_methods = Vec::new();
955 for trait_item in trait_items.iter() {
957 ty::MethodTraitItem(ref trait_method) => {
959 impl_items.iter().any(|ii| {
961 ast::MethodImplItem(ref m) => {
962 m.pe_ident().name == trait_method.name
964 ast::TypeImplItem(_) => false,
968 provided_methods.iter().any(|m| m.name == trait_method.name);
969 if !is_implemented && !is_provided {
970 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
973 ty::TypeTraitItem(ref associated_type) => {
974 let is_implemented = impl_items.iter().any(|ii| {
976 ast::TypeImplItem(ref typedef) => {
977 typedef.ident.name == associated_type.name
979 ast::MethodImplItem(_) => false,
983 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
989 if !missing_methods.is_empty() {
990 span_err!(tcx.sess, impl_span, E0046,
991 "not all trait items implemented, missing: {}",
992 missing_methods.connect(", "));
996 fn check_cast(fcx: &FnCtxt,
997 cast_expr: &ast::Expr,
1000 let id = cast_expr.id;
1001 let span = cast_expr.span;
1003 // Find the type of `e`. Supply hints based on the type we are casting to,
1005 let t_1 = fcx.to_ty(t);
1006 let t_1 = structurally_resolved_type(fcx, span, t_1);
1008 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1010 let t_e = fcx.expr_ty(e);
1012 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1013 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1015 if ty::type_is_error(t_e) {
1016 fcx.write_error(id);
1020 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1021 let tstr = fcx.infcx().ty_to_string(t_1);
1022 fcx.type_error_message(span, |actual| {
1023 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1026 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1027 let mtstr = match mt {
1028 ast::MutMutable => "mut ",
1029 ast::MutImmutable => ""
1031 if ty::type_is_trait(t_1) {
1032 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1034 span_help!(fcx.tcx().sess, span,
1035 "consider using an implicit coercion to `&{}{}` instead",
1039 ty::ty_uniq(..) => {
1040 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1043 span_help!(fcx.tcx().sess, e.span,
1044 "consider using a box or reference as appropriate");
1047 fcx.write_error(id);
1051 if ty::type_is_trait(t_1) {
1052 // This will be looked up later on.
1053 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1054 fcx.write_ty(id, t_1);
1058 let t_1 = structurally_resolved_type(fcx, span, t_1);
1059 let t_e = structurally_resolved_type(fcx, span, t_e);
1061 if ty::type_is_nil(t_e) {
1062 fcx.type_error_message(span, |actual| {
1063 format!("cast from nil: `{}` as `{}`",
1065 fcx.infcx().ty_to_string(t_1))
1067 } else if ty::type_is_nil(t_1) {
1068 fcx.type_error_message(span, |actual| {
1069 format!("cast to nil: `{}` as `{}`",
1071 fcx.infcx().ty_to_string(t_1))
1075 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1077 let t_1_is_scalar = ty::type_is_scalar(t_1);
1078 let t_1_is_char = ty::type_is_char(t_1);
1079 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1080 let t_1_is_float = ty::type_is_floating_point(t_1);
1082 // casts to scalars other than `char` and `bare fn` are trivial
1083 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1084 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1085 demand::coerce(fcx, e.span, t_1, &*e);
1086 } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1087 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1088 fcx.type_error_message(span, |actual| {
1089 format!("illegal cast; cast through an \
1090 integer first: `{}` as `{}`",
1092 fcx.infcx().ty_to_string(t_1))
1095 // casts from C-like enums are allowed
1096 } else if t_1_is_char {
1097 let t_e = fcx.infcx().shallow_resolve(t_e);
1098 if t_e.sty != ty::ty_uint(ast::TyU8) {
1099 fcx.type_error_message(span, |actual| {
1100 format!("only `u8` can be cast as \
1101 `char`, not `{}`", actual)
1104 } else if t_1.sty == ty::ty_bool {
1105 span_err!(fcx.tcx().sess, span, E0054,
1106 "cannot cast as `bool`, compare with zero instead");
1107 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1108 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1109 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1111 ty::ty_vec(_, Some(_)) => {}
1114 if ty::type_needs_infer(t2) {
1115 // This prevents this special case from going off when casting
1116 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1121 let el = ty::sequence_element_type(fcx.tcx(), t1);
1122 infer::mk_eqty(fcx.infcx(),
1129 // Due to the limitations of LLVM global constants,
1130 // region pointers end up pointing at copies of
1131 // vector elements instead of the original values.
1132 // To allow unsafe pointers to work correctly, we
1133 // need to special-case obtaining an unsafe pointer
1134 // from a region pointer to a vector.
1136 /* this cast is only allowed from &[T, ..n] to *T or
1138 match (&t_e.sty, &t_1.sty) {
1139 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1140 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1141 if types_compatible(fcx, e.span, mt1, mt2) => {
1142 /* this case is allowed */
1145 demand::coerce(fcx, e.span, t_1, &*e);
1148 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1150 If more type combinations should be supported than are
1151 supported here, then file an enhancement issue and
1152 record the issue number in this comment.
1154 fcx.type_error_message(span, |actual| {
1155 format!("non-scalar cast: `{}` as `{}`",
1157 fcx.infcx().ty_to_string(t_1))
1159 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1160 fcx.type_error_message(span, |actual| {
1161 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1164 fcx.infcx().ty_to_string(t_1))
1168 fcx.write_ty(id, t_1);
1171 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1172 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1174 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1175 ty::lookup_item_type(self.tcx(), id)
1178 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1179 ty::lookup_trait_def(self.tcx(), id)
1182 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1183 Some(&self.inh.param_env.free_substs)
1186 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1187 self.infcx().next_ty_var()
1190 fn projected_ty_from_poly_trait_ref(&self,
1192 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1193 item_name: ast::Name)
1196 let (trait_ref, _) =
1197 self.infcx().replace_late_bound_regions_with_fresh_var(
1199 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1202 self.normalize_associated_type(span, trait_ref, item_name)
1205 fn projected_ty(&self,
1207 trait_ref: Rc<ty::TraitRef<'tcx>>,
1208 item_name: ast::Name)
1211 self.normalize_associated_type(span, trait_ref, item_name)
1215 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1216 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1218 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1222 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1226 pub fn sess(&self) -> &Session {
1230 pub fn err_count_since_creation(&self) -> uint {
1231 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1234 /// Resolves all type variables in `t` and then, if any were left
1235 /// unresolved, substitutes an error type. This is used after the
1236 /// main checking when doing a second pass before writeback. The
1237 /// justification is that writeback will produce an error for
1238 /// these unconstrained type variables.
1239 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1240 let t = self.infcx().resolve_type_vars_if_possible(t);
1241 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1244 pub fn tag(&self) -> String {
1245 format!("{:?}", self as *const FnCtxt)
1248 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1249 match self.inh.locals.borrow().get(&nid) {
1252 self.tcx().sess.span_bug(
1254 &format!("no type for local variable {}",
1260 /// Apply "fallbacks" to some types
1261 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1262 pub fn default_type_parameters(&self) {
1263 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1264 for (_, &mut ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1265 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1266 if self.infcx().type_var_diverges(resolved) {
1267 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1269 match self.infcx().type_is_unconstrained_numeric(resolved) {
1270 UnconstrainedInt => {
1271 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1273 UnconstrainedFloat => {
1274 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1283 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1284 debug!("write_ty({}, {}) in fcx {}",
1285 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1286 self.inh.node_types.borrow_mut().insert(node_id, ty);
1289 pub fn write_object_cast(&self,
1291 trait_ref: ty::PolyTraitRef<'tcx>) {
1292 debug!("write_object_cast key={} trait_ref={}",
1293 key, trait_ref.repr(self.tcx()));
1294 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1297 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1298 if !substs.substs.is_noop() {
1299 debug!("write_substs({}, {}) in fcx {}",
1301 substs.repr(self.tcx()),
1304 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1308 pub fn write_autoderef_adjustment(&self,
1309 node_id: ast::NodeId,
1312 if derefs == 0 { return; }
1313 self.write_adjustment(
1316 ty::AdjustDerefRef(ty::AutoDerefRef {
1322 pub fn write_adjustment(&self,
1323 node_id: ast::NodeId,
1325 adj: ty::AutoAdjustment<'tcx>) {
1326 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1328 if adj.is_identity() {
1332 // Careful: adjustments can imply trait obligations if we are
1333 // casting from a concrete type to an object type. I think
1334 // it'd probably be nicer to move the logic that creates the
1335 // obligation into the code that creates the adjustment, but
1336 // that's a bit awkward, so instead we go digging and pull the
1337 // obligation out here.
1338 self.register_adjustment_obligations(span, &adj);
1339 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1342 /// Basically whenever we are converting from a type scheme into
1343 /// the fn body space, we always want to normalize associated
1344 /// types as well. This function combines the two.
1345 fn instantiate_type_scheme<T>(&self,
1347 substs: &Substs<'tcx>,
1350 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1352 let value = value.subst(self.tcx(), substs);
1353 let result = self.normalize_associated_types_in(span, &value);
1354 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1355 value.repr(self.tcx()),
1356 substs.repr(self.tcx()),
1357 result.repr(self.tcx()));
1361 /// As `instantiate_type_scheme`, but for the bounds found in a
1362 /// generic type scheme.
1363 fn instantiate_bounds(&self,
1365 substs: &Substs<'tcx>,
1366 generics: &ty::Generics<'tcx>)
1367 -> ty::GenericBounds<'tcx>
1370 predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
1375 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1376 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1378 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1381 fn normalize_associated_type(&self,
1383 trait_ref: Rc<ty::TraitRef<'tcx>>,
1384 item_name: ast::Name)
1387 let cause = traits::ObligationCause::new(span,
1389 traits::ObligationCauseCode::MiscObligation);
1390 self.inh.fulfillment_cx
1392 .normalize_projection_type(self.infcx(),
1395 trait_ref: trait_ref,
1396 item_name: item_name,
1401 fn register_adjustment_obligations(&self,
1403 adj: &ty::AutoAdjustment<'tcx>) {
1405 ty::AdjustReifyFnPointer(..) => {
1407 ty::AdjustDerefRef(ref d_r) => {
1410 self.register_autoref_obligations(span, a_r);
1418 fn register_autoref_obligations(&self,
1420 autoref: &ty::AutoRef<'tcx>) {
1422 ty::AutoUnsize(ref unsize) => {
1423 self.register_unsize_obligations(span, unsize);
1425 ty::AutoPtr(_, _, None) |
1426 ty::AutoUnsafe(_, None) => {
1428 ty::AutoPtr(_, _, Some(ref a_r)) |
1429 ty::AutoUnsafe(_, Some(ref a_r)) => {
1430 self.register_autoref_obligations(span, &**a_r)
1432 ty::AutoUnsizeUniq(ref unsize) => {
1433 self.register_unsize_obligations(span, unsize);
1438 fn register_unsize_obligations(&self,
1440 unsize: &ty::UnsizeKind<'tcx>) {
1441 debug!("register_unsize_obligations: unsize={:?}", unsize);
1444 ty::UnsizeLength(..) => {}
1445 ty::UnsizeStruct(ref u, _) => {
1446 self.register_unsize_obligations(span, &**u)
1448 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1449 vtable::check_object_safety(self.tcx(), ty_trait, span);
1451 // If the type is `Foo+'a`, ensures that the type
1452 // being cast to `Foo+'a` implements `Foo`:
1453 vtable::register_object_cast_obligations(self,
1458 // If the type is `Foo+'a`, ensures that the type
1459 // being cast to `Foo+'a` outlives `'a`:
1460 let cause = traits::ObligationCause { span: span,
1461 body_id: self.body_id,
1462 code: traits::ObjectCastObligation(self_ty) };
1463 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1468 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1469 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1470 /// Registers any trait obligations specified on `def_id` at the same time.
1472 /// Note that function is only intended to be used with types (notably, not fns). This is
1473 /// because it doesn't do any instantiation of late-bound regions.
1474 pub fn instantiate_type(&self,
1477 -> TypeAndSubsts<'tcx>
1480 ty::lookup_item_type(self.tcx(), def_id);
1482 self.infcx().fresh_substs_for_generics(
1484 &type_scheme.generics);
1486 self.instantiate_bounds(span, &substs, &type_scheme.generics);
1487 self.add_obligations_for_parameters(
1488 traits::ObligationCause::new(
1491 traits::ItemObligation(def_id)),
1494 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1502 /// Returns the type that this AST path refers to. If the path has no type
1503 /// parameters and the corresponding type has type parameters, fresh type
1504 /// and/or region variables are substituted.
1506 /// This is used when checking the constructor in struct literals.
1507 fn instantiate_struct_literal_ty(&self,
1510 -> TypeAndSubsts<'tcx>
1512 let tcx = self.tcx();
1514 let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
1517 generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1519 let needs_defaults =
1521 path.segments.iter().all(|s| s.parameters.is_empty());
1523 let substs = if needs_defaults {
1525 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1527 self.infcx().region_vars_for_defs(path.span,
1528 generics.regions.get_slice(TypeSpace));
1529 Substs::new_type(tps, rps)
1531 astconv::ast_path_substs_for_ty(self, self, &generics, path)
1534 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1536 TypeAndSubsts { substs: substs, ty: ty }
1539 pub fn write_nil(&self, node_id: ast::NodeId) {
1540 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1542 pub fn write_error(&self, node_id: ast::NodeId) {
1543 self.write_ty(node_id, self.tcx().types.err);
1546 pub fn require_type_meets(&self,
1549 code: traits::ObligationCauseCode<'tcx>,
1550 bound: ty::BuiltinBound)
1552 self.register_builtin_bound(
1555 traits::ObligationCause::new(span, self.body_id, code));
1558 pub fn require_type_is_sized(&self,
1561 code: traits::ObligationCauseCode<'tcx>)
1563 self.require_type_meets(ty, span, code, ty::BoundSized);
1566 pub fn require_expr_have_sized_type(&self,
1568 code: traits::ObligationCauseCode<'tcx>)
1570 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1573 pub fn type_is_known_to_be_sized(&self,
1578 traits::type_known_to_meet_builtin_bound(self.infcx(),
1585 pub fn register_builtin_bound(&self,
1587 builtin_bound: ty::BuiltinBound,
1588 cause: traits::ObligationCause<'tcx>)
1590 self.inh.fulfillment_cx.borrow_mut()
1591 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1594 pub fn register_predicate(&self,
1595 obligation: traits::PredicateObligation<'tcx>)
1597 debug!("register_predicate({})",
1598 obligation.repr(self.tcx()));
1599 self.inh.fulfillment_cx
1601 .register_predicate_obligation(self.infcx(), obligation);
1604 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1605 let t = ast_ty_to_ty(self, self, ast_t);
1607 let mut bounds_checker = wf::BoundsChecker::new(self,
1609 CodeExtent::from_node_id(self.body_id),
1611 bounds_checker.check_ty(t);
1616 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1617 pat.repr(self.tcx())
1620 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1621 match self.inh.node_types.borrow().get(&ex.id) {
1624 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1630 /// Apply `adjustment` to the type of `expr`
1631 pub fn adjust_expr_ty(&self,
1633 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1636 let raw_ty = self.expr_ty(expr);
1637 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1638 ty::adjust_ty(self.tcx(),
1643 |method_call| self.inh.method_map.borrow()
1645 .map(|method| method.ty))
1648 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1649 match self.inh.node_types.borrow().get(&id) {
1651 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1653 self.tcx().sess.bug(
1654 &format!("no type for node {}: {} in fcx {}",
1655 id, self.tcx().map.node_to_string(id),
1661 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1662 self.inh.item_substs.borrow()
1665 pub fn opt_node_ty_substs<F>(&self,
1668 F: FnOnce(&ty::ItemSubsts<'tcx>),
1670 match self.inh.item_substs.borrow().get(&id) {
1676 pub fn mk_subty(&self,
1677 a_is_expected: bool,
1678 origin: infer::TypeOrigin,
1681 -> Result<(), ty::type_err<'tcx>> {
1682 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1685 pub fn mk_assignty(&self,
1689 -> Result<(), ty::type_err<'tcx>> {
1690 match infer::mk_coercety(self.infcx(),
1692 infer::ExprAssignable(expr.span),
1696 Err(ref e) => Err((*e)),
1697 Ok(Some(adjustment)) => {
1698 self.write_adjustment(expr.id, expr.span, adjustment);
1704 pub fn mk_eqty(&self,
1705 a_is_expected: bool,
1706 origin: infer::TypeOrigin,
1709 -> Result<(), ty::type_err<'tcx>> {
1710 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1713 pub fn mk_subr(&self,
1714 origin: infer::SubregionOrigin<'tcx>,
1717 infer::mk_subr(self.infcx(), origin, sub, sup)
1720 pub fn type_error_message<M>(&self,
1723 actual_ty: Ty<'tcx>,
1724 err: Option<&ty::type_err<'tcx>>) where
1725 M: FnOnce(String) -> String,
1727 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1730 pub fn report_mismatched_types(&self,
1734 err: &ty::type_err<'tcx>) {
1735 self.infcx().report_mismatched_types(sp, e, a, err)
1738 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1739 /// outlive the region `r`.
1740 pub fn register_region_obligation(&self,
1743 cause: traits::ObligationCause<'tcx>)
1745 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1746 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1749 pub fn add_default_region_param_bounds(&self,
1750 substs: &Substs<'tcx>,
1753 for &ty in substs.types.iter() {
1754 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1755 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1756 traits::MiscObligation);
1757 self.register_region_obligation(ty, default_bound, cause);
1761 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1762 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1763 /// trait/region obligations.
1765 /// For example, if there is a function:
1768 /// fn foo<'a,T:'a>(...)
1771 /// and a reference:
1777 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1778 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1779 pub fn add_obligations_for_parameters(&self,
1780 cause: traits::ObligationCause<'tcx>,
1781 generic_bounds: &ty::GenericBounds<'tcx>)
1783 assert!(!generic_bounds.has_escaping_regions());
1785 debug!("add_obligations_for_parameters(generic_bounds={})",
1786 generic_bounds.repr(self.tcx()));
1788 let obligations = traits::predicates_for_generics(self.tcx(),
1792 obligations.map_move(|o| self.register_predicate(o));
1795 // Only for fields! Returns <none> for methods>
1796 // Indifferent to privacy flags
1797 pub fn lookup_field_ty(&self,
1799 class_id: ast::DefId,
1800 items: &[ty::field_ty],
1801 fieldname: ast::Name,
1802 substs: &subst::Substs<'tcx>)
1805 let o_field = items.iter().find(|f| f.name == fieldname);
1806 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1807 .map(|t| self.normalize_associated_types_in(span, &t))
1810 pub fn lookup_tup_field_ty(&self,
1812 class_id: ast::DefId,
1813 items: &[ty::field_ty],
1815 substs: &subst::Substs<'tcx>)
1818 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1819 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1820 .map(|t| self.normalize_associated_types_in(span, &t))
1824 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1825 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1826 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1829 fn anon_regions(&self, span: Span, count: uint)
1830 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1831 Ok(range(0, count).map(|_| {
1832 self.infcx().next_region_var(infer::MiscVariable(span))
1837 #[derive(Copy, Show, PartialEq, Eq)]
1838 pub enum LvaluePreference {
1843 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1844 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1846 /// Note: this method does not modify the adjustments table. The caller is responsible for
1847 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1848 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1851 opt_expr: Option<&ast::Expr>,
1852 mut lvalue_pref: LvaluePreference,
1854 -> (Ty<'tcx>, uint, Option<T>)
1855 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1857 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1858 base_ty.repr(fcx.tcx()),
1859 opt_expr.repr(fcx.tcx()),
1862 let mut t = base_ty;
1863 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1864 let resolved_t = structurally_resolved_type(fcx, sp, t);
1866 if ty::type_is_error(resolved_t) {
1867 return (resolved_t, autoderefs, None);
1870 match should_stop(resolved_t, autoderefs) {
1871 Some(x) => return (resolved_t, autoderefs, Some(x)),
1875 // Otherwise, deref if type is derefable:
1876 let mt = match ty::deref(resolved_t, false) {
1877 Some(mt) => Some(mt),
1879 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1881 // Super subtle: it might seem as though we should
1882 // pass `opt_expr` to `try_overloaded_deref`, so that
1883 // the (implicit) autoref of using an overloaded deref
1884 // would get added to the adjustment table. However we
1885 // do not do that, because it's kind of a
1886 // "meta-adjustment" -- instead, we just leave it
1887 // unrecorded and know that there "will be" an
1888 // autoref. regionck and other bits of the code base,
1889 // when they encounter an overloaded autoderef, have
1890 // to do some reconstructive surgery. This is a pretty
1891 // complex mess that is begging for a proper MIR.
1892 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1898 if mt.mutbl == ast::MutImmutable {
1899 lvalue_pref = NoPreference;
1902 None => return (resolved_t, autoderefs, None)
1906 // We've reached the recursion limit, error gracefully.
1907 span_err!(fcx.tcx().sess, sp, E0055,
1908 "reached the recursion limit while auto-dereferencing {}",
1909 base_ty.repr(fcx.tcx()));
1910 (fcx.tcx().types.err, 0, None)
1913 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1915 method_call: Option<MethodCall>,
1916 base_expr: Option<&ast::Expr>,
1918 lvalue_pref: LvaluePreference)
1919 -> Option<ty::mt<'tcx>>
1921 // Try DerefMut first, if preferred.
1922 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1923 (PreferMutLvalue, Some(trait_did)) => {
1924 method::lookup_in_trait(fcx, span, base_expr,
1925 token::intern("deref_mut"), trait_did,
1931 // Otherwise, fall back to Deref.
1932 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1933 (None, Some(trait_did)) => {
1934 method::lookup_in_trait(fcx, span, base_expr,
1935 token::intern("deref"), trait_did,
1938 (method, _) => method
1941 make_overloaded_lvalue_return_type(fcx, method_call, method)
1944 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
1945 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
1946 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
1947 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1948 method_call: Option<MethodCall>,
1949 method: Option<MethodCallee<'tcx>>)
1950 -> Option<ty::mt<'tcx>>
1954 let ref_ty = // invoked methods have all LB regions instantiated
1955 ty::assert_no_late_bound_regions(
1956 fcx.tcx(), &ty::ty_fn_ret(method.ty));
1958 Some(method_call) => {
1959 fcx.inh.method_map.borrow_mut().insert(method_call,
1965 ty::FnConverging(ref_ty) => {
1966 ty::deref(ref_ty, true)
1968 ty::FnDiverging => {
1969 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
1977 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1978 base_expr: &ast::Expr,
1980 lvalue_pref: LvaluePreference,
1983 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
1985 // FIXME(#18741) -- this is almost but not quite the same as the
1986 // autoderef that normal method probing does. They could likely be
1989 let (ty, autoderefs, final_mt) =
1990 autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
1991 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
1992 step(adj_ty, autoderefref)
1995 if final_mt.is_some() {
1999 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2000 // do a final unsized coercion to yield [T].
2002 ty::ty_vec(element_ty, Some(n)) => {
2003 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2004 let autoderefref = ty::AutoDerefRef {
2005 autoderefs: autoderefs,
2006 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2008 step(adjusted_ty, autoderefref)
2016 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2017 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2018 /// This loop implements one step in that search; the autoderef loop is implemented by
2019 /// `autoderef_for_index`.
2020 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2021 method_call: MethodCall,
2023 base_expr: &ast::Expr,
2024 adjusted_ty: Ty<'tcx>,
2025 adjustment: ty::AutoDerefRef<'tcx>,
2026 lvalue_pref: LvaluePreference,
2028 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2030 let tcx = fcx.tcx();
2031 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2033 base_expr.repr(tcx),
2034 adjusted_ty.repr(tcx),
2036 index_ty.repr(tcx));
2038 let input_ty = fcx.infcx().next_ty_var();
2040 // First, try built-in indexing.
2041 match (ty::index(adjusted_ty), &index_ty.sty) {
2042 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2043 debug!("try_index_step: success, using built-in indexing");
2044 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2045 return Some((tcx.types.uint, ty));
2050 // Try `IndexMut` first, if preferred.
2051 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2052 (PreferMutLvalue, Some(trait_did)) => {
2053 method::lookup_in_trait_adjusted(fcx,
2056 token::intern("index_mut"),
2060 Some(vec![input_ty]))
2065 // Otherwise, fall back to `Index`.
2066 let method = match (method, tcx.lang_items.index_trait()) {
2067 (None, Some(trait_did)) => {
2068 method::lookup_in_trait_adjusted(fcx,
2071 token::intern("index"),
2075 Some(vec![input_ty]))
2077 (method, _) => method,
2080 // If some lookup succeeds, write callee into table and extract index/element
2081 // type from the method signature.
2082 // If some lookup succeeded, install method in table
2083 method.and_then(|method| {
2084 debug!("try_index_step: success, using overloaded indexing");
2085 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2086 map(|ret| (input_ty, ret.ty))
2090 /// Given the head of a `for` expression, looks up the `next` method in the
2091 /// `Iterator` trait. Panics if the expression does not implement `next`.
2093 /// The return type of this function represents the concrete element type
2094 /// `A` in the type `Iterator<A>` that the method returns.
2095 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2096 iterator_expr: &ast::Expr,
2097 loop_id: ast::NodeId)
2099 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2100 Ok(trait_did) => trait_did,
2101 Err(ref err_string) => {
2102 fcx.tcx().sess.span_err(iterator_expr.span,
2104 return fcx.tcx().types.err
2108 let expr_type = fcx.expr_ty(&*iterator_expr);
2109 let method = method::lookup_in_trait(fcx,
2111 Some(&*iterator_expr),
2112 token::intern("next"),
2117 // Regardless of whether the lookup succeeds, check the method arguments
2118 // so that we have *some* type for each argument.
2119 let method_type = match method {
2120 Some(ref method) => method.ty,
2122 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2124 if !ty::type_is_error(true_expr_type) {
2125 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2126 fcx.tcx().sess.span_err(iterator_expr.span,
2127 &format!("`for` loop expression has type `{}` which does \
2128 not implement the `Iterator` trait; \
2135 let return_type = check_method_argument_types(fcx,
2146 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2149 // We expect the return type to be `Option` or something like it.
2150 // Grab the first parameter of its type substitution.
2151 let return_type = match return_type {
2152 ty::FnConverging(return_type) =>
2153 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2154 ty::FnDiverging => fcx.tcx().types.err
2156 match return_type.sty {
2157 ty::ty_enum(_, ref substs)
2158 if !substs.types.is_empty_in(subst::TypeSpace) => {
2159 *substs.types.get(subst::TypeSpace, 0)
2165 fcx.tcx().sess.span_err(iterator_expr.span,
2166 &format!("`next` method of the `Iterator` \
2167 trait has an unexpected type `{}`",
2168 fcx.infcx().ty_to_string(return_type))
2174 None => fcx.tcx().types.err
2178 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2180 method_fn_ty: Ty<'tcx>,
2181 callee_expr: &ast::Expr,
2182 args_no_rcvr: &[P<ast::Expr>],
2183 autoref_args: AutorefArgs,
2184 tuple_arguments: TupleArgumentsFlag,
2185 expected: Expectation<'tcx>)
2186 -> ty::FnOutput<'tcx> {
2187 if ty::type_is_error(method_fn_ty) {
2188 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2190 let err_inputs = match tuple_arguments {
2191 DontTupleArguments => err_inputs,
2192 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2195 check_argument_types(fcx,
2203 ty::FnConverging(fcx.tcx().types.err)
2205 match method_fn_ty.sty {
2206 ty::ty_bare_fn(_, ref fty) => {
2207 // HACK(eddyb) ignore self in the definition (see above).
2208 let expected_arg_tys = expected_types_for_fn_args(fcx,
2212 &fty.sig.0.inputs[1..]);
2213 check_argument_types(fcx,
2215 &fty.sig.0.inputs[1..],
2216 &expected_arg_tys[],
2224 fcx.tcx().sess.span_bug(callee_expr.span,
2225 "method without bare fn type");
2231 /// Generic function that factors out common logic from function calls, method calls and overloaded
2233 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2235 fn_inputs: &[Ty<'tcx>],
2236 expected_arg_tys: &[Ty<'tcx>],
2237 args: &[P<ast::Expr>],
2238 autoref_args: AutorefArgs,
2240 tuple_arguments: TupleArgumentsFlag) {
2241 let tcx = fcx.ccx.tcx;
2243 // Grab the argument types, supplying fresh type variables
2244 // if the wrong number of arguments were supplied
2245 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2251 let mut expected_arg_tys = expected_arg_tys;
2252 let expected_arg_count = fn_inputs.len();
2253 let formal_tys = if tuple_arguments == TupleArguments {
2254 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2255 match tuple_type.sty {
2256 ty::ty_tup(ref arg_types) => {
2257 if arg_types.len() != args.len() {
2258 span_err!(tcx.sess, sp, E0057,
2259 "this function takes {} parameter{} but {} parameter{} supplied",
2261 if arg_types.len() == 1 {""} else {"s"},
2263 if args.len() == 1 {" was"} else {"s were"});
2264 expected_arg_tys = &[][];
2265 err_args(fcx.tcx(), args.len())
2267 expected_arg_tys = match expected_arg_tys.get(0) {
2268 Some(&ty) => match ty.sty {
2269 ty::ty_tup(ref tys) => &**tys,
2274 (*arg_types).clone()
2278 span_err!(tcx.sess, sp, E0059,
2279 "cannot use call notation; the first type parameter \
2280 for the function trait is neither a tuple nor unit");
2281 expected_arg_tys = &[][];
2282 err_args(fcx.tcx(), args.len())
2285 } else if expected_arg_count == supplied_arg_count {
2287 } else if variadic {
2288 if supplied_arg_count >= expected_arg_count {
2291 span_err!(tcx.sess, sp, E0060,
2292 "this function takes at least {} parameter{} \
2293 but {} parameter{} supplied",
2295 if expected_arg_count == 1 {""} else {"s"},
2297 if supplied_arg_count == 1 {" was"} else {"s were"});
2298 expected_arg_tys = &[][];
2299 err_args(fcx.tcx(), supplied_arg_count)
2302 span_err!(tcx.sess, sp, E0061,
2303 "this function takes {} parameter{} but {} parameter{} supplied",
2305 if expected_arg_count == 1 {""} else {"s"},
2307 if supplied_arg_count == 1 {" was"} else {"s were"});
2308 expected_arg_tys = &[][];
2309 err_args(fcx.tcx(), supplied_arg_count)
2312 debug!("check_argument_types: formal_tys={:?}",
2313 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2315 // Check the arguments.
2316 // We do this in a pretty awful way: first we typecheck any arguments
2317 // that are not anonymous functions, then we typecheck the anonymous
2318 // functions. This is so that we have more information about the types
2319 // of arguments when we typecheck the functions. This isn't really the
2320 // right way to do this.
2321 let xs = [false, true];
2322 for check_blocks in xs.iter() {
2323 let check_blocks = *check_blocks;
2324 debug!("check_blocks={}", check_blocks);
2326 // More awful hacks: before we check the blocks, try to do
2327 // an "opportunistic" vtable resolution of any trait
2328 // bounds on the call.
2330 vtable::select_new_fcx_obligations(fcx);
2333 // For variadic functions, we don't have a declared type for all of
2334 // the arguments hence we only do our usual type checking with
2335 // the arguments who's types we do know.
2336 let t = if variadic {
2338 } else if tuple_arguments == TupleArguments {
2343 for (i, arg) in args.iter().take(t).enumerate() {
2344 let is_block = match arg.node {
2345 ast::ExprClosure(..) => true,
2349 if is_block == check_blocks {
2350 debug!("checking the argument");
2351 let mut formal_ty = formal_tys[i];
2353 match autoref_args {
2354 AutorefArgs::Yes => {
2355 match formal_ty.sty {
2356 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2359 // So we hit this case when one implements the
2360 // operator traits but leaves an argument as
2361 // just T instead of &T. We'll catch it in the
2362 // mismatch impl/trait method phase no need to
2365 formal_ty = tcx.types.err;
2369 AutorefArgs::No => {}
2372 // The special-cased logic below has three functions:
2373 // 1. Provide as good of an expected type as possible.
2374 let expected = expected_arg_tys.get(i).map(|&ty| {
2375 Expectation::rvalue_hint(ty)
2378 check_expr_with_unifier(fcx, &**arg,
2379 expected.unwrap_or(ExpectHasType(formal_ty)),
2381 // 2. Coerce to the most detailed type that could be coerced
2382 // to, which is `expected_ty` if `rvalue_hint` returns an
2383 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2384 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2385 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2387 // 3. Relate the expected type and the formal one,
2388 // if the expected type was used for the coercion.
2389 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2395 // We also need to make sure we at least write the ty of the other
2396 // arguments which we skipped above.
2398 for arg in args.iter().skip(expected_arg_count) {
2399 check_expr(fcx, &**arg);
2401 // There are a few types which get autopromoted when passed via varargs
2402 // in C but we just error out instead and require explicit casts.
2403 let arg_ty = structurally_resolved_type(fcx, arg.span,
2404 fcx.expr_ty(&**arg));
2406 ty::ty_float(ast::TyF32) => {
2407 fcx.type_error_message(arg.span,
2409 format!("can't pass an {} to variadic \
2410 function, cast to c_double", t)
2413 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2414 fcx.type_error_message(arg.span, |t| {
2415 format!("can't pass {} to variadic \
2416 function, cast to c_int",
2420 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2421 fcx.type_error_message(arg.span, |t| {
2422 format!("can't pass {} to variadic \
2423 function, cast to c_uint",
2433 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2434 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2435 range(0, len).map(|_| tcx.types.err).collect()
2438 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2439 call_expr: &ast::Expr,
2440 output: ty::FnOutput<'tcx>) {
2441 fcx.write_ty(call_expr.id, match output {
2442 ty::FnConverging(output_ty) => output_ty,
2443 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2447 // AST fragment checking
2448 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2450 expected: Expectation<'tcx>)
2453 let tcx = fcx.ccx.tcx;
2456 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2457 ast::LitBinary(..) => {
2459 tcx.mk_region(ty::ReStatic),
2460 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2462 ast::LitByte(_) => tcx.types.u8,
2463 ast::LitChar(_) => tcx.types.char,
2464 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2465 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2466 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2467 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2469 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2470 ty::ty_char => Some(tcx.types.u8),
2471 ty::ty_ptr(..) => Some(tcx.types.uint),
2472 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2476 opt_ty.unwrap_or_else(
2477 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2479 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2480 ast::LitFloatUnsuffixed(_) => {
2481 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2483 ty::ty_float(_) => Some(ty),
2487 opt_ty.unwrap_or_else(
2488 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2490 ast::LitBool(_) => tcx.types.bool
2494 pub fn valid_range_bounds(ccx: &CrateCtxt,
2498 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2499 Some(val) => Some(val <= 0),
2504 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2506 expected: Ty<'tcx>) {
2507 check_expr_with_unifier(
2508 fcx, expr, ExpectHasType(expected), NoPreference,
2509 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2512 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2514 expected: Ty<'tcx>) {
2515 check_expr_with_unifier(
2516 fcx, expr, ExpectHasType(expected), NoPreference,
2517 || demand::coerce(fcx, expr.span, expected, expr));
2520 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2521 expected: Ty<'tcx>) {
2522 check_expr_with_unifier(
2523 fcx, expr, ExpectHasType(expected), NoPreference,
2527 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2529 expected: Expectation<'tcx>) {
2530 check_expr_with_unifier(
2531 fcx, expr, expected, NoPreference,
2535 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2537 expected: Expectation<'tcx>,
2538 lvalue_pref: LvaluePreference)
2540 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2543 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2544 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2547 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2548 lvalue_pref: LvaluePreference) {
2549 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2552 // determine the `self` type, using fresh variables for all variables
2553 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2554 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2556 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2557 span: Span, // (potential) receiver for this impl
2559 -> TypeAndSubsts<'tcx> {
2560 let tcx = fcx.tcx();
2562 let ity = ty::lookup_item_type(tcx, did);
2563 let (n_tps, rps, raw_ty) =
2564 (ity.generics.types.len(subst::TypeSpace),
2565 ity.generics.regions.get_slice(subst::TypeSpace),
2568 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2569 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2570 let substs = subst::Substs::new_type(tps, rps);
2571 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2573 TypeAndSubsts { substs: substs, ty: substd_ty }
2576 // Controls whether the arguments are automatically referenced. This is useful
2577 // for overloaded binary and unary operators.
2578 #[derive(Copy, PartialEq)]
2579 pub enum AutorefArgs {
2584 /// Controls whether the arguments are tupled. This is used for the call
2587 /// Tupling means that all call-side arguments are packed into a tuple and
2588 /// passed as a single parameter. For example, if tupling is enabled, this
2591 /// fn f(x: (int, int))
2593 /// Can be called as:
2600 #[derive(Clone, Eq, PartialEq)]
2601 enum TupleArgumentsFlag {
2606 /// Unifies the return type with the expected type early, for more coercions
2607 /// and forward type information on the argument expressions.
2608 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2610 expected_ret: Expectation<'tcx>,
2611 formal_ret: ty::FnOutput<'tcx>,
2612 formal_args: &[Ty<'tcx>])
2614 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2615 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2616 fcx.infcx().commit_regions_if_ok(|| {
2617 // Attempt to apply a subtyping relationship between the formal
2618 // return type (likely containing type variables if the function
2619 // is polymorphic) and the expected return type.
2620 // No argument expectations are produced if unification fails.
2621 let origin = infer::Misc(call_span);
2622 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2623 // FIXME(#15760) can't use try! here, FromError doesn't default
2624 // to identity so the resulting type is not constrained.
2625 if let Err(e) = ures {
2629 // Record all the argument types, with the substitutions
2630 // produced from the above subtyping unification.
2631 Ok(formal_args.iter().map(|ty| {
2632 fcx.infcx().resolve_type_vars_if_possible(ty)
2638 }).unwrap_or(vec![]);
2639 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2640 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2641 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2646 /// If an expression has any sub-expressions that result in a type error,
2647 /// inspecting that expression's type with `ty::type_is_error` will return
2648 /// true. Likewise, if an expression is known to diverge, inspecting its
2649 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2650 /// strict, _|_ can appear in the type of an expression that does not,
2651 /// itself, diverge: for example, fn() -> _|_.)
2652 /// Note that inspecting a type's structure *directly* may expose the fact
2653 /// that there are actually multiple representations for `ty_err`, so avoid
2654 /// that when err needs to be handled differently.
2655 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2657 expected: Expectation<'tcx>,
2658 lvalue_pref: LvaluePreference,
2662 debug!(">> typechecking: expr={} expected={}",
2663 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2665 // Checks a method call.
2666 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2668 method_name: ast::SpannedIdent,
2669 args: &[P<ast::Expr>],
2671 expected: Expectation<'tcx>,
2672 lvalue_pref: LvaluePreference) {
2673 let rcvr = &*args[0];
2674 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2676 // no need to check for bot/err -- callee does that
2677 let expr_t = structurally_resolved_type(fcx,
2679 fcx.expr_ty(&*rcvr));
2681 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2682 let fn_ty = match method::lookup(fcx,
2684 method_name.node.name,
2690 let method_ty = method.ty;
2691 let method_call = MethodCall::expr(expr.id);
2692 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2696 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
2697 fcx.write_error(expr.id);
2702 // Call the generic checker.
2703 let ret_ty = check_method_argument_types(fcx,
2712 write_call(fcx, expr, ret_ty);
2715 // A generic function for checking the then and else in an if
2717 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2718 cond_expr: &ast::Expr,
2719 then_blk: &ast::Block,
2720 opt_else_expr: Option<&ast::Expr>,
2723 expected: Expectation<'tcx>) {
2724 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2726 let expected = expected.adjust_for_branches(fcx);
2727 check_block_with_expected(fcx, then_blk, expected);
2728 let then_ty = fcx.node_ty(then_blk.id);
2730 let branches_ty = match opt_else_expr {
2731 Some(ref else_expr) => {
2732 check_expr_with_expectation(fcx, &**else_expr, expected);
2733 let else_ty = fcx.expr_ty(&**else_expr);
2734 infer::common_supertype(fcx.infcx(),
2735 infer::IfExpression(sp),
2741 infer::common_supertype(fcx.infcx(),
2742 infer::IfExpressionWithNoElse(sp),
2745 ty::mk_nil(fcx.tcx()))
2749 let cond_ty = fcx.expr_ty(cond_expr);
2750 let if_ty = if ty::type_is_error(cond_ty) {
2756 fcx.write_ty(id, if_ty);
2759 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2763 trait_did: Option<ast::DefId>,
2765 rhs: Option<&P<ast::Expr>>,
2767 autoref_args: AutorefArgs) -> Ty<'tcx> where
2770 let method = match trait_did {
2771 Some(trait_did) => {
2772 // We do eager coercions to make using operators
2775 // - If the input is of type &'a T (resp. &'a mut T),
2776 // then reborrow it to &'b T (resp. &'b mut T) where
2777 // 'b <= 'a. This makes things like `x == y`, where
2778 // `x` and `y` are both region pointers, work. We
2779 // could also solve this with variance or different
2780 // traits that don't force left and right to have same
2782 let (adj_ty, adjustment) = match lhs_ty.sty {
2783 ty::ty_rptr(r_in, mt) => {
2784 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2785 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2786 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2787 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2788 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2789 (adjusted_ty, adjustment)
2792 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2796 debug!("adjusted_ty={} adjustment={:?}",
2797 adj_ty.repr(fcx.tcx()),
2800 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2801 trait_did, adjustment, adj_ty, None)
2805 let args = match rhs {
2806 Some(rhs) => slice::ref_slice(rhs),
2811 let method_ty = method.ty;
2812 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2813 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2814 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2815 match check_method_argument_types(fcx,
2823 ty::FnConverging(result_type) => result_type,
2824 ty::FnDiverging => fcx.tcx().types.err
2829 // Check the args anyway
2830 // so we get all the error messages
2831 let expected_ty = fcx.tcx().types.err;
2832 check_method_argument_types(fcx,
2845 // could be either an expr_binop or an expr_assign_binop
2846 fn check_binop(fcx: &FnCtxt,
2851 is_binop_assignment: IsBinopAssignment) {
2852 let tcx = fcx.ccx.tcx;
2854 let lvalue_pref = match is_binop_assignment {
2855 BinopAssignment => PreferMutLvalue,
2856 SimpleBinop => NoPreference
2858 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2860 // Callee does bot / err checking
2861 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2862 fcx.expr_ty(&*lhs));
2864 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2865 // Shift is a special case: rhs must be uint, no matter what lhs is
2866 check_expr(fcx, &**rhs);
2867 let rhs_ty = fcx.expr_ty(&**rhs);
2868 let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
2869 if ty::type_is_integral(rhs_ty) {
2870 fcx.write_ty(expr.id, lhs_t);
2872 fcx.type_error_message(
2876 "right-hand-side of a shift operation must have integral type, \
2882 fcx.write_ty(expr.id, fcx.tcx().types.err);
2887 if ty::is_binopable(tcx, lhs_t, op) {
2888 let tvar = fcx.infcx().next_ty_var();
2889 demand::suptype(fcx, expr.span, tvar, lhs_t);
2890 check_expr_has_type(fcx, &**rhs, tvar);
2892 let result_t = match op {
2893 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2895 if ty::type_is_simd(tcx, lhs_t) {
2896 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2897 fcx.type_error_message(expr.span,
2899 format!("binary comparison \
2900 operation `{}` not \
2901 supported for floating \
2902 point SIMD vector `{}`",
2903 ast_util::binop_to_string(op),
2914 fcx.tcx().types.bool
2920 fcx.write_ty(expr.id, result_t);
2924 if op == ast::BiOr || op == ast::BiAnd {
2925 // This is an error; one of the operands must have the wrong
2927 fcx.write_error(expr.id);
2928 fcx.write_error(rhs.id);
2929 fcx.type_error_message(expr.span,
2931 format!("binary operation `{}` cannot be applied \
2933 ast_util::binop_to_string(op),
2940 // Check for overloaded operators if not an assignment.
2941 let result_t = if is_binop_assignment == SimpleBinop {
2942 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2944 fcx.type_error_message(expr.span,
2946 format!("binary assignment \
2948 cannot be applied to \
2950 ast_util::binop_to_string(op),
2955 check_expr(fcx, &**rhs);
2959 fcx.write_ty(expr.id, result_t);
2960 if ty::type_is_error(result_t) {
2961 fcx.write_ty(rhs.id, result_t);
2965 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2967 lhs_expr: &ast::Expr,
2968 lhs_resolved_t: Ty<'tcx>,
2970 rhs: &P<ast::Expr>) -> Ty<'tcx> {
2971 let tcx = fcx.ccx.tcx;
2972 let lang = &tcx.lang_items;
2973 let (name, trait_did) = match op {
2974 ast::BiAdd => ("add", lang.add_trait()),
2975 ast::BiSub => ("sub", lang.sub_trait()),
2976 ast::BiMul => ("mul", lang.mul_trait()),
2977 ast::BiDiv => ("div", lang.div_trait()),
2978 ast::BiRem => ("rem", lang.rem_trait()),
2979 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2980 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2981 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2982 ast::BiShl => ("shl", lang.shl_trait()),
2983 ast::BiShr => ("shr", lang.shr_trait()),
2984 ast::BiLt => ("lt", lang.ord_trait()),
2985 ast::BiLe => ("le", lang.ord_trait()),
2986 ast::BiGe => ("ge", lang.ord_trait()),
2987 ast::BiGt => ("gt", lang.ord_trait()),
2988 ast::BiEq => ("eq", lang.eq_trait()),
2989 ast::BiNe => ("ne", lang.eq_trait()),
2990 ast::BiAnd | ast::BiOr => {
2991 check_expr(fcx, &**rhs);
2992 return tcx.types.err;
2995 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2996 trait_did, lhs_expr, Some(rhs), || {
2997 fcx.type_error_message(ex.span, |actual| {
2998 format!("binary operation `{}` cannot be applied to type `{}`",
2999 ast_util::binop_to_string(op),
3001 }, lhs_resolved_t, None)
3002 }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3005 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3008 trait_did: Option<ast::DefId>,
3010 rhs_expr: &ast::Expr,
3012 op: ast::UnOp) -> Ty<'tcx> {
3013 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3014 trait_did, rhs_expr, None, || {
3015 fcx.type_error_message(ex.span, |actual| {
3016 format!("cannot apply unary operator `{}` to type `{}`",
3019 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3022 // Check field access expressions
3023 fn check_field(fcx: &FnCtxt,
3025 lvalue_pref: LvaluePreference,
3027 field: &ast::SpannedIdent) {
3028 let tcx = fcx.ccx.tcx;
3029 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3030 let expr_t = structurally_resolved_type(fcx, expr.span,
3032 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3033 let (_, autoderefs, field_ty) =
3034 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3036 ty::ty_struct(base_id, substs) => {
3037 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3038 let fields = ty::lookup_struct_fields(tcx, base_id);
3039 fcx.lookup_field_ty(expr.span, base_id, &fields[],
3040 field.node.name, &(*substs))
3047 fcx.write_ty(expr.id, field_ty);
3048 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3054 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3055 fcx.type_error_message(
3058 format!("attempted to take value of method `{}` on type \
3059 `{}`", token::get_ident(field.node), actual)
3063 tcx.sess.span_help(field.span,
3064 "maybe a `()` to call it is missing? \
3065 If not, try an anonymous function");
3067 fcx.type_error_message(
3070 format!("attempted access of field `{}` on \
3071 type `{}`, but no field with that \
3073 token::get_ident(field.node),
3079 fcx.write_error(expr.id);
3082 // Check tuple index expressions
3083 fn check_tup_field(fcx: &FnCtxt,
3085 lvalue_pref: LvaluePreference,
3087 idx: codemap::Spanned<uint>) {
3088 let tcx = fcx.ccx.tcx;
3089 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3090 let expr_t = structurally_resolved_type(fcx, expr.span,
3092 let mut tuple_like = false;
3093 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3094 let (_, autoderefs, field_ty) =
3095 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3097 ty::ty_struct(base_id, substs) => {
3098 tuple_like = ty::is_tuple_struct(tcx, base_id);
3100 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3101 let fields = ty::lookup_struct_fields(tcx, base_id);
3102 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3103 idx.node, &(*substs))
3108 ty::ty_tup(ref v) => {
3110 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3117 fcx.write_ty(expr.id, field_ty);
3118 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3123 fcx.type_error_message(
3127 format!("attempted out-of-bounds tuple index `{}` on \
3132 format!("attempted tuple index `{}` on type `{}`, but the \
3133 type was not a tuple or tuple struct",
3140 fcx.write_error(expr.id);
3143 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3144 struct_ty: Ty<'tcx>,
3146 class_id: ast::DefId,
3147 node_id: ast::NodeId,
3148 substitutions: &'tcx subst::Substs<'tcx>,
3149 field_types: &[ty::field_ty],
3150 ast_fields: &[ast::Field],
3151 check_completeness: bool,
3152 enum_id_opt: Option<ast::DefId>) {
3153 let tcx = fcx.ccx.tcx;
3155 let mut class_field_map = FnvHashMap();
3156 let mut fields_found = 0;
3157 for field in field_types.iter() {
3158 class_field_map.insert(field.name, (field.id, false));
3161 let mut error_happened = false;
3163 // Typecheck each field.
3164 for field in ast_fields.iter() {
3165 let mut expected_field_type = tcx.types.err;
3167 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3170 fcx.type_error_message(
3172 |actual| match enum_id_opt {
3174 let variant_type = ty::enum_variant_with_id(tcx,
3177 format!("struct variant `{}::{}` has no field named `{}`",
3178 actual, variant_type.name.as_str(),
3179 token::get_ident(field.ident.node))
3182 format!("structure `{}` has no field named `{}`",
3184 token::get_ident(field.ident.node))
3189 error_happened = true;
3191 Some((_, true)) => {
3192 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3193 "field `{}` specified more than once",
3194 token::get_ident(field.ident.node));
3195 error_happened = true;
3197 Some((field_id, false)) => {
3198 expected_field_type =
3199 ty::lookup_field_type(
3200 tcx, class_id, field_id, substitutions);
3201 expected_field_type =
3202 fcx.normalize_associated_types_in(
3203 field.span, &expected_field_type);
3204 class_field_map.insert(
3205 field.ident.node.name, (field_id, true));
3210 // Make sure to give a type to the field even if there's
3211 // an error, so we can continue typechecking
3212 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3216 fcx.write_error(node_id);
3219 if check_completeness && !error_happened {
3220 // Make sure the programmer specified all the fields.
3221 assert!(fields_found <= field_types.len());
3222 if fields_found < field_types.len() {
3223 let mut missing_fields = Vec::new();
3224 for class_field in field_types.iter() {
3225 let name = class_field.name;
3226 let (_, seen) = class_field_map[name];
3228 missing_fields.push(
3229 format!("`{}`", token::get_name(name).get()))
3233 span_err!(tcx.sess, span, E0063,
3234 "missing field{}: {}",
3235 if missing_fields.len() == 1 {""} else {"s"},
3236 missing_fields.connect(", "));
3240 if !error_happened {
3241 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3242 class_id, substitutions));
3246 fn check_struct_constructor(fcx: &FnCtxt,
3248 span: codemap::Span,
3249 class_id: ast::DefId,
3250 fields: &[ast::Field],
3251 base_expr: Option<&ast::Expr>) {
3252 let tcx = fcx.ccx.tcx;
3254 // Generate the struct type.
3256 ty: mut struct_type,
3257 substs: struct_substs
3258 } = fcx.instantiate_type(span, class_id);
3260 // Look up and check the fields.
3261 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3262 check_struct_or_variant_fields(fcx,
3267 fcx.ccx.tcx.mk_substs(struct_substs),
3270 base_expr.is_none(),
3272 if ty::type_is_error(fcx.node_ty(id)) {
3273 struct_type = tcx.types.err;
3276 // Check the base expression if necessary.
3279 Some(base_expr) => {
3280 check_expr_has_type(fcx, &*base_expr, struct_type);
3284 // Write in the resulting type.
3285 fcx.write_ty(id, struct_type);
3288 fn check_struct_enum_variant(fcx: &FnCtxt,
3290 span: codemap::Span,
3291 enum_id: ast::DefId,
3292 variant_id: ast::DefId,
3293 fields: &[ast::Field]) {
3294 let tcx = fcx.ccx.tcx;
3296 // Look up the number of type parameters and the raw type, and
3297 // determine whether the enum is region-parameterized.
3300 substs: substitutions
3301 } = fcx.instantiate_type(span, enum_id);
3303 // Look up and check the enum variant fields.
3304 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3305 check_struct_or_variant_fields(fcx,
3310 fcx.ccx.tcx.mk_substs(substitutions),
3315 fcx.write_ty(id, enum_type);
3318 fn check_struct_fields_on_error(fcx: &FnCtxt,
3320 fields: &[ast::Field],
3321 base_expr: &Option<P<ast::Expr>>) {
3322 // Make sure to still write the types
3323 // otherwise we might ICE
3324 fcx.write_error(id);
3325 for field in fields.iter() {
3326 check_expr(fcx, &*field.expr);
3329 Some(ref base) => check_expr(fcx, &**base),
3334 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3336 let tcx = fcx.ccx.tcx;
3339 ast::ExprBox(ref opt_place, ref subexpr) => {
3340 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3341 check_expr(fcx, &**subexpr);
3343 let mut checked = false;
3344 opt_place.as_ref().map(|place| match place.node {
3345 ast::ExprPath(ref path) => {
3346 // FIXME(pcwalton): For now we hardcode the two permissible
3347 // places: the exchange heap and the managed heap.
3348 let definition = lookup_def(fcx, path.span, place.id);
3349 let def_id = definition.def_id();
3350 let referent_ty = fcx.expr_ty(&**subexpr);
3351 if tcx.lang_items.exchange_heap() == Some(def_id) {
3352 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3360 span_err!(tcx.sess, expr.span, E0066,
3361 "only the managed heap and exchange heap are currently supported");
3362 fcx.write_ty(id, tcx.types.err);
3366 ast::ExprLit(ref lit) => {
3367 let typ = check_lit(fcx, &**lit, expected);
3368 fcx.write_ty(id, typ);
3370 ast::ExprBinary(op, ref lhs, ref rhs) => {
3371 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3373 let lhs_ty = fcx.expr_ty(&**lhs);
3374 let rhs_ty = fcx.expr_ty(&**rhs);
3375 if ty::type_is_error(lhs_ty) ||
3376 ty::type_is_error(rhs_ty) {
3377 fcx.write_error(id);
3380 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3381 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3383 let lhs_t = fcx.expr_ty(&**lhs);
3384 let result_t = fcx.expr_ty(expr);
3385 demand::suptype(fcx, expr.span, result_t, lhs_t);
3387 let tcx = fcx.tcx();
3388 if !ty::expr_is_lval(tcx, &**lhs) {
3389 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3392 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3394 // Overwrite result of check_binop...this preserves existing behavior
3395 // but seems quite dubious with regard to user-defined methods
3396 // and so forth. - Niko
3397 if !ty::type_is_error(result_t) {
3398 fcx.write_nil(expr.id);
3401 ast::ExprUnary(unop, ref oprnd) => {
3402 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3404 ast::UnUniq => match ty.sty {
3405 ty::ty_uniq(ty) => {
3406 Expectation::rvalue_hint(ty)
3412 ast::UnNot | ast::UnNeg => {
3420 let lvalue_pref = match unop {
3421 ast::UnDeref => lvalue_pref,
3424 check_expr_with_expectation_and_lvalue_pref(
3425 fcx, &**oprnd, expected_inner, lvalue_pref);
3426 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3428 if !ty::type_is_error(oprnd_t) {
3431 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3434 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3435 oprnd_t = match ty::deref(oprnd_t, true) {
3437 None => match try_overloaded_deref(fcx, expr.span,
3438 Some(MethodCall::expr(expr.id)),
3439 Some(&**oprnd), oprnd_t, lvalue_pref) {
3442 let is_newtype = match oprnd_t.sty {
3443 ty::ty_struct(did, substs) => {
3444 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3446 && fields[0].name ==
3447 token::special_idents::unnamed_field.name
3452 // This is an obsolete struct deref
3453 span_err!(tcx.sess, expr.span, E0068,
3454 "single-field tuple-structs can \
3455 no longer be dereferenced");
3457 fcx.type_error_message(expr.span, |actual| {
3458 format!("type `{}` cannot be \
3459 dereferenced", actual)
3468 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3470 if !(ty::type_is_integral(oprnd_t) ||
3471 oprnd_t.sty == ty::ty_bool) {
3472 oprnd_t = check_user_unop(fcx, "!", "not",
3473 tcx.lang_items.not_trait(),
3474 expr, &**oprnd, oprnd_t, unop);
3478 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3480 if !(ty::type_is_integral(oprnd_t) ||
3481 ty::type_is_fp(oprnd_t)) {
3482 oprnd_t = check_user_unop(fcx, "-", "neg",
3483 tcx.lang_items.neg_trait(),
3484 expr, &**oprnd, oprnd_t, unop);
3489 fcx.write_ty(id, oprnd_t);
3491 ast::ExprAddrOf(mutbl, ref oprnd) => {
3492 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3494 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3495 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3496 // Lvalues may legitimately have unsized types.
3497 // For example, dereferences of a fat pointer and
3498 // the last field of a struct can be unsized.
3499 ExpectHasType(mt.ty)
3501 Expectation::rvalue_hint(mt.ty)
3507 let lvalue_pref = match mutbl {
3508 ast::MutMutable => PreferMutLvalue,
3509 ast::MutImmutable => NoPreference
3511 check_expr_with_expectation_and_lvalue_pref(fcx,
3516 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3517 let oprnd_t = if ty::type_is_error(tm.ty) {
3520 // Note: at this point, we cannot say what the best lifetime
3521 // is to use for resulting pointer. We want to use the
3522 // shortest lifetime possible so as to avoid spurious borrowck
3523 // errors. Moreover, the longest lifetime will depend on the
3524 // precise details of the value whose address is being taken
3525 // (and how long it is valid), which we don't know yet until type
3526 // inference is complete.
3528 // Therefore, here we simply generate a region variable. The
3529 // region inferencer will then select the ultimate value.
3530 // Finally, borrowck is charged with guaranteeing that the
3531 // value whose address was taken can actually be made to live
3532 // as long as it needs to live.
3534 // String literals are already, implicitly converted to slices.
3535 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3536 // Empty slices live in static memory.
3537 ast::ExprVec(ref elements) if elements.len() == 0 => {
3538 // Note: we do not assign a lifetime of
3539 // static. This is because the resulting type
3540 // `&'static [T]` would require that T outlives
3542 let region = fcx.infcx().next_region_var(
3543 infer::AddrOfSlice(expr.span));
3544 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3547 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3548 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3552 fcx.write_ty(id, oprnd_t);
3554 ast::ExprPath(ref path) => {
3555 let defn = lookup_def(fcx, path.span, id);
3556 let pty = type_scheme_for_def(fcx, expr.span, defn);
3557 instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3559 // We always require that the type provided as the value for
3560 // a type parameter outlives the moment of instantiation.
3561 constrain_path_type_parameters(fcx, expr);
3563 ast::ExprQPath(ref qpath) => {
3564 // Require explicit type params for the trait.
3565 let self_ty = fcx.to_ty(&*qpath.self_type);
3566 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3568 let defn = lookup_def(fcx, expr.span, id);
3569 let pty = type_scheme_for_def(fcx, expr.span, defn);
3570 let mut path = qpath.trait_ref.path.clone();
3571 path.segments.push(qpath.item_path.clone());
3572 instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3574 // We always require that the type provided as the value for
3575 // a type parameter outlives the moment of instantiation.
3576 constrain_path_type_parameters(fcx, expr);
3578 ast::ExprInlineAsm(ref ia) => {
3579 for &(_, ref input) in ia.inputs.iter() {
3580 check_expr(fcx, &**input);
3582 for &(_, ref out, _) in ia.outputs.iter() {
3583 check_expr(fcx, &**out);
3587 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3588 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3589 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3590 ast::ExprRet(ref expr_opt) => {
3592 ty::FnConverging(result_type) => {
3595 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3596 result_type, ty::mk_nil(fcx.tcx())) {
3597 span_err!(tcx.sess, expr.span, E0069,
3598 "`return;` in function returning non-nil");
3601 check_expr_coercable_to_type(fcx, &**e, result_type);
3605 ty::FnDiverging => {
3606 if let Some(ref e) = *expr_opt {
3607 check_expr(fcx, &**e);
3609 span_err!(tcx.sess, expr.span, E0166,
3610 "`return` in a function declared as diverging");
3613 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3615 ast::ExprParen(ref a) => {
3616 check_expr_with_expectation_and_lvalue_pref(fcx,
3620 fcx.write_ty(id, fcx.expr_ty(&**a));
3622 ast::ExprAssign(ref lhs, ref rhs) => {
3623 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3625 let tcx = fcx.tcx();
3626 if !ty::expr_is_lval(tcx, &**lhs) {
3627 span_err!(tcx.sess, expr.span, E0070,
3628 "illegal left-hand side expression");
3631 let lhs_ty = fcx.expr_ty(&**lhs);
3632 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3633 let rhs_ty = fcx.expr_ty(&**rhs);
3635 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3637 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3638 fcx.write_error(id);
3643 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3644 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3645 id, expr.span, expected);
3647 ast::ExprIfLet(..) => {
3648 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3650 ast::ExprWhile(ref cond, ref body, _) => {
3651 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3652 check_block_no_value(fcx, &**body);
3653 let cond_ty = fcx.expr_ty(&**cond);
3654 let body_ty = fcx.node_ty(body.id);
3655 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3656 fcx.write_error(id);
3662 ast::ExprWhileLet(..) => {
3663 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3665 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3666 check_expr(fcx, &**head);
3667 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
3668 vtable::select_new_fcx_obligations(fcx);
3670 debug!("ExprForLoop each item has type {}",
3671 fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
3673 let pcx = pat_ctxt {
3675 map: pat_id_map(&tcx.def_map, &**pat),
3677 _match::check_pat(&pcx, &**pat, typ);
3679 check_block_no_value(fcx, &**block);
3682 ast::ExprLoop(ref body, _) => {
3683 check_block_no_value(fcx, &**body);
3684 if !may_break(tcx, expr.id, &**body) {
3685 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3690 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3691 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3693 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3694 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3696 ast::ExprBlock(ref b) => {
3697 check_block_with_expected(fcx, &**b, expected);
3698 fcx.write_ty(id, fcx.node_ty(b.id));
3700 ast::ExprCall(ref callee, ref args) => {
3701 callee::check_call(fcx, expr, &**callee, &args[], expected);
3703 ast::ExprMethodCall(ident, ref tps, ref args) => {
3704 check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3705 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3706 let args_err = arg_tys.fold(false,
3708 rest_err || ty::type_is_error(a)});
3710 fcx.write_error(id);
3713 ast::ExprCast(ref e, ref t) => {
3714 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3715 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3717 check_cast(fcx, expr, &**e, &**t);
3719 ast::ExprVec(ref args) => {
3720 let uty = expected.to_option(fcx).and_then(|uty| {
3722 ty::ty_vec(ty, _) => Some(ty),
3727 let typ = match uty {
3729 for e in args.iter() {
3730 check_expr_coercable_to_type(fcx, &**e, uty);
3735 let t: Ty = fcx.infcx().next_ty_var();
3736 for e in args.iter() {
3737 check_expr_has_type(fcx, &**e, t);
3742 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3743 fcx.write_ty(id, typ);
3745 ast::ExprRepeat(ref element, ref count_expr) => {
3746 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3747 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3749 let uty = match expected {
3750 ExpectHasType(uty) => {
3752 ty::ty_vec(ty, _) => Some(ty),
3759 let (element_ty, t) = match uty {
3761 check_expr_coercable_to_type(fcx, &**element, uty);
3765 let t: Ty = fcx.infcx().next_ty_var();
3766 check_expr_has_type(fcx, &**element, t);
3767 (fcx.expr_ty(&**element), t)
3772 // For [foo, ..n] where n > 1, `foo` must have
3774 fcx.require_type_meets(
3781 if ty::type_is_error(element_ty) {
3782 fcx.write_error(id);
3784 let t = ty::mk_vec(tcx, t, Some(count));
3785 fcx.write_ty(id, t);
3788 ast::ExprTup(ref elts) => {
3789 let flds = expected.only_has_type(fcx).and_then(|ty| {
3791 ty::ty_tup(ref flds) => Some(&flds[]),
3795 let mut err_field = false;
3797 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3798 let t = match flds {
3799 Some(ref fs) if i < fs.len() => {
3801 check_expr_coercable_to_type(fcx, &**e, ety);
3805 check_expr_with_expectation(fcx, &**e, NoExpectation);
3809 err_field = err_field || ty::type_is_error(t);
3813 fcx.write_error(id);
3815 let typ = ty::mk_tup(tcx, elt_ts);
3816 fcx.write_ty(id, typ);
3819 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3820 // Resolve the path.
3821 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3822 let struct_id = match def {
3823 Some(def::DefVariant(enum_id, variant_id, true)) => {
3824 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3825 variant_id, &fields[]);
3828 Some(def::DefTrait(def_id)) => {
3829 span_err!(tcx.sess, path.span, E0159,
3830 "use of trait `{}` as a struct constructor",
3831 pprust::path_to_string(path));
3832 check_struct_fields_on_error(fcx,
3839 // Verify that this was actually a struct.
3840 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3842 ty::ty_struct(struct_did, _) => {
3843 check_struct_constructor(fcx,
3848 base_expr.as_ref().map(|e| &**e));
3851 span_err!(tcx.sess, path.span, E0071,
3852 "`{}` does not name a structure",
3853 pprust::path_to_string(path));
3854 check_struct_fields_on_error(fcx,
3864 tcx.sess.span_bug(path.span,
3865 "structure constructor wasn't resolved")
3869 // Turn the path into a type and verify that that type unifies with
3870 // the resulting structure type. This is needed to handle type
3871 // parameters correctly.
3872 let actual_structure_type = fcx.expr_ty(&*expr);
3873 if !ty::type_is_error(actual_structure_type) {
3874 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3875 match fcx.mk_subty(false,
3876 infer::Misc(path.span),
3877 actual_structure_type,
3878 type_and_substs.ty) {
3880 Err(type_error) => {
3881 let type_error_description =
3882 ty::type_err_to_str(tcx, &type_error);
3885 .span_err(path.span,
3886 &format!("structure constructor specifies a \
3887 structure of type `{}`, but this \
3888 structure has type `{}`: {}",
3890 .ty_to_string(type_and_substs.ty),
3893 actual_structure_type),
3894 type_error_description)[]);
3895 ty::note_and_explain_type_err(tcx, &type_error);
3900 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3902 ast::ExprField(ref base, ref field) => {
3903 check_field(fcx, expr, lvalue_pref, &**base, field);
3905 ast::ExprTupField(ref base, idx) => {
3906 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3908 ast::ExprIndex(ref base, ref idx) => {
3909 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3910 let base_t = fcx.expr_ty(&**base);
3911 if ty::type_is_error(base_t) {
3912 fcx.write_ty(id, base_t);
3914 check_expr(fcx, &**idx);
3915 let idx_t = fcx.expr_ty(&**idx);
3916 if ty::type_is_error(idx_t) {
3917 fcx.write_ty(id, idx_t);
3919 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3922 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3924 MethodCall::expr(expr.id),
3934 Some((index_ty, element_ty)) => {
3935 // FIXME: we've already checked idx above, we should
3936 // probably just demand subtype or something here.
3937 check_expr_has_type(fcx, &**idx, index_ty);
3938 fcx.write_ty(id, element_ty);
3941 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3942 fcx.type_error_message(
3945 format!("cannot index a value of type `{}`",
3950 fcx.write_ty(id, fcx.tcx().types.err);
3956 ast::ExprRange(ref start, ref end) => {
3957 let t_start = start.as_ref().map(|e| {
3958 check_expr(fcx, &**e);
3961 let t_end = end.as_ref().map(|e| {
3962 check_expr(fcx, &**e);
3966 let idx_type = match (t_start, t_end) {
3967 (Some(ty), None) | (None, Some(ty)) => {
3970 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3971 ty::type_is_error(t_end)) => {
3972 Some(fcx.tcx().types.err)
3974 (Some(t_start), Some(t_end)) => {
3975 Some(infer::common_supertype(fcx.infcx(),
3976 infer::RangeExpression(expr.span),
3984 // Note that we don't check the type of start/end satisfy any
3985 // bounds because right now the range structs do not have any. If we add
3986 // some bounds, then we'll need to check `t_start` against them here.
3988 let range_type = match idx_type {
3989 Some(idx_type) if ty::type_is_error(idx_type) => {
3993 // Find the did from the appropriate lang item.
3994 let did = match (start, end) {
3995 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3996 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3997 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3999 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4003 if let Some(did) = did {
4004 let polytype = ty::lookup_item_type(tcx, did);
4005 let substs = Substs::new_type(vec![idx_type], vec![]);
4006 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4007 fcx.add_obligations_for_parameters(
4008 traits::ObligationCause::new(expr.span,
4010 traits::ItemObligation(did)),
4013 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4015 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4020 // Neither start nor end => FullRange
4021 if let Some(did) = tcx.lang_items.full_range_struct() {
4022 let substs = Substs::new_type(vec![], vec![]);
4023 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4025 tcx.sess.span_err(expr.span, "No lang item for range syntax");
4031 fcx.write_ty(id, range_type);
4036 debug!("type of expr({}) {} is...", expr.id,
4037 syntax::print::pprust::expr_to_string(expr));
4038 debug!("... {}, expected is {}",
4039 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4040 expected.repr(tcx));
4045 fn constrain_path_type_parameters(fcx: &FnCtxt,
4048 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4049 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4053 impl<'tcx> Expectation<'tcx> {
4054 /// Provide an expectation for an rvalue expression given an *optional*
4055 /// hint, which is not required for type safety (the resulting type might
4056 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4057 /// is useful in determining the concrete type.
4059 /// The primary use case is where the expected type is a fat pointer,
4060 /// like `&[int]`. For example, consider the following statement:
4062 /// let x: &[int] = &[1, 2, 3];
4064 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4065 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4066 /// expectation `ExpectHasType([int])`, that would be too strong --
4067 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4068 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4069 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4070 /// which still is useful, because it informs integer literals and the like.
4071 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4072 /// for examples of where this comes up,.
4073 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4075 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4076 ExpectRvalueLikeUnsized(ty)
4078 _ => ExpectHasType(ty)
4082 // Resolves `expected` by a single level if it is a variable. If
4083 // there is no expected type or resolution is not possible (e.g.,
4084 // no constraints yet present), just returns `None`.
4085 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4090 ExpectCastableToType(t) => {
4091 ExpectCastableToType(
4092 fcx.infcx().resolve_type_vars_if_possible(&t))
4094 ExpectHasType(t) => {
4096 fcx.infcx().resolve_type_vars_if_possible(&t))
4098 ExpectRvalueLikeUnsized(t) => {
4099 ExpectRvalueLikeUnsized(
4100 fcx.infcx().resolve_type_vars_if_possible(&t))
4105 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4106 match self.resolve(fcx) {
4107 NoExpectation => None,
4108 ExpectCastableToType(ty) |
4110 ExpectRvalueLikeUnsized(ty) => Some(ty),
4114 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4115 match self.resolve(fcx) {
4116 ExpectHasType(ty) => Some(ty),
4122 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4123 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4125 NoExpectation => format!("NoExpectation"),
4126 ExpectHasType(t) => format!("ExpectHasType({})",
4128 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4130 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4136 pub fn check_decl_initializer(fcx: &FnCtxt,
4140 let local_ty = fcx.local_ty(init.span, nid);
4141 check_expr_coercable_to_type(fcx, init, local_ty)
4144 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4145 let tcx = fcx.ccx.tcx;
4147 let t = fcx.local_ty(local.span, local.id);
4148 fcx.write_ty(local.id, t);
4150 if let Some(ref init) = local.init {
4151 check_decl_initializer(fcx, local.id, &**init);
4152 let init_ty = fcx.expr_ty(&**init);
4153 if ty::type_is_error(init_ty) {
4154 fcx.write_ty(local.id, init_ty);
4158 let pcx = pat_ctxt {
4160 map: pat_id_map(&tcx.def_map, &*local.pat),
4162 _match::check_pat(&pcx, &*local.pat, t);
4163 let pat_ty = fcx.node_ty(local.pat.id);
4164 if ty::type_is_error(pat_ty) {
4165 fcx.write_ty(local.id, pat_ty);
4169 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4171 let mut saw_bot = false;
4172 let mut saw_err = false;
4174 ast::StmtDecl(ref decl, id) => {
4177 ast::DeclLocal(ref l) => {
4178 check_decl_local(fcx, &**l);
4179 let l_t = fcx.node_ty(l.id);
4180 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4181 saw_err = saw_err || ty::type_is_error(l_t);
4183 ast::DeclItem(_) => {/* ignore for now */ }
4186 ast::StmtExpr(ref expr, id) => {
4188 // Check with expected type of ()
4189 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4190 let expr_ty = fcx.expr_ty(&**expr);
4191 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4192 saw_err = saw_err || ty::type_is_error(expr_ty);
4194 ast::StmtSemi(ref expr, id) => {
4196 check_expr(fcx, &**expr);
4197 let expr_ty = fcx.expr_ty(&**expr);
4198 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4199 saw_err |= ty::type_is_error(expr_ty);
4201 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4204 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4207 fcx.write_error(node_id);
4210 fcx.write_nil(node_id)
4214 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4215 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4216 let blkty = fcx.node_ty(blk.id);
4217 if ty::type_is_error(blkty) {
4218 fcx.write_error(blk.id);
4220 let nilty = ty::mk_nil(fcx.tcx());
4221 demand::suptype(fcx, blk.span, nilty, blkty);
4225 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4227 expected: Expectation<'tcx>) {
4229 let mut fcx_ps = fcx.ps.borrow_mut();
4230 let unsafety_state = fcx_ps.recurse(blk);
4231 replace(&mut *fcx_ps, unsafety_state)
4234 let mut warned = false;
4235 let mut any_diverges = false;
4236 let mut any_err = false;
4237 for s in blk.stmts.iter() {
4238 check_stmt(fcx, &**s);
4239 let s_id = ast_util::stmt_id(&**s);
4240 let s_ty = fcx.node_ty(s_id);
4241 if any_diverges && !warned && match s.node {
4242 ast::StmtDecl(ref decl, _) => {
4244 ast::DeclLocal(_) => true,
4248 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4254 .add_lint(lint::builtin::UNREACHABLE_CODE,
4257 "unreachable statement".to_string());
4260 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4261 any_err = any_err || ty::type_is_error(s_ty);
4264 None => if any_err {
4265 fcx.write_error(blk.id);
4266 } else if any_diverges {
4267 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4269 fcx.write_nil(blk.id);
4272 if any_diverges && !warned {
4276 .add_lint(lint::builtin::UNREACHABLE_CODE,
4279 "unreachable expression".to_string());
4281 let ety = match expected {
4282 ExpectHasType(ety) => {
4283 check_expr_coercable_to_type(fcx, &**e, ety);
4287 check_expr_with_expectation(fcx, &**e, expected);
4293 fcx.write_error(blk.id);
4294 } else if any_diverges {
4295 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4297 fcx.write_ty(blk.id, ety);
4302 *fcx.ps.borrow_mut() = prev;
4305 /// Checks a constant appearing in a type. At the moment this is just the
4306 /// length expression in a fixed-length vector, but someday it might be
4307 /// extended to type-level numeric literals.
4308 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4310 expected_type: Ty<'tcx>) {
4311 let inh = static_inherited_fields(ccx);
4312 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4313 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4316 fn check_const(ccx: &CrateCtxt,
4320 let inh = static_inherited_fields(ccx);
4321 let rty = ty::node_id_to_type(ccx.tcx, id);
4322 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4323 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4324 check_const_with_ty(&fcx, sp, e, declty);
4327 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4331 // Gather locals in statics (because of block expressions).
4332 // This is technically unnecessary because locals in static items are forbidden,
4333 // but prevents type checking from blowing up before const checking can properly
4335 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4337 check_expr_with_hint(fcx, e, declty);
4338 demand::coerce(fcx, e.span, declty, e);
4339 vtable::select_all_fcx_obligations_or_error(fcx);
4340 regionck::regionck_expr(fcx, e);
4341 writeback::resolve_type_vars_in_expr(fcx, e);
4344 /// Checks whether a type can be represented in memory. In particular, it
4345 /// identifies types that contain themselves without indirection through a
4346 /// pointer, which would mean their size is unbounded. This is different from
4347 /// the question of whether a type can be instantiated. See the definition of
4348 /// `check_instantiable`.
4349 pub fn check_representable(tcx: &ty::ctxt,
4351 item_id: ast::NodeId,
4352 designation: &str) -> bool {
4353 let rty = ty::node_id_to_type(tcx, item_id);
4355 // Check that it is possible to represent this type. This call identifies
4356 // (1) types that contain themselves and (2) types that contain a different
4357 // recursive type. It is only necessary to throw an error on those that
4358 // contain themselves. For case 2, there must be an inner type that will be
4359 // caught by case 1.
4360 match ty::is_type_representable(tcx, sp, rty) {
4361 ty::SelfRecursive => {
4362 span_err!(tcx.sess, sp, E0072,
4363 "illegal recursive {} type; \
4364 wrap the inner value in a box to make it representable",
4368 ty::Representable | ty::ContainsRecursive => (),
4373 /// Checks whether a type can be created without an instance of itself.
4374 /// This is similar but different from the question of whether a type
4375 /// can be represented. For example, the following type:
4377 /// enum foo { None, Some(foo) }
4379 /// is instantiable but is not representable. Similarly, the type
4381 /// enum foo { Some(@foo) }
4383 /// is representable, but not instantiable.
4384 pub fn check_instantiable(tcx: &ty::ctxt,
4386 item_id: ast::NodeId)
4388 let item_ty = ty::node_id_to_type(tcx, item_id);
4389 if !ty::is_instantiable(tcx, item_ty) {
4390 span_err!(tcx.sess, sp, E0073,
4391 "this type cannot be instantiated without an \
4392 instance of itself");
4393 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4394 ppaux::ty_to_string(tcx, item_ty));
4401 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4402 let t = ty::node_id_to_type(tcx, id);
4403 if ty::type_needs_subst(t) {
4404 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4408 ty::ty_struct(did, substs) => {
4409 let fields = ty::lookup_struct_fields(tcx, did);
4410 if fields.is_empty() {
4411 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4414 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4415 if !fields.iter().all(
4416 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4417 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4420 if !ty::type_is_machine(e) {
4421 span_err!(tcx.sess, sp, E0077,
4422 "SIMD vector element type should be machine type");
4430 pub fn check_enum_variants(ccx: &CrateCtxt,
4432 vs: &[P<ast::Variant>],
4435 fn disr_in_range(ccx: &CrateCtxt,
4437 disr: ty::Disr) -> bool {
4438 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4440 ast::TyU8 => disr as u8 as Disr == disr,
4441 ast::TyU16 => disr as u16 as Disr == disr,
4442 ast::TyU32 => disr as u32 as Disr == disr,
4443 ast::TyU64 => disr as u64 as Disr == disr,
4444 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4447 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4449 ast::TyI8 => disr as i8 as Disr == disr,
4450 ast::TyI16 => disr as i16 as Disr == disr,
4451 ast::TyI32 => disr as i32 as Disr == disr,
4452 ast::TyI64 => disr as i64 as Disr == disr,
4453 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4457 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4458 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4462 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4463 vs: &[P<ast::Variant>],
4465 hint: attr::ReprAttr)
4466 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4468 let rty = ty::node_id_to_type(ccx.tcx, id);
4469 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4470 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4471 let mut prev_disr_val: Option<ty::Disr> = None;
4473 for v in vs.iter() {
4475 // If the discriminant value is specified explicitly in the enum check whether the
4476 // initialization expression is valid, otherwise use the last value plus one.
4477 let mut current_disr_val = match prev_disr_val {
4478 Some(prev_disr_val) => prev_disr_val + 1,
4479 None => ty::INITIAL_DISCRIMINANT_VALUE
4482 match v.node.disr_expr {
4484 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4486 let inh = static_inherited_fields(ccx);
4487 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4488 let declty = match hint {
4489 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4490 attr::ReprInt(_, attr::SignedInt(ity)) => {
4491 ty::mk_mach_int(fcx.tcx(), ity)
4493 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4494 ty::mk_mach_uint(fcx.tcx(), ity)
4497 check_const_with_ty(&fcx, e.span, &**e, declty);
4498 // check_expr (from check_const pass) doesn't guarantee
4499 // that the expression is in a form that eval_const_expr can
4500 // handle, so we may still get an internal compiler error
4502 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4503 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4504 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4506 span_err!(ccx.tcx.sess, e.span, E0079,
4507 "expected signed integer constant");
4510 span_err!(ccx.tcx.sess, e.span, E0080,
4511 "expected constant: {}", *err);
4518 // Check for duplicate discriminant values
4519 match disr_vals.iter().position(|&x| x == current_disr_val) {
4521 span_err!(ccx.tcx.sess, v.span, E0081,
4522 "discriminant value `{}` already exists", disr_vals[i]);
4523 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4524 "conflicting discriminant here")
4528 // Check for unrepresentable discriminant values
4530 attr::ReprAny | attr::ReprExtern => (),
4531 attr::ReprInt(sp, ity) => {
4532 if !disr_in_range(ccx, ity, current_disr_val) {
4533 span_err!(ccx.tcx.sess, v.span, E0082,
4534 "discriminant value outside specified type");
4535 span_note!(ccx.tcx.sess, sp,
4536 "discriminant type specified here");
4539 attr::ReprPacked => {
4540 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4543 disr_vals.push(current_disr_val);
4545 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4547 prev_disr_val = Some(current_disr_val);
4549 variants.push(variant_info);
4555 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4556 [].get(0).unwrap_or(&attr::ReprAny);
4558 if hint != attr::ReprAny && vs.len() <= 1 {
4560 span_err!(ccx.tcx.sess, sp, E0083,
4561 "unsupported representation for univariant enum");
4563 span_err!(ccx.tcx.sess, sp, E0084,
4564 "unsupported representation for zero-variant enum");
4568 let variants = do_check(ccx, vs, id, hint);
4570 // cache so that ty::enum_variants won't repeat this work
4571 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4573 check_representable(ccx.tcx, sp, id, "enum");
4575 // Check that it is possible to instantiate this enum:
4577 // This *sounds* like the same that as representable, but it's
4578 // not. See def'n of `check_instantiable()` for details.
4579 check_instantiable(ccx.tcx, sp, id);
4582 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4583 lookup_def_ccx(fcx.ccx, sp, id)
4586 // Returns the type parameter count and the type for the given definition.
4587 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4590 -> TypeScheme<'tcx> {
4592 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4593 let typ = fcx.local_ty(sp, nid);
4594 return no_params(typ);
4596 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4597 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4598 def::DefStruct(id) | def::DefConst(id) => {
4599 return ty::lookup_item_type(fcx.ccx.tcx, id);
4603 def::DefAssociatedTy(..) |
4604 def::DefAssociatedPath(..) |
4606 def::DefTyParam(..) => {
4607 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4609 def::DefMod(..) | def::DefForeignMod(..) => {
4610 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4612 def::DefUse(..) => {
4613 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4615 def::DefRegion(..) => {
4616 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4618 def::DefTyParamBinder(..) => {
4619 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4621 def::DefLabel(..) => {
4622 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4624 def::DefSelfTy(..) => {
4625 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4630 // Instantiates the given path, which must refer to an item with the given
4631 // number of type parameters and type.
4632 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4634 type_scheme: TypeScheme<'tcx>,
4635 opt_self_ty: Option<Ty<'tcx>>,
4638 node_id: ast::NodeId) {
4639 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4640 path.repr(fcx.tcx()),
4641 def.repr(fcx.tcx()),
4643 type_scheme.repr(fcx.tcx()));
4645 // We need to extract the type parameters supplied by the user in
4646 // the path `path`. Due to the current setup, this is a bit of a
4647 // tricky-process; the problem is that resolve only tells us the
4648 // end-point of the path resolution, and not the intermediate steps.
4649 // Luckily, we can (at least for now) deduce the intermediate steps
4650 // just from the end-point.
4652 // There are basically three cases to consider:
4654 // 1. Reference to a *type*, such as a struct or enum:
4656 // mod a { struct Foo<T> { ... } }
4658 // Because we don't allow types to be declared within one
4659 // another, a path that leads to a type will always look like
4660 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4661 // that only the final segment can have type parameters, and
4662 // they are located in the TypeSpace.
4664 // *Note:* Generally speaking, references to types don't
4665 // actually pass through this function, but rather the
4666 // `ast_ty_to_ty` function in `astconv`. However, in the case
4667 // of struct patterns (and maybe literals) we do invoke
4668 // `instantiate_path` to get the general type of an instance of
4669 // a struct. (In these cases, there are actually no type
4670 // parameters permitted at present, but perhaps we will allow
4671 // them in the future.)
4673 // 1b. Reference to a enum variant or tuple-like struct:
4675 // struct foo<T>(...)
4676 // enum E<T> { foo(...) }
4678 // In these cases, the parameters are declared in the type
4681 // 2. Reference to a *fn item*:
4685 // In this case, the path will again always have the form
4686 // `a::b::foo::<T>` where only the final segment should have
4687 // type parameters. However, in this case, those parameters are
4688 // declared on a value, and hence are in the `FnSpace`.
4690 // 3. Reference to a *method*:
4692 // impl<A> SomeStruct<A> {
4696 // Here we can have a path like
4697 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4698 // may appear in two places. The penultimate segment,
4699 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4700 // final segment, `foo::<B>` contains parameters in fn space.
4702 // The first step then is to categorize the segments appropriately.
4704 assert!(path.segments.len() >= 1);
4705 let mut segment_spaces: Vec<_>;
4707 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4708 def::DefSelfTy(..) |
4709 def::DefStruct(..) |
4710 def::DefVariant(..) |
4711 def::DefTyParamBinder(..) |
4713 def::DefAssociatedTy(..) |
4714 def::DefAssociatedPath(..) |
4716 def::DefPrimTy(..) |
4717 def::DefTyParam(..) => {
4718 // Everything but the final segment should have no
4719 // parameters at all.
4720 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4721 segment_spaces.push(Some(subst::TypeSpace));
4724 // Case 2. Reference to a top-level value.
4727 def::DefStatic(..) => {
4728 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4729 segment_spaces.push(Some(subst::FnSpace));
4732 // Case 3. Reference to a method.
4733 def::DefStaticMethod(_, providence) |
4734 def::DefMethod(_, _, providence) => {
4735 assert!(path.segments.len() >= 2);
4738 def::FromTrait(trait_did) => {
4739 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4741 def::FromImpl(_) => {}
4744 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4745 segment_spaces.push(Some(subst::TypeSpace));
4746 segment_spaces.push(Some(subst::FnSpace));
4749 // Other cases. Various nonsense that really shouldn't show up
4750 // here. If they do, an error will have been reported
4751 // elsewhere. (I hope)
4753 def::DefForeignMod(..) |
4756 def::DefRegion(..) |
4758 def::DefUpvar(..) => {
4759 segment_spaces = repeat(None).take(path.segments.len()).collect();
4762 assert_eq!(segment_spaces.len(), path.segments.len());
4764 debug!("segment_spaces={:?}", segment_spaces);
4766 // Next, examine the definition, and determine how many type
4767 // parameters we expect from each space.
4768 let type_defs = &type_scheme.generics.types;
4769 let region_defs = &type_scheme.generics.regions;
4771 // Now that we have categorized what space the parameters for each
4772 // segment belong to, let's sort out the parameters that the user
4773 // provided (if any) into their appropriate spaces. We'll also report
4774 // errors if type parameters are provided in an inappropriate place.
4775 let mut substs = Substs::empty();
4776 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4779 report_error_if_segment_contains_type_parameters(fcx, segment);
4783 push_explicit_parameters_from_segment_to_substs(fcx,
4793 if let Some(self_ty) = opt_self_ty {
4794 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4795 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4796 substs.types.push(subst::SelfSpace, self_ty);
4799 // Now we have to compare the types that the user *actually*
4800 // provided against the types that were *expected*. If the user
4801 // did not provide any types, then we want to substitute inference
4802 // variables. If the user provided some types, we may still need
4803 // to add defaults. If the user provided *too many* types, that's
4805 for &space in ParamSpace::all().iter() {
4806 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4807 assert_eq!(substs.types.len(space), type_defs.len(space));
4809 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4810 assert_eq!(substs.regions().len(space), region_defs.len(space));
4813 // The things we are substituting into the type should not contain
4814 // escaping late-bound regions, and nor should the base type scheme.
4815 assert!(!substs.has_regions_escaping_depth(0));
4816 assert!(!type_scheme.has_escaping_regions());
4818 // Add all the obligations that are required, substituting and
4819 // normalized appropriately.
4820 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4821 fcx.add_obligations_for_parameters(
4822 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4825 // Substitute the values for the type parameters into the type of
4826 // the referenced item.
4827 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4829 fcx.write_ty(node_id, ty_substituted);
4830 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4833 fn report_error_if_segment_contains_type_parameters(
4835 segment: &ast::PathSegment)
4837 for typ in segment.parameters.types().iter() {
4838 span_err!(fcx.tcx().sess, typ.span, E0085,
4839 "type parameters may not appear here");
4843 for lifetime in segment.parameters.lifetimes().iter() {
4844 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4845 "lifetime parameters may not appear here");
4850 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4851 /// parameters are provided, then reports an error and clears the output vector.
4853 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4854 /// use inference variables. This seems less likely to lead to derived errors.
4856 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4857 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4858 /// here because we can easily use the precise span of the N+1'th parameter.
4859 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4860 fcx: &FnCtxt<'a, 'tcx>,
4861 space: subst::ParamSpace,
4863 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4864 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4865 segment: &ast::PathSegment,
4866 substs: &mut Substs<'tcx>)
4868 match segment.parameters {
4869 ast::AngleBracketedParameters(ref data) => {
4870 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4871 fcx, space, type_defs, region_defs, data, substs);
4874 ast::ParenthesizedParameters(ref data) => {
4875 fcx.tcx().sess.span_err(
4877 "parenthesized parameters may only be used with a trait");
4878 push_explicit_parenthesized_parameters_from_segment_to_substs(
4879 fcx, space, span, type_defs, data, substs);
4884 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4885 fcx: &FnCtxt<'a, 'tcx>,
4886 space: subst::ParamSpace,
4887 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4888 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4889 data: &ast::AngleBracketedParameterData,
4890 substs: &mut Substs<'tcx>)
4893 let type_count = type_defs.len(space);
4894 assert_eq!(substs.types.len(space), 0);
4895 for (i, typ) in data.types.iter().enumerate() {
4896 let t = fcx.to_ty(&**typ);
4898 substs.types.push(space, t);
4899 } else if i == type_count {
4900 span_err!(fcx.tcx().sess, typ.span, E0087,
4901 "too many type parameters provided: \
4902 expected at most {} parameter(s), \
4903 found {} parameter(s)",
4904 type_count, data.types.len());
4905 substs.types.truncate(space, 0);
4911 if data.bindings.len() > 0 {
4912 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4913 "unexpected binding of associated item in expression path \
4914 (only allowed in type paths)");
4918 let region_count = region_defs.len(space);
4919 assert_eq!(substs.regions().len(space), 0);
4920 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4921 let r = ast_region_to_region(fcx.tcx(), lifetime);
4922 if i < region_count {
4923 substs.mut_regions().push(space, r);
4924 } else if i == region_count {
4925 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4926 "too many lifetime parameters provided: \
4927 expected {} parameter(s), found {} parameter(s)",
4929 data.lifetimes.len());
4930 substs.mut_regions().truncate(space, 0);
4938 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4939 /// but intended for `Foo(A,B) -> C` form. This expands to
4940 /// roughly the same thing as `Foo<(A,B),C>`. One important
4941 /// difference has to do with the treatment of anonymous
4942 /// regions, which are translated into bound regions (NYI).
4943 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4944 fcx: &FnCtxt<'a, 'tcx>,
4945 space: subst::ParamSpace,
4947 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4948 data: &ast::ParenthesizedParameterData,
4949 substs: &mut Substs<'tcx>)
4951 let type_count = type_defs.len(space);
4953 span_err!(fcx.tcx().sess, span, E0167,
4954 "parenthesized form always supplies 2 type parameters, \
4955 but only {} parameter(s) were expected",
4959 let input_tys: Vec<Ty> =
4960 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4963 ty::mk_tup(fcx.tcx(), input_tys);
4965 if type_count >= 1 {
4966 substs.types.push(space, tuple_ty);
4969 let output_ty: Option<Ty> =
4970 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4973 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4975 if type_count >= 2 {
4976 substs.types.push(space, output_ty);
4980 fn adjust_type_parameters<'a, 'tcx>(
4981 fcx: &FnCtxt<'a, 'tcx>,
4984 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4985 substs: &mut Substs<'tcx>)
4987 let provided_len = substs.types.len(space);
4988 let desired = defs.get_slice(space);
4989 let required_len = desired.iter()
4990 .take_while(|d| d.default.is_none())
4993 debug!("adjust_type_parameters(space={:?}, \
5002 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5003 assert!(provided_len <= desired.len());
5005 // Nothing specified at all: supply inference variables for
5007 if provided_len == 0 {
5008 substs.types.replace(space,
5009 fcx.infcx().next_ty_vars(desired.len()));
5013 // Too few parameters specified: report an error and use Err
5015 if provided_len < required_len {
5017 if desired.len() != required_len { "at least " } else { "" };
5018 span_err!(fcx.tcx().sess, span, E0089,
5019 "too few type parameters provided: expected {}{} parameter(s) \
5020 , found {} parameter(s)",
5021 qualifier, required_len, provided_len);
5022 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5026 // Otherwise, add in any optional parameters that the user
5027 // omitted. The case of *too many* parameters is handled
5029 // push_explicit_parameters_from_segment_to_substs(). Note
5030 // that the *default* type are expressed in terms of all prior
5031 // parameters, so we have to substitute as we go with the
5032 // partial substitution that we have built up.
5033 for i in range(provided_len, desired.len()) {
5034 let default = desired[i].default.unwrap();
5035 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5036 substs.types.push(space, default);
5038 assert_eq!(substs.types.len(space), desired.len());
5040 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5043 fn adjust_region_parameters(
5047 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5048 substs: &mut Substs)
5050 let provided_len = substs.mut_regions().len(space);
5051 let desired = defs.get_slice(space);
5053 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5054 assert!(provided_len <= desired.len());
5056 // If nothing was provided, just use inference variables.
5057 if provided_len == 0 {
5058 substs.mut_regions().replace(
5060 fcx.infcx().region_vars_for_defs(span, desired));
5064 // If just the right number were provided, everybody is happy.
5065 if provided_len == desired.len() {
5069 // Otherwise, too few were provided. Report an error and then
5070 // use inference variables.
5071 span_err!(fcx.tcx().sess, span, E0090,
5072 "too few lifetime parameters provided: expected {} parameter(s), \
5073 found {} parameter(s)",
5074 desired.len(), provided_len);
5076 substs.mut_regions().replace(
5078 fcx.infcx().region_vars_for_defs(span, desired));
5082 // Resolves `typ` by a single level if `typ` is a type variable. If no
5083 // resolution is possible, then an error is reported.
5084 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5085 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5086 // If `ty` is a type variable, see whether we already know what it is.
5087 ty = fcx.infcx().shallow_resolve(ty);
5089 // If not, try resolve pending fcx obligations. Those can shed light.
5091 // FIXME(#18391) -- This current strategy can lead to bad performance in
5092 // extreme cases. We probably ought to smarter in general about
5093 // only resolving when we need help and only resolving obligations
5094 // will actually help.
5095 if ty::type_is_ty_var(ty) {
5096 vtable::select_fcx_obligations_where_possible(fcx);
5097 ty = fcx.infcx().shallow_resolve(ty);
5101 if ty::type_is_ty_var(ty) {
5102 fcx.type_error_message(sp, |_actual| {
5103 "the type of this value must be known in this \
5104 context".to_string()
5106 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5107 ty = fcx.tcx().types.err;
5113 // Returns true if b contains a break that can exit from b
5114 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5115 // First: is there an unlabeled break immediately
5117 (loop_query(&*b, |e| {
5119 ast::ExprBreak(_) => true,
5123 // Second: is there a labeled break with label
5124 // <id> nested anywhere inside the loop?
5125 (block_query(b, |e| {
5127 ast::ExprBreak(Some(_)) => {
5128 match cx.def_map.borrow().get(&e.id) {
5129 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5137 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5139 tps: &OwnedSlice<ast::TyParam>,
5141 debug!("check_bounds_are_used(n_tps={}, ty={})",
5142 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5144 // make a vector of booleans initially false, set to true when used
5145 if tps.len() == 0u { return; }
5146 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5148 ty::walk_ty(ty, |t| {
5150 ty::ty_param(ParamTy {idx, ..}) => {
5151 debug!("Found use of ty param num {}", idx);
5152 tps_used[idx as uint] = true;
5158 for (i, b) in tps_used.iter().enumerate() {
5160 span_err!(ccx.tcx.sess, span, E0091,
5161 "type parameter `{}` is unused",
5162 token::get_ident(tps[i].ident));
5167 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5168 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5169 let name = token::intern(format!("P{}", n).as_slice());
5170 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5174 let name = token::get_ident(it.ident);
5175 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5176 let split : Vec<&str> = name.get().split('_').collect();
5177 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5179 //We only care about the operation here
5180 let (n_tps, inputs, output) = match split[1] {
5181 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5185 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5187 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5190 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5191 "min" | "umax" | "umin" => {
5192 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5196 (0, Vec::new(), ty::mk_nil(tcx))
5199 span_err!(tcx.sess, it.span, E0092,
5200 "unrecognized atomic operation function: `{}`", op);
5204 (n_tps, inputs, ty::FnConverging(output))
5205 } else if name.get() == "abort" || name.get() == "unreachable" {
5206 (0, Vec::new(), ty::FnDiverging)
5208 let (n_tps, inputs, output) = match name.get() {
5209 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5211 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5212 "init" => (1u, Vec::new(), param(ccx, 0)),
5213 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5214 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5215 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5216 "move_val_init" => {
5219 ty::mk_mut_rptr(tcx,
5220 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5227 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5228 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5231 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5233 Err(s) => { tcx.sess.span_fatal(it.span, &s[]); }
5235 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5237 mutbl: ast::MutImmutable
5239 (1u, Vec::new(), td_ptr)
5241 "type_id" => (1u, Vec::new(), ccx.tcx.types.u64),
5245 ty::mk_ptr(tcx, ty::mt {
5247 mutbl: ast::MutImmutable
5251 ty::mk_ptr(tcx, ty::mt {
5253 mutbl: ast::MutImmutable
5256 "copy_memory" | "copy_nonoverlapping_memory" |
5257 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5260 ty::mk_ptr(tcx, ty::mt {
5262 mutbl: ast::MutMutable
5264 ty::mk_ptr(tcx, ty::mt {
5266 mutbl: ast::MutImmutable
5272 "set_memory" | "volatile_set_memory" => {
5275 ty::mk_ptr(tcx, ty::mt {
5277 mutbl: ast::MutMutable
5284 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5285 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5288 vec!( tcx.types.f32, tcx.types.i32 ),
5293 vec!( tcx.types.f64, tcx.types.i32 ),
5296 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5297 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5298 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5299 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5302 vec!( tcx.types.f32, tcx.types.f32 ),
5307 vec!( tcx.types.f64, tcx.types.f64 ),
5310 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5311 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5312 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5313 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5314 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5315 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5316 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5317 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5318 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5319 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5322 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5327 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5330 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5331 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5332 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5333 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5334 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5335 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5336 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5337 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5338 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5339 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5340 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5341 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5342 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5343 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5344 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5345 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5346 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5347 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5348 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5349 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5350 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5351 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5352 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5353 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5354 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5355 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5356 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5357 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5358 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5359 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5360 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5363 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5365 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5367 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5368 (0, vec!(tcx.types.i8, tcx.types.i8),
5369 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5371 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5372 (0, vec!(tcx.types.i16, tcx.types.i16),
5373 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5375 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5376 (0, vec!(tcx.types.i32, tcx.types.i32),
5377 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5379 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5380 (0, vec!(tcx.types.i64, tcx.types.i64),
5381 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5383 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5384 (0, vec!(tcx.types.u8, tcx.types.u8),
5385 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5387 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5388 (0, vec!(tcx.types.u16, tcx.types.u16),
5389 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5391 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5392 (0, vec!(tcx.types.u32, tcx.types.u32),
5393 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5395 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5396 (0, vec!(tcx.types.u64, tcx.types.u64),
5397 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5399 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5401 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5404 span_err!(tcx.sess, it.span, E0093,
5405 "unrecognized intrinsic function: `{}`", *other);
5409 (n_tps, inputs, ty::FnConverging(output))
5411 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5412 unsafety: ast::Unsafety::Unsafe,
5413 abi: abi::RustIntrinsic,
5414 sig: ty::Binder(FnSig {
5420 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5421 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5422 if i_n_tps != n_tps {
5423 span_err!(tcx.sess, it.span, E0094,
5424 "intrinsic has wrong number of type \
5425 parameters: found {}, expected {}",
5428 require_same_types(tcx,
5435 format!("intrinsic has wrong type: expected `{}`",
5436 ppaux::ty_to_string(ccx.tcx, fty))