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 span_err!(ccx.tcx.sess, attr.span, E0230,
805 "there is no type parameter \
807 s, item.ident.as_str());
810 // `{:1}` and `{}` are not to be used
811 Position::ArgumentIs(_) | Position::ArgumentNext => {
812 span_err!(ccx.tcx.sess, attr.span, E0231,
813 "only named substitution \
814 parameters are allowed");
820 span_err!(ccx.tcx.sess, attr.span, E0232,
821 "this attribute must have a value, \
822 eg `#[rustc_on_unimplemented = \"foo\"]`")
827 /// Type checks a method body.
831 /// * `item_generics`: generics defined on the impl/trait that contains
833 /// * `self_bound`: bound for the `Self` type parameter, if any
834 /// * `method`: the method definition
835 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
836 item_generics: &ty::Generics<'tcx>,
837 method: &ast::Method) {
838 debug!("check_method_body(item_generics={}, method.id={})",
839 item_generics.repr(ccx.tcx),
841 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
843 let fty = ty::node_id_to_type(ccx.tcx, method.id);
844 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
847 &*method.pe_fn_decl(),
854 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
856 impl_trait_ref: &ty::TraitRef<'tcx>,
857 impl_items: &[ast::ImplItem]) {
858 // Locate trait methods
860 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
862 // Check existing impl methods to see if they are both present in trait
863 // and compatible with trait signature
864 for impl_item in impl_items.iter() {
866 ast::MethodImplItem(ref impl_method) => {
867 let impl_method_def_id = local_def(impl_method.id);
868 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
871 // If this is an impl of a trait method, find the
872 // corresponding method definition in the trait.
873 let opt_trait_method_ty =
875 .find(|ti| ti.name() == impl_item_ty.name());
876 match opt_trait_method_ty {
877 Some(trait_method_ty) => {
878 match (trait_method_ty, &impl_item_ty) {
879 (&ty::MethodTraitItem(ref trait_method_ty),
880 &ty::MethodTraitItem(ref impl_method_ty)) => {
881 compare_impl_method(ccx.tcx,
884 impl_method.pe_body().id,
889 // This is span_bug as it should have already been
890 // caught in resolve.
893 format!("item `{}` is of a different kind from its trait `{}`",
894 token::get_name(impl_item_ty.name()),
895 impl_trait_ref.repr(tcx)).as_slice());
900 // This is span_bug as it should have already been
901 // caught in resolve.
904 format!("method `{}` is not a member of trait `{}`",
905 token::get_name(impl_item_ty.name()),
906 impl_trait_ref.repr(tcx)).as_slice());
910 ast::TypeImplItem(ref typedef) => {
911 let typedef_def_id = local_def(typedef.id);
912 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
915 // If this is an impl of an associated type, find the
916 // corresponding type definition in the trait.
917 let opt_associated_type =
919 .find(|ti| ti.name() == typedef_ty.name());
920 match opt_associated_type {
921 Some(associated_type) => {
922 match (associated_type, &typedef_ty) {
923 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
925 // This is `span_bug` as it should have
926 // already been caught in resolve.
929 format!("item `{}` is of a different kind from its trait `{}`",
930 token::get_name(typedef_ty.name()),
931 impl_trait_ref.repr(tcx)).as_slice());
936 // This is `span_bug` as it should have already been
937 // caught in resolve.
941 "associated type `{}` is not a member of \
943 token::get_name(typedef_ty.name()),
944 impl_trait_ref.repr(tcx)).as_slice());
951 // Check for missing items from trait
952 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
953 let mut missing_methods = Vec::new();
954 for trait_item in trait_items.iter() {
956 ty::MethodTraitItem(ref trait_method) => {
958 impl_items.iter().any(|ii| {
960 ast::MethodImplItem(ref m) => {
961 m.pe_ident().name == trait_method.name
963 ast::TypeImplItem(_) => false,
967 provided_methods.iter().any(|m| m.name == trait_method.name);
968 if !is_implemented && !is_provided {
969 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
972 ty::TypeTraitItem(ref associated_type) => {
973 let is_implemented = impl_items.iter().any(|ii| {
975 ast::TypeImplItem(ref typedef) => {
976 typedef.ident.name == associated_type.name
978 ast::MethodImplItem(_) => false,
982 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
988 if !missing_methods.is_empty() {
989 span_err!(tcx.sess, impl_span, E0046,
990 "not all trait items implemented, missing: {}",
991 missing_methods.connect(", "));
995 fn check_cast(fcx: &FnCtxt,
996 cast_expr: &ast::Expr,
999 let id = cast_expr.id;
1000 let span = cast_expr.span;
1002 // Find the type of `e`. Supply hints based on the type we are casting to,
1004 let t_1 = fcx.to_ty(t);
1005 let t_1 = structurally_resolved_type(fcx, span, t_1);
1007 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1009 let t_e = fcx.expr_ty(e);
1011 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1012 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1014 if ty::type_is_error(t_e) {
1015 fcx.write_error(id);
1019 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1020 let tstr = fcx.infcx().ty_to_string(t_1);
1021 fcx.type_error_message(span, |actual| {
1022 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1025 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1026 let mtstr = match mt {
1027 ast::MutMutable => "mut ",
1028 ast::MutImmutable => ""
1030 if ty::type_is_trait(t_1) {
1031 span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr);
1033 span_help!(fcx.tcx().sess, span,
1034 "consider using an implicit coercion to `&{}{}` instead",
1038 ty::ty_uniq(..) => {
1039 span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr);
1042 span_help!(fcx.tcx().sess, e.span,
1043 "consider using a box or reference as appropriate");
1046 fcx.write_error(id);
1050 if ty::type_is_trait(t_1) {
1051 // This will be looked up later on.
1052 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1053 fcx.write_ty(id, t_1);
1057 let t_1 = structurally_resolved_type(fcx, span, t_1);
1058 let t_e = structurally_resolved_type(fcx, span, t_e);
1060 if ty::type_is_nil(t_e) {
1061 fcx.type_error_message(span, |actual| {
1062 format!("cast from nil: `{}` as `{}`",
1064 fcx.infcx().ty_to_string(t_1))
1066 } else if ty::type_is_nil(t_1) {
1067 fcx.type_error_message(span, |actual| {
1068 format!("cast to nil: `{}` as `{}`",
1070 fcx.infcx().ty_to_string(t_1))
1074 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1076 let t_1_is_scalar = ty::type_is_scalar(t_1);
1077 let t_1_is_char = ty::type_is_char(t_1);
1078 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1079 let t_1_is_float = ty::type_is_floating_point(t_1);
1081 // casts to scalars other than `char` and `bare fn` are trivial
1082 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1083 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1084 demand::coerce(fcx, e.span, t_1, &*e);
1085 } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1086 if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
1087 fcx.type_error_message(span, |actual| {
1088 format!("illegal cast; cast through an \
1089 integer first: `{}` as `{}`",
1091 fcx.infcx().ty_to_string(t_1))
1094 // casts from C-like enums are allowed
1095 } else if t_1_is_char {
1096 let t_e = fcx.infcx().shallow_resolve(t_e);
1097 if t_e.sty != ty::ty_uint(ast::TyU8) {
1098 fcx.type_error_message(span, |actual| {
1099 format!("only `u8` can be cast as \
1100 `char`, not `{}`", actual)
1103 } else if t_1.sty == ty::ty_bool {
1104 span_err!(fcx.tcx().sess, span, E0054,
1105 "cannot cast as `bool`, compare with zero instead");
1106 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1107 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1108 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1110 ty::ty_vec(_, Some(_)) => {}
1113 if ty::type_needs_infer(t2) {
1114 // This prevents this special case from going off when casting
1115 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1120 let el = ty::sequence_element_type(fcx.tcx(), t1);
1121 infer::mk_eqty(fcx.infcx(),
1128 // Due to the limitations of LLVM global constants,
1129 // region pointers end up pointing at copies of
1130 // vector elements instead of the original values.
1131 // To allow unsafe pointers to work correctly, we
1132 // need to special-case obtaining an unsafe pointer
1133 // from a region pointer to a vector.
1135 /* this cast is only allowed from &[T, ..n] to *T or
1137 match (&t_e.sty, &t_1.sty) {
1138 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1139 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1140 if types_compatible(fcx, e.span, mt1, mt2) => {
1141 /* this case is allowed */
1144 demand::coerce(fcx, e.span, t_1, &*e);
1147 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1149 If more type combinations should be supported than are
1150 supported here, then file an enhancement issue and
1151 record the issue number in this comment.
1153 fcx.type_error_message(span, |actual| {
1154 format!("non-scalar cast: `{}` as `{}`",
1156 fcx.infcx().ty_to_string(t_1))
1158 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1159 fcx.type_error_message(span, |actual| {
1160 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1163 fcx.infcx().ty_to_string(t_1))
1167 fcx.write_ty(id, t_1);
1170 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1171 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1173 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1174 ty::lookup_item_type(self.tcx(), id)
1177 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1178 ty::lookup_trait_def(self.tcx(), id)
1181 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1182 Some(&self.inh.param_env.free_substs)
1185 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1186 self.infcx().next_ty_var()
1189 fn projected_ty_from_poly_trait_ref(&self,
1191 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1192 item_name: ast::Name)
1195 let (trait_ref, _) =
1196 self.infcx().replace_late_bound_regions_with_fresh_var(
1198 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1201 self.normalize_associated_type(span, trait_ref, item_name)
1204 fn projected_ty(&self,
1206 trait_ref: Rc<ty::TraitRef<'tcx>>,
1207 item_name: ast::Name)
1210 self.normalize_associated_type(span, trait_ref, item_name)
1214 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1215 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1217 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1221 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1225 pub fn sess(&self) -> &Session {
1229 pub fn err_count_since_creation(&self) -> uint {
1230 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1233 /// Resolves all type variables in `t` and then, if any were left
1234 /// unresolved, substitutes an error type. This is used after the
1235 /// main checking when doing a second pass before writeback. The
1236 /// justification is that writeback will produce an error for
1237 /// these unconstrained type variables.
1238 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1239 let t = self.infcx().resolve_type_vars_if_possible(t);
1240 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1243 pub fn tag(&self) -> String {
1244 format!("{:?}", self as *const FnCtxt)
1247 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1248 match self.inh.locals.borrow().get(&nid) {
1251 self.tcx().sess.span_bug(
1253 &format!("no type for local variable {}",
1259 /// Apply "fallbacks" to some types
1260 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1261 pub fn default_type_parameters(&self) {
1262 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1263 for (_, &mut ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1264 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1265 if self.infcx().type_var_diverges(resolved) {
1266 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1268 match self.infcx().type_is_unconstrained_numeric(resolved) {
1269 UnconstrainedInt => {
1270 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1272 UnconstrainedFloat => {
1273 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1282 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1283 debug!("write_ty({}, {}) in fcx {}",
1284 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1285 self.inh.node_types.borrow_mut().insert(node_id, ty);
1288 pub fn write_object_cast(&self,
1290 trait_ref: ty::PolyTraitRef<'tcx>) {
1291 debug!("write_object_cast key={} trait_ref={}",
1292 key, trait_ref.repr(self.tcx()));
1293 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1296 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1297 if !substs.substs.is_noop() {
1298 debug!("write_substs({}, {}) in fcx {}",
1300 substs.repr(self.tcx()),
1303 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1307 pub fn write_autoderef_adjustment(&self,
1308 node_id: ast::NodeId,
1311 if derefs == 0 { return; }
1312 self.write_adjustment(
1315 ty::AdjustDerefRef(ty::AutoDerefRef {
1321 pub fn write_adjustment(&self,
1322 node_id: ast::NodeId,
1324 adj: ty::AutoAdjustment<'tcx>) {
1325 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1327 if adj.is_identity() {
1331 // Careful: adjustments can imply trait obligations if we are
1332 // casting from a concrete type to an object type. I think
1333 // it'd probably be nicer to move the logic that creates the
1334 // obligation into the code that creates the adjustment, but
1335 // that's a bit awkward, so instead we go digging and pull the
1336 // obligation out here.
1337 self.register_adjustment_obligations(span, &adj);
1338 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1341 /// Basically whenever we are converting from a type scheme into
1342 /// the fn body space, we always want to normalize associated
1343 /// types as well. This function combines the two.
1344 fn instantiate_type_scheme<T>(&self,
1346 substs: &Substs<'tcx>,
1349 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1351 let value = value.subst(self.tcx(), substs);
1352 let result = self.normalize_associated_types_in(span, &value);
1353 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1354 value.repr(self.tcx()),
1355 substs.repr(self.tcx()),
1356 result.repr(self.tcx()));
1360 /// As `instantiate_type_scheme`, but for the bounds found in a
1361 /// generic type scheme.
1362 fn instantiate_bounds(&self,
1364 substs: &Substs<'tcx>,
1365 generics: &ty::Generics<'tcx>)
1366 -> ty::GenericBounds<'tcx>
1369 predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
1374 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1375 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1377 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1380 fn normalize_associated_type(&self,
1382 trait_ref: Rc<ty::TraitRef<'tcx>>,
1383 item_name: ast::Name)
1386 let cause = traits::ObligationCause::new(span,
1388 traits::ObligationCauseCode::MiscObligation);
1389 self.inh.fulfillment_cx
1391 .normalize_projection_type(self.infcx(),
1394 trait_ref: trait_ref,
1395 item_name: item_name,
1400 fn register_adjustment_obligations(&self,
1402 adj: &ty::AutoAdjustment<'tcx>) {
1404 ty::AdjustReifyFnPointer(..) => {
1406 ty::AdjustDerefRef(ref d_r) => {
1409 self.register_autoref_obligations(span, a_r);
1417 fn register_autoref_obligations(&self,
1419 autoref: &ty::AutoRef<'tcx>) {
1421 ty::AutoUnsize(ref unsize) => {
1422 self.register_unsize_obligations(span, unsize);
1424 ty::AutoPtr(_, _, None) |
1425 ty::AutoUnsafe(_, None) => {
1427 ty::AutoPtr(_, _, Some(ref a_r)) |
1428 ty::AutoUnsafe(_, Some(ref a_r)) => {
1429 self.register_autoref_obligations(span, &**a_r)
1431 ty::AutoUnsizeUniq(ref unsize) => {
1432 self.register_unsize_obligations(span, unsize);
1437 fn register_unsize_obligations(&self,
1439 unsize: &ty::UnsizeKind<'tcx>) {
1440 debug!("register_unsize_obligations: unsize={:?}", unsize);
1443 ty::UnsizeLength(..) => {}
1444 ty::UnsizeStruct(ref u, _) => {
1445 self.register_unsize_obligations(span, &**u)
1447 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1448 vtable::check_object_safety(self.tcx(), ty_trait, span);
1450 // If the type is `Foo+'a`, ensures that the type
1451 // being cast to `Foo+'a` implements `Foo`:
1452 vtable::register_object_cast_obligations(self,
1457 // If the type is `Foo+'a`, ensures that the type
1458 // being cast to `Foo+'a` outlives `'a`:
1459 let cause = traits::ObligationCause { span: span,
1460 body_id: self.body_id,
1461 code: traits::ObjectCastObligation(self_ty) };
1462 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1467 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1468 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1469 /// Registers any trait obligations specified on `def_id` at the same time.
1471 /// Note that function is only intended to be used with types (notably, not fns). This is
1472 /// because it doesn't do any instantiation of late-bound regions.
1473 pub fn instantiate_type(&self,
1476 -> TypeAndSubsts<'tcx>
1479 ty::lookup_item_type(self.tcx(), def_id);
1481 self.infcx().fresh_substs_for_generics(
1483 &type_scheme.generics);
1485 self.instantiate_bounds(span, &substs, &type_scheme.generics);
1486 self.add_obligations_for_parameters(
1487 traits::ObligationCause::new(
1490 traits::ItemObligation(def_id)),
1493 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1501 /// Returns the type that this AST path refers to. If the path has no type
1502 /// parameters and the corresponding type has type parameters, fresh type
1503 /// and/or region variables are substituted.
1505 /// This is used when checking the constructor in struct literals.
1506 fn instantiate_struct_literal_ty(&self,
1509 -> TypeAndSubsts<'tcx>
1511 let tcx = self.tcx();
1513 let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
1516 generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1518 let needs_defaults =
1520 path.segments.iter().all(|s| s.parameters.is_empty());
1522 let substs = if needs_defaults {
1524 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1526 self.infcx().region_vars_for_defs(path.span,
1527 generics.regions.get_slice(TypeSpace));
1528 Substs::new_type(tps, rps)
1530 astconv::ast_path_substs_for_ty(self, self, &generics, path)
1533 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1535 TypeAndSubsts { substs: substs, ty: ty }
1538 pub fn write_nil(&self, node_id: ast::NodeId) {
1539 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1541 pub fn write_error(&self, node_id: ast::NodeId) {
1542 self.write_ty(node_id, self.tcx().types.err);
1545 pub fn require_type_meets(&self,
1548 code: traits::ObligationCauseCode<'tcx>,
1549 bound: ty::BuiltinBound)
1551 self.register_builtin_bound(
1554 traits::ObligationCause::new(span, self.body_id, code));
1557 pub fn require_type_is_sized(&self,
1560 code: traits::ObligationCauseCode<'tcx>)
1562 self.require_type_meets(ty, span, code, ty::BoundSized);
1565 pub fn require_expr_have_sized_type(&self,
1567 code: traits::ObligationCauseCode<'tcx>)
1569 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1572 pub fn type_is_known_to_be_sized(&self,
1577 traits::type_known_to_meet_builtin_bound(self.infcx(),
1584 pub fn register_builtin_bound(&self,
1586 builtin_bound: ty::BuiltinBound,
1587 cause: traits::ObligationCause<'tcx>)
1589 self.inh.fulfillment_cx.borrow_mut()
1590 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1593 pub fn register_predicate(&self,
1594 obligation: traits::PredicateObligation<'tcx>)
1596 debug!("register_predicate({})",
1597 obligation.repr(self.tcx()));
1598 self.inh.fulfillment_cx
1600 .register_predicate_obligation(self.infcx(), obligation);
1603 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1604 let t = ast_ty_to_ty(self, self, ast_t);
1606 let mut bounds_checker = wf::BoundsChecker::new(self,
1608 CodeExtent::from_node_id(self.body_id),
1610 bounds_checker.check_ty(t);
1615 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1616 pat.repr(self.tcx())
1619 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1620 match self.inh.node_types.borrow().get(&ex.id) {
1623 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1629 /// Apply `adjustment` to the type of `expr`
1630 pub fn adjust_expr_ty(&self,
1632 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1635 let raw_ty = self.expr_ty(expr);
1636 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1637 ty::adjust_ty(self.tcx(),
1642 |method_call| self.inh.method_map.borrow()
1644 .map(|method| method.ty))
1647 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1648 match self.inh.node_types.borrow().get(&id) {
1650 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1652 self.tcx().sess.bug(
1653 &format!("no type for node {}: {} in fcx {}",
1654 id, self.tcx().map.node_to_string(id),
1660 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1661 self.inh.item_substs.borrow()
1664 pub fn opt_node_ty_substs<F>(&self,
1667 F: FnOnce(&ty::ItemSubsts<'tcx>),
1669 match self.inh.item_substs.borrow().get(&id) {
1675 pub fn mk_subty(&self,
1676 a_is_expected: bool,
1677 origin: infer::TypeOrigin,
1680 -> Result<(), ty::type_err<'tcx>> {
1681 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1684 pub fn mk_assignty(&self,
1688 -> Result<(), ty::type_err<'tcx>> {
1689 match infer::mk_coercety(self.infcx(),
1691 infer::ExprAssignable(expr.span),
1695 Err(ref e) => Err((*e)),
1696 Ok(Some(adjustment)) => {
1697 self.write_adjustment(expr.id, expr.span, adjustment);
1703 pub fn mk_eqty(&self,
1704 a_is_expected: bool,
1705 origin: infer::TypeOrigin,
1708 -> Result<(), ty::type_err<'tcx>> {
1709 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1712 pub fn mk_subr(&self,
1713 origin: infer::SubregionOrigin<'tcx>,
1716 infer::mk_subr(self.infcx(), origin, sub, sup)
1719 pub fn type_error_message<M>(&self,
1722 actual_ty: Ty<'tcx>,
1723 err: Option<&ty::type_err<'tcx>>) where
1724 M: FnOnce(String) -> String,
1726 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1729 pub fn report_mismatched_types(&self,
1733 err: &ty::type_err<'tcx>) {
1734 self.infcx().report_mismatched_types(sp, e, a, err)
1737 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1738 /// outlive the region `r`.
1739 pub fn register_region_obligation(&self,
1742 cause: traits::ObligationCause<'tcx>)
1744 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1745 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1748 pub fn add_default_region_param_bounds(&self,
1749 substs: &Substs<'tcx>,
1752 for &ty in substs.types.iter() {
1753 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1754 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1755 traits::MiscObligation);
1756 self.register_region_obligation(ty, default_bound, cause);
1760 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1761 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1762 /// trait/region obligations.
1764 /// For example, if there is a function:
1767 /// fn foo<'a,T:'a>(...)
1770 /// and a reference:
1776 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1777 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1778 pub fn add_obligations_for_parameters(&self,
1779 cause: traits::ObligationCause<'tcx>,
1780 generic_bounds: &ty::GenericBounds<'tcx>)
1782 assert!(!generic_bounds.has_escaping_regions());
1784 debug!("add_obligations_for_parameters(generic_bounds={})",
1785 generic_bounds.repr(self.tcx()));
1787 let obligations = traits::predicates_for_generics(self.tcx(),
1791 obligations.map_move(|o| self.register_predicate(o));
1794 // Only for fields! Returns <none> for methods>
1795 // Indifferent to privacy flags
1796 pub fn lookup_field_ty(&self,
1798 class_id: ast::DefId,
1799 items: &[ty::field_ty],
1800 fieldname: ast::Name,
1801 substs: &subst::Substs<'tcx>)
1804 let o_field = items.iter().find(|f| f.name == fieldname);
1805 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1806 .map(|t| self.normalize_associated_types_in(span, &t))
1809 pub fn lookup_tup_field_ty(&self,
1811 class_id: ast::DefId,
1812 items: &[ty::field_ty],
1814 substs: &subst::Substs<'tcx>)
1817 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1818 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1819 .map(|t| self.normalize_associated_types_in(span, &t))
1823 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1824 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1825 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1828 fn anon_regions(&self, span: Span, count: uint)
1829 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1830 Ok(range(0, count).map(|_| {
1831 self.infcx().next_region_var(infer::MiscVariable(span))
1836 #[derive(Copy, Show, PartialEq, Eq)]
1837 pub enum LvaluePreference {
1842 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1843 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1845 /// Note: this method does not modify the adjustments table. The caller is responsible for
1846 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1847 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1850 opt_expr: Option<&ast::Expr>,
1851 mut lvalue_pref: LvaluePreference,
1853 -> (Ty<'tcx>, uint, Option<T>)
1854 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1856 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1857 base_ty.repr(fcx.tcx()),
1858 opt_expr.repr(fcx.tcx()),
1861 let mut t = base_ty;
1862 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1863 let resolved_t = structurally_resolved_type(fcx, sp, t);
1865 if ty::type_is_error(resolved_t) {
1866 return (resolved_t, autoderefs, None);
1869 match should_stop(resolved_t, autoderefs) {
1870 Some(x) => return (resolved_t, autoderefs, Some(x)),
1874 // Otherwise, deref if type is derefable:
1875 let mt = match ty::deref(resolved_t, false) {
1876 Some(mt) => Some(mt),
1878 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1880 // Super subtle: it might seem as though we should
1881 // pass `opt_expr` to `try_overloaded_deref`, so that
1882 // the (implicit) autoref of using an overloaded deref
1883 // would get added to the adjustment table. However we
1884 // do not do that, because it's kind of a
1885 // "meta-adjustment" -- instead, we just leave it
1886 // unrecorded and know that there "will be" an
1887 // autoref. regionck and other bits of the code base,
1888 // when they encounter an overloaded autoderef, have
1889 // to do some reconstructive surgery. This is a pretty
1890 // complex mess that is begging for a proper MIR.
1891 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1897 if mt.mutbl == ast::MutImmutable {
1898 lvalue_pref = NoPreference;
1901 None => return (resolved_t, autoderefs, None)
1905 // We've reached the recursion limit, error gracefully.
1906 span_err!(fcx.tcx().sess, sp, E0055,
1907 "reached the recursion limit while auto-dereferencing {}",
1908 base_ty.repr(fcx.tcx()));
1909 (fcx.tcx().types.err, 0, None)
1912 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1914 method_call: Option<MethodCall>,
1915 base_expr: Option<&ast::Expr>,
1917 lvalue_pref: LvaluePreference)
1918 -> Option<ty::mt<'tcx>>
1920 // Try DerefMut first, if preferred.
1921 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1922 (PreferMutLvalue, Some(trait_did)) => {
1923 method::lookup_in_trait(fcx, span, base_expr,
1924 token::intern("deref_mut"), trait_did,
1930 // Otherwise, fall back to Deref.
1931 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1932 (None, Some(trait_did)) => {
1933 method::lookup_in_trait(fcx, span, base_expr,
1934 token::intern("deref"), trait_did,
1937 (method, _) => method
1940 make_overloaded_lvalue_return_type(fcx, method_call, method)
1943 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
1944 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
1945 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
1946 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1947 method_call: Option<MethodCall>,
1948 method: Option<MethodCallee<'tcx>>)
1949 -> Option<ty::mt<'tcx>>
1953 let ref_ty = // invoked methods have all LB regions instantiated
1954 ty::assert_no_late_bound_regions(
1955 fcx.tcx(), &ty::ty_fn_ret(method.ty));
1957 Some(method_call) => {
1958 fcx.inh.method_map.borrow_mut().insert(method_call,
1964 ty::FnConverging(ref_ty) => {
1965 ty::deref(ref_ty, true)
1967 ty::FnDiverging => {
1968 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
1976 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1977 base_expr: &ast::Expr,
1979 lvalue_pref: LvaluePreference,
1982 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
1984 // FIXME(#18741) -- this is almost but not quite the same as the
1985 // autoderef that normal method probing does. They could likely be
1988 let (ty, autoderefs, final_mt) =
1989 autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
1990 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
1991 step(adj_ty, autoderefref)
1994 if final_mt.is_some() {
1998 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
1999 // do a final unsized coercion to yield [T].
2001 ty::ty_vec(element_ty, Some(n)) => {
2002 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2003 let autoderefref = ty::AutoDerefRef {
2004 autoderefs: autoderefs,
2005 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2007 step(adjusted_ty, autoderefref)
2015 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2016 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2017 /// This loop implements one step in that search; the autoderef loop is implemented by
2018 /// `autoderef_for_index`.
2019 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2020 method_call: MethodCall,
2022 base_expr: &ast::Expr,
2023 adjusted_ty: Ty<'tcx>,
2024 adjustment: ty::AutoDerefRef<'tcx>,
2025 lvalue_pref: LvaluePreference,
2027 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2029 let tcx = fcx.tcx();
2030 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2032 base_expr.repr(tcx),
2033 adjusted_ty.repr(tcx),
2035 index_ty.repr(tcx));
2037 let input_ty = fcx.infcx().next_ty_var();
2039 // First, try built-in indexing.
2040 match (ty::index(adjusted_ty), &index_ty.sty) {
2041 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2042 debug!("try_index_step: success, using built-in indexing");
2043 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2044 return Some((tcx.types.uint, ty));
2049 // Try `IndexMut` first, if preferred.
2050 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2051 (PreferMutLvalue, Some(trait_did)) => {
2052 method::lookup_in_trait_adjusted(fcx,
2055 token::intern("index_mut"),
2059 Some(vec![input_ty]))
2064 // Otherwise, fall back to `Index`.
2065 let method = match (method, tcx.lang_items.index_trait()) {
2066 (None, Some(trait_did)) => {
2067 method::lookup_in_trait_adjusted(fcx,
2070 token::intern("index"),
2074 Some(vec![input_ty]))
2076 (method, _) => method,
2079 // If some lookup succeeds, write callee into table and extract index/element
2080 // type from the method signature.
2081 // If some lookup succeeded, install method in table
2082 method.and_then(|method| {
2083 debug!("try_index_step: success, using overloaded indexing");
2084 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2085 map(|ret| (input_ty, ret.ty))
2089 /// Given the head of a `for` expression, looks up the `next` method in the
2090 /// `Iterator` trait. Panics if the expression does not implement `next`.
2092 /// The return type of this function represents the concrete element type
2093 /// `A` in the type `Iterator<A>` that the method returns.
2094 fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2095 iterator_expr: &ast::Expr,
2096 loop_id: ast::NodeId)
2098 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2099 Ok(trait_did) => trait_did,
2100 Err(ref err_string) => {
2101 span_err!(fcx.tcx().sess, iterator_expr.span, E0233,
2102 "{}", &err_string[]);
2103 return fcx.tcx().types.err
2107 let expr_type = fcx.expr_ty(&*iterator_expr);
2108 let method = method::lookup_in_trait(fcx,
2110 Some(&*iterator_expr),
2111 token::intern("next"),
2116 // Regardless of whether the lookup succeeds, check the method arguments
2117 // so that we have *some* type for each argument.
2118 let method_type = match method {
2119 Some(ref method) => method.ty,
2121 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
2123 if !ty::type_is_error(true_expr_type) {
2124 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2125 span_err!(fcx.tcx().sess, iterator_expr.span, E0234,
2126 "`for` loop expression has type `{}` which does \
2127 not implement the `Iterator` trait; \
2128 maybe try .iter()", ty_string);
2133 let return_type = check_method_argument_types(fcx,
2144 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2147 // We expect the return type to be `Option` or something like it.
2148 // Grab the first parameter of its type substitution.
2149 let return_type = match return_type {
2150 ty::FnConverging(return_type) =>
2151 structurally_resolved_type(fcx, iterator_expr.span, return_type),
2152 ty::FnDiverging => fcx.tcx().types.err
2154 match return_type.sty {
2155 ty::ty_enum(_, ref substs)
2156 if !substs.types.is_empty_in(subst::TypeSpace) => {
2157 *substs.types.get(subst::TypeSpace, 0)
2163 span_err!(fcx.tcx().sess, iterator_expr.span, E0239,
2164 "`next` method of the `Iterator` \
2165 trait has an unexpected type `{}`",
2166 fcx.infcx().ty_to_string(return_type));
2171 None => fcx.tcx().types.err
2175 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2177 method_fn_ty: Ty<'tcx>,
2178 callee_expr: &ast::Expr,
2179 args_no_rcvr: &[P<ast::Expr>],
2180 autoref_args: AutorefArgs,
2181 tuple_arguments: TupleArgumentsFlag,
2182 expected: Expectation<'tcx>)
2183 -> ty::FnOutput<'tcx> {
2184 if ty::type_is_error(method_fn_ty) {
2185 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2187 let err_inputs = match tuple_arguments {
2188 DontTupleArguments => err_inputs,
2189 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2192 check_argument_types(fcx,
2200 ty::FnConverging(fcx.tcx().types.err)
2202 match method_fn_ty.sty {
2203 ty::ty_bare_fn(_, ref fty) => {
2204 // HACK(eddyb) ignore self in the definition (see above).
2205 let expected_arg_tys = expected_types_for_fn_args(fcx,
2209 &fty.sig.0.inputs[1..]);
2210 check_argument_types(fcx,
2212 &fty.sig.0.inputs[1..],
2213 &expected_arg_tys[],
2221 fcx.tcx().sess.span_bug(callee_expr.span,
2222 "method without bare fn type");
2228 /// Generic function that factors out common logic from function calls, method calls and overloaded
2230 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2232 fn_inputs: &[Ty<'tcx>],
2233 expected_arg_tys: &[Ty<'tcx>],
2234 args: &[P<ast::Expr>],
2235 autoref_args: AutorefArgs,
2237 tuple_arguments: TupleArgumentsFlag) {
2238 let tcx = fcx.ccx.tcx;
2240 // Grab the argument types, supplying fresh type variables
2241 // if the wrong number of arguments were supplied
2242 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2248 let mut expected_arg_tys = expected_arg_tys;
2249 let expected_arg_count = fn_inputs.len();
2250 let formal_tys = if tuple_arguments == TupleArguments {
2251 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2252 match tuple_type.sty {
2253 ty::ty_tup(ref arg_types) => {
2254 if arg_types.len() != args.len() {
2255 span_err!(tcx.sess, sp, E0057,
2256 "this function takes {} parameter{} but {} parameter{} supplied",
2258 if arg_types.len() == 1 {""} else {"s"},
2260 if args.len() == 1 {" was"} else {"s were"});
2261 expected_arg_tys = &[][];
2262 err_args(fcx.tcx(), args.len())
2264 expected_arg_tys = match expected_arg_tys.get(0) {
2265 Some(&ty) => match ty.sty {
2266 ty::ty_tup(ref tys) => &**tys,
2271 (*arg_types).clone()
2275 span_err!(tcx.sess, sp, E0059,
2276 "cannot use call notation; the first type parameter \
2277 for the function trait is neither a tuple nor unit");
2278 expected_arg_tys = &[][];
2279 err_args(fcx.tcx(), args.len())
2282 } else if expected_arg_count == supplied_arg_count {
2284 } else if variadic {
2285 if supplied_arg_count >= expected_arg_count {
2288 span_err!(tcx.sess, sp, E0060,
2289 "this function takes at least {} parameter{} \
2290 but {} parameter{} supplied",
2292 if expected_arg_count == 1 {""} else {"s"},
2294 if supplied_arg_count == 1 {" was"} else {"s were"});
2295 expected_arg_tys = &[][];
2296 err_args(fcx.tcx(), supplied_arg_count)
2299 span_err!(tcx.sess, sp, E0061,
2300 "this function takes {} parameter{} but {} parameter{} supplied",
2302 if expected_arg_count == 1 {""} else {"s"},
2304 if supplied_arg_count == 1 {" was"} else {"s were"});
2305 expected_arg_tys = &[][];
2306 err_args(fcx.tcx(), supplied_arg_count)
2309 debug!("check_argument_types: formal_tys={:?}",
2310 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2312 // Check the arguments.
2313 // We do this in a pretty awful way: first we typecheck any arguments
2314 // that are not anonymous functions, then we typecheck the anonymous
2315 // functions. This is so that we have more information about the types
2316 // of arguments when we typecheck the functions. This isn't really the
2317 // right way to do this.
2318 let xs = [false, true];
2319 for check_blocks in xs.iter() {
2320 let check_blocks = *check_blocks;
2321 debug!("check_blocks={}", check_blocks);
2323 // More awful hacks: before we check the blocks, try to do
2324 // an "opportunistic" vtable resolution of any trait
2325 // bounds on the call.
2327 vtable::select_new_fcx_obligations(fcx);
2330 // For variadic functions, we don't have a declared type for all of
2331 // the arguments hence we only do our usual type checking with
2332 // the arguments who's types we do know.
2333 let t = if variadic {
2335 } else if tuple_arguments == TupleArguments {
2340 for (i, arg) in args.iter().take(t).enumerate() {
2341 let is_block = match arg.node {
2342 ast::ExprClosure(..) => true,
2346 if is_block == check_blocks {
2347 debug!("checking the argument");
2348 let mut formal_ty = formal_tys[i];
2350 match autoref_args {
2351 AutorefArgs::Yes => {
2352 match formal_ty.sty {
2353 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2356 // So we hit this case when one implements the
2357 // operator traits but leaves an argument as
2358 // just T instead of &T. We'll catch it in the
2359 // mismatch impl/trait method phase no need to
2362 formal_ty = tcx.types.err;
2366 AutorefArgs::No => {}
2369 // The special-cased logic below has three functions:
2370 // 1. Provide as good of an expected type as possible.
2371 let expected = expected_arg_tys.get(i).map(|&ty| {
2372 Expectation::rvalue_hint(ty)
2375 check_expr_with_unifier(fcx, &**arg,
2376 expected.unwrap_or(ExpectHasType(formal_ty)),
2378 // 2. Coerce to the most detailed type that could be coerced
2379 // to, which is `expected_ty` if `rvalue_hint` returns an
2380 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2381 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2382 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2384 // 3. Relate the expected type and the formal one,
2385 // if the expected type was used for the coercion.
2386 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2392 // We also need to make sure we at least write the ty of the other
2393 // arguments which we skipped above.
2395 for arg in args.iter().skip(expected_arg_count) {
2396 check_expr(fcx, &**arg);
2398 // There are a few types which get autopromoted when passed via varargs
2399 // in C but we just error out instead and require explicit casts.
2400 let arg_ty = structurally_resolved_type(fcx, arg.span,
2401 fcx.expr_ty(&**arg));
2403 ty::ty_float(ast::TyF32) => {
2404 fcx.type_error_message(arg.span,
2406 format!("can't pass an {} to variadic \
2407 function, cast to c_double", t)
2410 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2411 fcx.type_error_message(arg.span, |t| {
2412 format!("can't pass {} to variadic \
2413 function, cast to c_int",
2417 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2418 fcx.type_error_message(arg.span, |t| {
2419 format!("can't pass {} to variadic \
2420 function, cast to c_uint",
2430 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2431 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2432 range(0, len).map(|_| tcx.types.err).collect()
2435 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2436 call_expr: &ast::Expr,
2437 output: ty::FnOutput<'tcx>) {
2438 fcx.write_ty(call_expr.id, match output {
2439 ty::FnConverging(output_ty) => output_ty,
2440 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2444 // AST fragment checking
2445 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2447 expected: Expectation<'tcx>)
2450 let tcx = fcx.ccx.tcx;
2453 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2454 ast::LitBinary(..) => {
2456 tcx.mk_region(ty::ReStatic),
2457 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2459 ast::LitByte(_) => tcx.types.u8,
2460 ast::LitChar(_) => tcx.types.char,
2461 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2462 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2463 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2464 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2466 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2467 ty::ty_char => Some(tcx.types.u8),
2468 ty::ty_ptr(..) => Some(tcx.types.uint),
2469 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2473 opt_ty.unwrap_or_else(
2474 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2476 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2477 ast::LitFloatUnsuffixed(_) => {
2478 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2480 ty::ty_float(_) => Some(ty),
2484 opt_ty.unwrap_or_else(
2485 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2487 ast::LitBool(_) => tcx.types.bool
2491 pub fn valid_range_bounds(ccx: &CrateCtxt,
2495 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2496 Some(val) => Some(val <= 0),
2501 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2503 expected: Ty<'tcx>) {
2504 check_expr_with_unifier(
2505 fcx, expr, ExpectHasType(expected), NoPreference,
2506 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2509 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2511 expected: Ty<'tcx>) {
2512 check_expr_with_unifier(
2513 fcx, expr, ExpectHasType(expected), NoPreference,
2514 || demand::coerce(fcx, expr.span, expected, expr));
2517 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
2518 expected: Ty<'tcx>) {
2519 check_expr_with_unifier(
2520 fcx, expr, ExpectHasType(expected), NoPreference,
2524 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2526 expected: Expectation<'tcx>) {
2527 check_expr_with_unifier(
2528 fcx, expr, expected, NoPreference,
2532 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2534 expected: Expectation<'tcx>,
2535 lvalue_pref: LvaluePreference)
2537 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2540 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2541 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2544 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2545 lvalue_pref: LvaluePreference) {
2546 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2549 // determine the `self` type, using fresh variables for all variables
2550 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2551 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2553 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2554 span: Span, // (potential) receiver for this impl
2556 -> TypeAndSubsts<'tcx> {
2557 let tcx = fcx.tcx();
2559 let ity = ty::lookup_item_type(tcx, did);
2560 let (n_tps, rps, raw_ty) =
2561 (ity.generics.types.len(subst::TypeSpace),
2562 ity.generics.regions.get_slice(subst::TypeSpace),
2565 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2566 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2567 let substs = subst::Substs::new_type(tps, rps);
2568 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2570 TypeAndSubsts { substs: substs, ty: substd_ty }
2573 // Controls whether the arguments are automatically referenced. This is useful
2574 // for overloaded binary and unary operators.
2575 #[derive(Copy, PartialEq)]
2576 pub enum AutorefArgs {
2581 /// Controls whether the arguments are tupled. This is used for the call
2584 /// Tupling means that all call-side arguments are packed into a tuple and
2585 /// passed as a single parameter. For example, if tupling is enabled, this
2588 /// fn f(x: (int, int))
2590 /// Can be called as:
2597 #[derive(Clone, Eq, PartialEq)]
2598 enum TupleArgumentsFlag {
2603 /// Unifies the return type with the expected type early, for more coercions
2604 /// and forward type information on the argument expressions.
2605 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2607 expected_ret: Expectation<'tcx>,
2608 formal_ret: ty::FnOutput<'tcx>,
2609 formal_args: &[Ty<'tcx>])
2611 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2612 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2613 fcx.infcx().commit_regions_if_ok(|| {
2614 // Attempt to apply a subtyping relationship between the formal
2615 // return type (likely containing type variables if the function
2616 // is polymorphic) and the expected return type.
2617 // No argument expectations are produced if unification fails.
2618 let origin = infer::Misc(call_span);
2619 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2620 // FIXME(#15760) can't use try! here, FromError doesn't default
2621 // to identity so the resulting type is not constrained.
2622 if let Err(e) = ures {
2626 // Record all the argument types, with the substitutions
2627 // produced from the above subtyping unification.
2628 Ok(formal_args.iter().map(|ty| {
2629 fcx.infcx().resolve_type_vars_if_possible(ty)
2635 }).unwrap_or(vec![]);
2636 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2637 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2638 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2643 /// If an expression has any sub-expressions that result in a type error,
2644 /// inspecting that expression's type with `ty::type_is_error` will return
2645 /// true. Likewise, if an expression is known to diverge, inspecting its
2646 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2647 /// strict, _|_ can appear in the type of an expression that does not,
2648 /// itself, diverge: for example, fn() -> _|_.)
2649 /// Note that inspecting a type's structure *directly* may expose the fact
2650 /// that there are actually multiple representations for `ty_err`, so avoid
2651 /// that when err needs to be handled differently.
2652 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2654 expected: Expectation<'tcx>,
2655 lvalue_pref: LvaluePreference,
2659 debug!(">> typechecking: expr={} expected={}",
2660 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2662 // Checks a method call.
2663 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2665 method_name: ast::SpannedIdent,
2666 args: &[P<ast::Expr>],
2668 expected: Expectation<'tcx>,
2669 lvalue_pref: LvaluePreference) {
2670 let rcvr = &*args[0];
2671 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2673 // no need to check for bot/err -- callee does that
2674 let expr_t = structurally_resolved_type(fcx,
2676 fcx.expr_ty(&*rcvr));
2678 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2679 let fn_ty = match method::lookup(fcx,
2681 method_name.node.name,
2687 let method_ty = method.ty;
2688 let method_call = MethodCall::expr(expr.id);
2689 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2693 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
2694 fcx.write_error(expr.id);
2699 // Call the generic checker.
2700 let ret_ty = check_method_argument_types(fcx,
2709 write_call(fcx, expr, ret_ty);
2712 // A generic function for checking the then and else in an if
2714 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2715 cond_expr: &ast::Expr,
2716 then_blk: &ast::Block,
2717 opt_else_expr: Option<&ast::Expr>,
2720 expected: Expectation<'tcx>) {
2721 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2723 let expected = expected.adjust_for_branches(fcx);
2724 check_block_with_expected(fcx, then_blk, expected);
2725 let then_ty = fcx.node_ty(then_blk.id);
2727 let branches_ty = match opt_else_expr {
2728 Some(ref else_expr) => {
2729 check_expr_with_expectation(fcx, &**else_expr, expected);
2730 let else_ty = fcx.expr_ty(&**else_expr);
2731 infer::common_supertype(fcx.infcx(),
2732 infer::IfExpression(sp),
2738 infer::common_supertype(fcx.infcx(),
2739 infer::IfExpressionWithNoElse(sp),
2742 ty::mk_nil(fcx.tcx()))
2746 let cond_ty = fcx.expr_ty(cond_expr);
2747 let if_ty = if ty::type_is_error(cond_ty) {
2753 fcx.write_ty(id, if_ty);
2756 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2760 trait_did: Option<ast::DefId>,
2762 rhs: Option<&P<ast::Expr>>,
2764 autoref_args: AutorefArgs) -> Ty<'tcx> where
2767 let method = match trait_did {
2768 Some(trait_did) => {
2769 // We do eager coercions to make using operators
2772 // - If the input is of type &'a T (resp. &'a mut T),
2773 // then reborrow it to &'b T (resp. &'b mut T) where
2774 // 'b <= 'a. This makes things like `x == y`, where
2775 // `x` and `y` are both region pointers, work. We
2776 // could also solve this with variance or different
2777 // traits that don't force left and right to have same
2779 let (adj_ty, adjustment) = match lhs_ty.sty {
2780 ty::ty_rptr(r_in, mt) => {
2781 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2782 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2783 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2784 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2785 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2786 (adjusted_ty, adjustment)
2789 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2793 debug!("adjusted_ty={} adjustment={:?}",
2794 adj_ty.repr(fcx.tcx()),
2797 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2798 trait_did, adjustment, adj_ty, None)
2802 let args = match rhs {
2803 Some(rhs) => slice::ref_slice(rhs),
2808 let method_ty = method.ty;
2809 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2810 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2811 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2812 match check_method_argument_types(fcx,
2820 ty::FnConverging(result_type) => result_type,
2821 ty::FnDiverging => fcx.tcx().types.err
2826 // Check the args anyway
2827 // so we get all the error messages
2828 let expected_ty = fcx.tcx().types.err;
2829 check_method_argument_types(fcx,
2842 // could be either an expr_binop or an expr_assign_binop
2843 fn check_binop(fcx: &FnCtxt,
2848 is_binop_assignment: IsBinopAssignment) {
2849 let tcx = fcx.ccx.tcx;
2851 let lvalue_pref = match is_binop_assignment {
2852 BinopAssignment => PreferMutLvalue,
2853 SimpleBinop => NoPreference
2855 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2857 // Callee does bot / err checking
2858 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2859 fcx.expr_ty(&*lhs));
2861 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2862 // Shift is a special case: rhs must be uint, no matter what lhs is
2863 check_expr(fcx, &**rhs);
2864 let rhs_ty = fcx.expr_ty(&**rhs);
2865 let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
2866 if ty::type_is_integral(rhs_ty) {
2867 fcx.write_ty(expr.id, lhs_t);
2869 fcx.type_error_message(
2873 "right-hand-side of a shift operation must have integral type, \
2879 fcx.write_ty(expr.id, fcx.tcx().types.err);
2884 if ty::is_binopable(tcx, lhs_t, op) {
2885 let tvar = fcx.infcx().next_ty_var();
2886 demand::suptype(fcx, expr.span, tvar, lhs_t);
2887 check_expr_has_type(fcx, &**rhs, tvar);
2889 let result_t = match op {
2890 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2892 if ty::type_is_simd(tcx, lhs_t) {
2893 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2894 fcx.type_error_message(expr.span,
2896 format!("binary comparison \
2897 operation `{}` not \
2898 supported for floating \
2899 point SIMD vector `{}`",
2900 ast_util::binop_to_string(op),
2911 fcx.tcx().types.bool
2917 fcx.write_ty(expr.id, result_t);
2921 if op == ast::BiOr || op == ast::BiAnd {
2922 // This is an error; one of the operands must have the wrong
2924 fcx.write_error(expr.id);
2925 fcx.write_error(rhs.id);
2926 fcx.type_error_message(expr.span,
2928 format!("binary operation `{}` cannot be applied \
2930 ast_util::binop_to_string(op),
2937 // Check for overloaded operators if not an assignment.
2938 let result_t = if is_binop_assignment == SimpleBinop {
2939 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2941 fcx.type_error_message(expr.span,
2943 format!("binary assignment \
2945 cannot be applied to \
2947 ast_util::binop_to_string(op),
2952 check_expr(fcx, &**rhs);
2956 fcx.write_ty(expr.id, result_t);
2957 if ty::type_is_error(result_t) {
2958 fcx.write_ty(rhs.id, result_t);
2962 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2964 lhs_expr: &ast::Expr,
2965 lhs_resolved_t: Ty<'tcx>,
2967 rhs: &P<ast::Expr>) -> Ty<'tcx> {
2968 let tcx = fcx.ccx.tcx;
2969 let lang = &tcx.lang_items;
2970 let (name, trait_did) = match op {
2971 ast::BiAdd => ("add", lang.add_trait()),
2972 ast::BiSub => ("sub", lang.sub_trait()),
2973 ast::BiMul => ("mul", lang.mul_trait()),
2974 ast::BiDiv => ("div", lang.div_trait()),
2975 ast::BiRem => ("rem", lang.rem_trait()),
2976 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2977 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2978 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2979 ast::BiShl => ("shl", lang.shl_trait()),
2980 ast::BiShr => ("shr", lang.shr_trait()),
2981 ast::BiLt => ("lt", lang.ord_trait()),
2982 ast::BiLe => ("le", lang.ord_trait()),
2983 ast::BiGe => ("ge", lang.ord_trait()),
2984 ast::BiGt => ("gt", lang.ord_trait()),
2985 ast::BiEq => ("eq", lang.eq_trait()),
2986 ast::BiNe => ("ne", lang.eq_trait()),
2987 ast::BiAnd | ast::BiOr => {
2988 check_expr(fcx, &**rhs);
2989 return tcx.types.err;
2992 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2993 trait_did, lhs_expr, Some(rhs), || {
2994 fcx.type_error_message(ex.span, |actual| {
2995 format!("binary operation `{}` cannot be applied to type `{}`",
2996 ast_util::binop_to_string(op),
2998 }, lhs_resolved_t, None)
2999 }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3002 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3005 trait_did: Option<ast::DefId>,
3007 rhs_expr: &ast::Expr,
3009 op: ast::UnOp) -> Ty<'tcx> {
3010 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3011 trait_did, rhs_expr, None, || {
3012 fcx.type_error_message(ex.span, |actual| {
3013 format!("cannot apply unary operator `{}` to type `{}`",
3016 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3019 // Check field access expressions
3020 fn check_field(fcx: &FnCtxt,
3022 lvalue_pref: LvaluePreference,
3024 field: &ast::SpannedIdent) {
3025 let tcx = fcx.ccx.tcx;
3026 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3027 let expr_t = structurally_resolved_type(fcx, expr.span,
3029 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3030 let (_, autoderefs, field_ty) =
3031 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3033 ty::ty_struct(base_id, substs) => {
3034 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3035 let fields = ty::lookup_struct_fields(tcx, base_id);
3036 fcx.lookup_field_ty(expr.span, base_id, &fields[],
3037 field.node.name, &(*substs))
3044 fcx.write_ty(expr.id, field_ty);
3045 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3051 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3052 fcx.type_error_message(
3055 format!("attempted to take value of method `{}` on type \
3056 `{}`", token::get_ident(field.node), actual)
3060 tcx.sess.span_help(field.span,
3061 "maybe a `()` to call it is missing? \
3062 If not, try an anonymous function");
3064 fcx.type_error_message(
3067 format!("attempted access of field `{}` on \
3068 type `{}`, but no field with that \
3070 token::get_ident(field.node),
3076 fcx.write_error(expr.id);
3079 // Check tuple index expressions
3080 fn check_tup_field(fcx: &FnCtxt,
3082 lvalue_pref: LvaluePreference,
3084 idx: codemap::Spanned<uint>) {
3085 let tcx = fcx.ccx.tcx;
3086 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3087 let expr_t = structurally_resolved_type(fcx, expr.span,
3089 let mut tuple_like = false;
3090 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3091 let (_, autoderefs, field_ty) =
3092 autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
3094 ty::ty_struct(base_id, substs) => {
3095 tuple_like = ty::is_tuple_struct(tcx, base_id);
3097 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3098 let fields = ty::lookup_struct_fields(tcx, base_id);
3099 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3100 idx.node, &(*substs))
3105 ty::ty_tup(ref v) => {
3107 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3114 fcx.write_ty(expr.id, field_ty);
3115 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3120 fcx.type_error_message(
3124 format!("attempted out-of-bounds tuple index `{}` on \
3129 format!("attempted tuple index `{}` on type `{}`, but the \
3130 type was not a tuple or tuple struct",
3137 fcx.write_error(expr.id);
3140 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3141 struct_ty: Ty<'tcx>,
3143 class_id: ast::DefId,
3144 node_id: ast::NodeId,
3145 substitutions: &'tcx subst::Substs<'tcx>,
3146 field_types: &[ty::field_ty],
3147 ast_fields: &[ast::Field],
3148 check_completeness: bool,
3149 enum_id_opt: Option<ast::DefId>) {
3150 let tcx = fcx.ccx.tcx;
3152 let mut class_field_map = FnvHashMap();
3153 let mut fields_found = 0;
3154 for field in field_types.iter() {
3155 class_field_map.insert(field.name, (field.id, false));
3158 let mut error_happened = false;
3160 // Typecheck each field.
3161 for field in ast_fields.iter() {
3162 let mut expected_field_type = tcx.types.err;
3164 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3167 fcx.type_error_message(
3169 |actual| match enum_id_opt {
3171 let variant_type = ty::enum_variant_with_id(tcx,
3174 format!("struct variant `{}::{}` has no field named `{}`",
3175 actual, variant_type.name.as_str(),
3176 token::get_ident(field.ident.node))
3179 format!("structure `{}` has no field named `{}`",
3181 token::get_ident(field.ident.node))
3186 error_happened = true;
3188 Some((_, true)) => {
3189 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3190 "field `{}` specified more than once",
3191 token::get_ident(field.ident.node));
3192 error_happened = true;
3194 Some((field_id, false)) => {
3195 expected_field_type =
3196 ty::lookup_field_type(
3197 tcx, class_id, field_id, substitutions);
3198 expected_field_type =
3199 fcx.normalize_associated_types_in(
3200 field.span, &expected_field_type);
3201 class_field_map.insert(
3202 field.ident.node.name, (field_id, true));
3207 // Make sure to give a type to the field even if there's
3208 // an error, so we can continue typechecking
3209 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3213 fcx.write_error(node_id);
3216 if check_completeness && !error_happened {
3217 // Make sure the programmer specified all the fields.
3218 assert!(fields_found <= field_types.len());
3219 if fields_found < field_types.len() {
3220 let mut missing_fields = Vec::new();
3221 for class_field in field_types.iter() {
3222 let name = class_field.name;
3223 let (_, seen) = class_field_map[name];
3225 missing_fields.push(
3226 format!("`{}`", token::get_name(name).get()))
3230 span_err!(tcx.sess, span, E0063,
3231 "missing field{}: {}",
3232 if missing_fields.len() == 1 {""} else {"s"},
3233 missing_fields.connect(", "));
3237 if !error_happened {
3238 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3239 class_id, substitutions));
3243 fn check_struct_constructor(fcx: &FnCtxt,
3245 span: codemap::Span,
3246 class_id: ast::DefId,
3247 fields: &[ast::Field],
3248 base_expr: Option<&ast::Expr>) {
3249 let tcx = fcx.ccx.tcx;
3251 // Generate the struct type.
3253 ty: mut struct_type,
3254 substs: struct_substs
3255 } = fcx.instantiate_type(span, class_id);
3257 // Look up and check the fields.
3258 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3259 check_struct_or_variant_fields(fcx,
3264 fcx.ccx.tcx.mk_substs(struct_substs),
3267 base_expr.is_none(),
3269 if ty::type_is_error(fcx.node_ty(id)) {
3270 struct_type = tcx.types.err;
3273 // Check the base expression if necessary.
3276 Some(base_expr) => {
3277 check_expr_has_type(fcx, &*base_expr, struct_type);
3281 // Write in the resulting type.
3282 fcx.write_ty(id, struct_type);
3285 fn check_struct_enum_variant(fcx: &FnCtxt,
3287 span: codemap::Span,
3288 enum_id: ast::DefId,
3289 variant_id: ast::DefId,
3290 fields: &[ast::Field]) {
3291 let tcx = fcx.ccx.tcx;
3293 // Look up the number of type parameters and the raw type, and
3294 // determine whether the enum is region-parameterized.
3297 substs: substitutions
3298 } = fcx.instantiate_type(span, enum_id);
3300 // Look up and check the enum variant fields.
3301 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3302 check_struct_or_variant_fields(fcx,
3307 fcx.ccx.tcx.mk_substs(substitutions),
3312 fcx.write_ty(id, enum_type);
3315 fn check_struct_fields_on_error(fcx: &FnCtxt,
3317 fields: &[ast::Field],
3318 base_expr: &Option<P<ast::Expr>>) {
3319 // Make sure to still write the types
3320 // otherwise we might ICE
3321 fcx.write_error(id);
3322 for field in fields.iter() {
3323 check_expr(fcx, &*field.expr);
3326 Some(ref base) => check_expr(fcx, &**base),
3331 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3333 let tcx = fcx.ccx.tcx;
3336 ast::ExprBox(ref opt_place, ref subexpr) => {
3337 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3338 check_expr(fcx, &**subexpr);
3340 let mut checked = false;
3341 opt_place.as_ref().map(|place| match place.node {
3342 ast::ExprPath(ref path) => {
3343 // FIXME(pcwalton): For now we hardcode the two permissible
3344 // places: the exchange heap and the managed heap.
3345 let definition = lookup_def(fcx, path.span, place.id);
3346 let def_id = definition.def_id();
3347 let referent_ty = fcx.expr_ty(&**subexpr);
3348 if tcx.lang_items.exchange_heap() == Some(def_id) {
3349 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3357 span_err!(tcx.sess, expr.span, E0066,
3358 "only the managed heap and exchange heap are currently supported");
3359 fcx.write_ty(id, tcx.types.err);
3363 ast::ExprLit(ref lit) => {
3364 let typ = check_lit(fcx, &**lit, expected);
3365 fcx.write_ty(id, typ);
3367 ast::ExprBinary(op, ref lhs, ref rhs) => {
3368 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3370 let lhs_ty = fcx.expr_ty(&**lhs);
3371 let rhs_ty = fcx.expr_ty(&**rhs);
3372 if ty::type_is_error(lhs_ty) ||
3373 ty::type_is_error(rhs_ty) {
3374 fcx.write_error(id);
3377 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3378 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3380 let lhs_t = fcx.expr_ty(&**lhs);
3381 let result_t = fcx.expr_ty(expr);
3382 demand::suptype(fcx, expr.span, result_t, lhs_t);
3384 let tcx = fcx.tcx();
3385 if !ty::expr_is_lval(tcx, &**lhs) {
3386 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3389 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3391 // Overwrite result of check_binop...this preserves existing behavior
3392 // but seems quite dubious with regard to user-defined methods
3393 // and so forth. - Niko
3394 if !ty::type_is_error(result_t) {
3395 fcx.write_nil(expr.id);
3398 ast::ExprUnary(unop, ref oprnd) => {
3399 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3401 ast::UnUniq => match ty.sty {
3402 ty::ty_uniq(ty) => {
3403 Expectation::rvalue_hint(ty)
3409 ast::UnNot | ast::UnNeg => {
3417 let lvalue_pref = match unop {
3418 ast::UnDeref => lvalue_pref,
3421 check_expr_with_expectation_and_lvalue_pref(
3422 fcx, &**oprnd, expected_inner, lvalue_pref);
3423 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3425 if !ty::type_is_error(oprnd_t) {
3428 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3431 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3432 oprnd_t = match ty::deref(oprnd_t, true) {
3434 None => match try_overloaded_deref(fcx, expr.span,
3435 Some(MethodCall::expr(expr.id)),
3436 Some(&**oprnd), oprnd_t, lvalue_pref) {
3439 let is_newtype = match oprnd_t.sty {
3440 ty::ty_struct(did, substs) => {
3441 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3443 && fields[0].name ==
3444 token::special_idents::unnamed_field.name
3449 // This is an obsolete struct deref
3450 span_err!(tcx.sess, expr.span, E0068,
3451 "single-field tuple-structs can \
3452 no longer be dereferenced");
3454 fcx.type_error_message(expr.span, |actual| {
3455 format!("type `{}` cannot be \
3456 dereferenced", actual)
3465 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3467 if !(ty::type_is_integral(oprnd_t) ||
3468 oprnd_t.sty == ty::ty_bool) {
3469 oprnd_t = check_user_unop(fcx, "!", "not",
3470 tcx.lang_items.not_trait(),
3471 expr, &**oprnd, oprnd_t, unop);
3475 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3477 if !(ty::type_is_integral(oprnd_t) ||
3478 ty::type_is_fp(oprnd_t)) {
3479 oprnd_t = check_user_unop(fcx, "-", "neg",
3480 tcx.lang_items.neg_trait(),
3481 expr, &**oprnd, oprnd_t, unop);
3486 fcx.write_ty(id, oprnd_t);
3488 ast::ExprAddrOf(mutbl, ref oprnd) => {
3489 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3491 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3492 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3493 // Lvalues may legitimately have unsized types.
3494 // For example, dereferences of a fat pointer and
3495 // the last field of a struct can be unsized.
3496 ExpectHasType(mt.ty)
3498 Expectation::rvalue_hint(mt.ty)
3504 let lvalue_pref = match mutbl {
3505 ast::MutMutable => PreferMutLvalue,
3506 ast::MutImmutable => NoPreference
3508 check_expr_with_expectation_and_lvalue_pref(fcx,
3513 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3514 let oprnd_t = if ty::type_is_error(tm.ty) {
3517 // Note: at this point, we cannot say what the best lifetime
3518 // is to use for resulting pointer. We want to use the
3519 // shortest lifetime possible so as to avoid spurious borrowck
3520 // errors. Moreover, the longest lifetime will depend on the
3521 // precise details of the value whose address is being taken
3522 // (and how long it is valid), which we don't know yet until type
3523 // inference is complete.
3525 // Therefore, here we simply generate a region variable. The
3526 // region inferencer will then select the ultimate value.
3527 // Finally, borrowck is charged with guaranteeing that the
3528 // value whose address was taken can actually be made to live
3529 // as long as it needs to live.
3531 // String literals are already, implicitly converted to slices.
3532 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3533 // Empty slices live in static memory.
3534 ast::ExprVec(ref elements) if elements.len() == 0 => {
3535 // Note: we do not assign a lifetime of
3536 // static. This is because the resulting type
3537 // `&'static [T]` would require that T outlives
3539 let region = fcx.infcx().next_region_var(
3540 infer::AddrOfSlice(expr.span));
3541 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3544 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3545 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3549 fcx.write_ty(id, oprnd_t);
3551 ast::ExprPath(ref path) => {
3552 let defn = lookup_def(fcx, path.span, id);
3553 let pty = type_scheme_for_def(fcx, expr.span, defn);
3554 instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3556 // We always require that the type provided as the value for
3557 // a type parameter outlives the moment of instantiation.
3558 constrain_path_type_parameters(fcx, expr);
3560 ast::ExprQPath(ref qpath) => {
3561 // Require explicit type params for the trait.
3562 let self_ty = fcx.to_ty(&*qpath.self_type);
3563 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3565 let defn = lookup_def(fcx, expr.span, id);
3566 let pty = type_scheme_for_def(fcx, expr.span, defn);
3567 let mut path = qpath.trait_ref.path.clone();
3568 path.segments.push(qpath.item_path.clone());
3569 instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3571 // We always require that the type provided as the value for
3572 // a type parameter outlives the moment of instantiation.
3573 constrain_path_type_parameters(fcx, expr);
3575 ast::ExprInlineAsm(ref ia) => {
3576 for &(_, ref input) in ia.inputs.iter() {
3577 check_expr(fcx, &**input);
3579 for &(_, ref out, _) in ia.outputs.iter() {
3580 check_expr(fcx, &**out);
3584 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3585 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3586 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3587 ast::ExprRet(ref expr_opt) => {
3589 ty::FnConverging(result_type) => {
3592 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3593 result_type, ty::mk_nil(fcx.tcx())) {
3594 span_err!(tcx.sess, expr.span, E0069,
3595 "`return;` in function returning non-nil");
3598 check_expr_coercable_to_type(fcx, &**e, result_type);
3602 ty::FnDiverging => {
3603 if let Some(ref e) = *expr_opt {
3604 check_expr(fcx, &**e);
3606 span_err!(tcx.sess, expr.span, E0166,
3607 "`return` in a function declared as diverging");
3610 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3612 ast::ExprParen(ref a) => {
3613 check_expr_with_expectation_and_lvalue_pref(fcx,
3617 fcx.write_ty(id, fcx.expr_ty(&**a));
3619 ast::ExprAssign(ref lhs, ref rhs) => {
3620 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3622 let tcx = fcx.tcx();
3623 if !ty::expr_is_lval(tcx, &**lhs) {
3624 span_err!(tcx.sess, expr.span, E0070,
3625 "illegal left-hand side expression");
3628 let lhs_ty = fcx.expr_ty(&**lhs);
3629 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3630 let rhs_ty = fcx.expr_ty(&**rhs);
3632 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3634 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3635 fcx.write_error(id);
3640 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3641 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3642 id, expr.span, expected);
3644 ast::ExprIfLet(..) => {
3645 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3647 ast::ExprWhile(ref cond, ref body, _) => {
3648 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3649 check_block_no_value(fcx, &**body);
3650 let cond_ty = fcx.expr_ty(&**cond);
3651 let body_ty = fcx.node_ty(body.id);
3652 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3653 fcx.write_error(id);
3659 ast::ExprWhileLet(..) => {
3660 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3662 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3663 check_expr(fcx, &**head);
3664 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
3665 vtable::select_new_fcx_obligations(fcx);
3667 debug!("ExprForLoop each item has type {}",
3668 fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
3670 let pcx = pat_ctxt {
3672 map: pat_id_map(&tcx.def_map, &**pat),
3674 _match::check_pat(&pcx, &**pat, typ);
3676 check_block_no_value(fcx, &**block);
3679 ast::ExprLoop(ref body, _) => {
3680 check_block_no_value(fcx, &**body);
3681 if !may_break(tcx, expr.id, &**body) {
3682 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3687 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3688 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3690 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3691 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3693 ast::ExprBlock(ref b) => {
3694 check_block_with_expected(fcx, &**b, expected);
3695 fcx.write_ty(id, fcx.node_ty(b.id));
3697 ast::ExprCall(ref callee, ref args) => {
3698 callee::check_call(fcx, expr, &**callee, &args[], expected);
3700 ast::ExprMethodCall(ident, ref tps, ref args) => {
3701 check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3702 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3703 let args_err = arg_tys.fold(false,
3705 rest_err || ty::type_is_error(a)});
3707 fcx.write_error(id);
3710 ast::ExprCast(ref e, ref t) => {
3711 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3712 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3714 check_cast(fcx, expr, &**e, &**t);
3716 ast::ExprVec(ref args) => {
3717 let uty = expected.to_option(fcx).and_then(|uty| {
3719 ty::ty_vec(ty, _) => Some(ty),
3724 let typ = match uty {
3726 for e in args.iter() {
3727 check_expr_coercable_to_type(fcx, &**e, uty);
3732 let t: Ty = fcx.infcx().next_ty_var();
3733 for e in args.iter() {
3734 check_expr_has_type(fcx, &**e, t);
3739 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3740 fcx.write_ty(id, typ);
3742 ast::ExprRepeat(ref element, ref count_expr) => {
3743 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3744 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3746 let uty = match expected {
3747 ExpectHasType(uty) => {
3749 ty::ty_vec(ty, _) => Some(ty),
3756 let (element_ty, t) = match uty {
3758 check_expr_coercable_to_type(fcx, &**element, uty);
3762 let t: Ty = fcx.infcx().next_ty_var();
3763 check_expr_has_type(fcx, &**element, t);
3764 (fcx.expr_ty(&**element), t)
3769 // For [foo, ..n] where n > 1, `foo` must have
3771 fcx.require_type_meets(
3778 if ty::type_is_error(element_ty) {
3779 fcx.write_error(id);
3781 let t = ty::mk_vec(tcx, t, Some(count));
3782 fcx.write_ty(id, t);
3785 ast::ExprTup(ref elts) => {
3786 let flds = expected.only_has_type(fcx).and_then(|ty| {
3788 ty::ty_tup(ref flds) => Some(&flds[]),
3792 let mut err_field = false;
3794 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3795 let t = match flds {
3796 Some(ref fs) if i < fs.len() => {
3798 check_expr_coercable_to_type(fcx, &**e, ety);
3802 check_expr_with_expectation(fcx, &**e, NoExpectation);
3806 err_field = err_field || ty::type_is_error(t);
3810 fcx.write_error(id);
3812 let typ = ty::mk_tup(tcx, elt_ts);
3813 fcx.write_ty(id, typ);
3816 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3817 // Resolve the path.
3818 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3819 let struct_id = match def {
3820 Some(def::DefVariant(enum_id, variant_id, true)) => {
3821 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3822 variant_id, &fields[]);
3825 Some(def::DefTrait(def_id)) => {
3826 span_err!(tcx.sess, path.span, E0159,
3827 "use of trait `{}` as a struct constructor",
3828 pprust::path_to_string(path));
3829 check_struct_fields_on_error(fcx,
3836 // Verify that this was actually a struct.
3837 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3839 ty::ty_struct(struct_did, _) => {
3840 check_struct_constructor(fcx,
3845 base_expr.as_ref().map(|e| &**e));
3848 span_err!(tcx.sess, path.span, E0071,
3849 "`{}` does not name a structure",
3850 pprust::path_to_string(path));
3851 check_struct_fields_on_error(fcx,
3861 tcx.sess.span_bug(path.span,
3862 "structure constructor wasn't resolved")
3866 // Turn the path into a type and verify that that type unifies with
3867 // the resulting structure type. This is needed to handle type
3868 // parameters correctly.
3869 let actual_structure_type = fcx.expr_ty(&*expr);
3870 if !ty::type_is_error(actual_structure_type) {
3871 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3872 match fcx.mk_subty(false,
3873 infer::Misc(path.span),
3874 actual_structure_type,
3875 type_and_substs.ty) {
3877 Err(type_error) => {
3878 let type_error_description =
3879 ty::type_err_to_str(tcx, &type_error);
3880 span_err!(fcx.tcx().sess, path.span, E0235,
3881 "structure constructor specifies a \
3882 structure of type `{}`, but this \
3883 structure has type `{}`: {}",
3885 .ty_to_string(type_and_substs.ty),
3888 actual_structure_type),
3889 type_error_description);
3890 ty::note_and_explain_type_err(tcx, &type_error);
3895 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3897 ast::ExprField(ref base, ref field) => {
3898 check_field(fcx, expr, lvalue_pref, &**base, field);
3900 ast::ExprTupField(ref base, idx) => {
3901 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3903 ast::ExprIndex(ref base, ref idx) => {
3904 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3905 let base_t = fcx.expr_ty(&**base);
3906 if ty::type_is_error(base_t) {
3907 fcx.write_ty(id, base_t);
3909 check_expr(fcx, &**idx);
3910 let idx_t = fcx.expr_ty(&**idx);
3911 if ty::type_is_error(idx_t) {
3912 fcx.write_ty(id, idx_t);
3914 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3917 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3919 MethodCall::expr(expr.id),
3929 Some((index_ty, element_ty)) => {
3930 // FIXME: we've already checked idx above, we should
3931 // probably just demand subtype or something here.
3932 check_expr_has_type(fcx, &**idx, index_ty);
3933 fcx.write_ty(id, element_ty);
3936 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3937 fcx.type_error_message(
3940 format!("cannot index a value of type `{}`",
3945 fcx.write_ty(id, fcx.tcx().types.err);
3951 ast::ExprRange(ref start, ref end) => {
3952 let t_start = start.as_ref().map(|e| {
3953 check_expr(fcx, &**e);
3956 let t_end = end.as_ref().map(|e| {
3957 check_expr(fcx, &**e);
3961 let idx_type = match (t_start, t_end) {
3962 (Some(ty), None) | (None, Some(ty)) => {
3965 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
3966 ty::type_is_error(t_end)) => {
3967 Some(fcx.tcx().types.err)
3969 (Some(t_start), Some(t_end)) => {
3970 Some(infer::common_supertype(fcx.infcx(),
3971 infer::RangeExpression(expr.span),
3979 // Note that we don't check the type of start/end satisfy any
3980 // bounds because right now the range structs do not have any. If we add
3981 // some bounds, then we'll need to check `t_start` against them here.
3983 let range_type = match idx_type {
3984 Some(idx_type) if ty::type_is_error(idx_type) => {
3988 // Find the did from the appropriate lang item.
3989 let did = match (start, end) {
3990 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
3991 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
3992 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
3994 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
3998 if let Some(did) = did {
3999 let polytype = ty::lookup_item_type(tcx, did);
4000 let substs = Substs::new_type(vec![idx_type], vec![]);
4001 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4002 fcx.add_obligations_for_parameters(
4003 traits::ObligationCause::new(expr.span,
4005 traits::ItemObligation(did)),
4008 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4010 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
4015 // Neither start nor end => FullRange
4016 if let Some(did) = tcx.lang_items.full_range_struct() {
4017 let substs = Substs::new_type(vec![], vec![]);
4018 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4020 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
4026 fcx.write_ty(id, range_type);
4031 debug!("type of expr({}) {} is...", expr.id,
4032 syntax::print::pprust::expr_to_string(expr));
4033 debug!("... {}, expected is {}",
4034 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4035 expected.repr(tcx));
4040 fn constrain_path_type_parameters(fcx: &FnCtxt,
4043 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4044 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4048 impl<'tcx> Expectation<'tcx> {
4049 /// Provide an expectation for an rvalue expression given an *optional*
4050 /// hint, which is not required for type safety (the resulting type might
4051 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4052 /// is useful in determining the concrete type.
4054 /// The primary use case is where the expected type is a fat pointer,
4055 /// like `&[int]`. For example, consider the following statement:
4057 /// let x: &[int] = &[1, 2, 3];
4059 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4060 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4061 /// expectation `ExpectHasType([int])`, that would be too strong --
4062 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4063 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4064 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4065 /// which still is useful, because it informs integer literals and the like.
4066 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4067 /// for examples of where this comes up,.
4068 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4070 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4071 ExpectRvalueLikeUnsized(ty)
4073 _ => ExpectHasType(ty)
4077 // Resolves `expected` by a single level if it is a variable. If
4078 // there is no expected type or resolution is not possible (e.g.,
4079 // no constraints yet present), just returns `None`.
4080 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4085 ExpectCastableToType(t) => {
4086 ExpectCastableToType(
4087 fcx.infcx().resolve_type_vars_if_possible(&t))
4089 ExpectHasType(t) => {
4091 fcx.infcx().resolve_type_vars_if_possible(&t))
4093 ExpectRvalueLikeUnsized(t) => {
4094 ExpectRvalueLikeUnsized(
4095 fcx.infcx().resolve_type_vars_if_possible(&t))
4100 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4101 match self.resolve(fcx) {
4102 NoExpectation => None,
4103 ExpectCastableToType(ty) |
4105 ExpectRvalueLikeUnsized(ty) => Some(ty),
4109 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4110 match self.resolve(fcx) {
4111 ExpectHasType(ty) => Some(ty),
4117 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4118 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4120 NoExpectation => format!("NoExpectation"),
4121 ExpectHasType(t) => format!("ExpectHasType({})",
4123 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4125 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4131 pub fn check_decl_initializer(fcx: &FnCtxt,
4135 let local_ty = fcx.local_ty(init.span, nid);
4136 check_expr_coercable_to_type(fcx, init, local_ty)
4139 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4140 let tcx = fcx.ccx.tcx;
4142 let t = fcx.local_ty(local.span, local.id);
4143 fcx.write_ty(local.id, t);
4145 if let Some(ref init) = local.init {
4146 check_decl_initializer(fcx, local.id, &**init);
4147 let init_ty = fcx.expr_ty(&**init);
4148 if ty::type_is_error(init_ty) {
4149 fcx.write_ty(local.id, init_ty);
4153 let pcx = pat_ctxt {
4155 map: pat_id_map(&tcx.def_map, &*local.pat),
4157 _match::check_pat(&pcx, &*local.pat, t);
4158 let pat_ty = fcx.node_ty(local.pat.id);
4159 if ty::type_is_error(pat_ty) {
4160 fcx.write_ty(local.id, pat_ty);
4164 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4166 let mut saw_bot = false;
4167 let mut saw_err = false;
4169 ast::StmtDecl(ref decl, id) => {
4172 ast::DeclLocal(ref l) => {
4173 check_decl_local(fcx, &**l);
4174 let l_t = fcx.node_ty(l.id);
4175 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4176 saw_err = saw_err || ty::type_is_error(l_t);
4178 ast::DeclItem(_) => {/* ignore for now */ }
4181 ast::StmtExpr(ref expr, id) => {
4183 // Check with expected type of ()
4184 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4185 let expr_ty = fcx.expr_ty(&**expr);
4186 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4187 saw_err = saw_err || ty::type_is_error(expr_ty);
4189 ast::StmtSemi(ref expr, id) => {
4191 check_expr(fcx, &**expr);
4192 let expr_ty = fcx.expr_ty(&**expr);
4193 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4194 saw_err |= ty::type_is_error(expr_ty);
4196 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4199 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4202 fcx.write_error(node_id);
4205 fcx.write_nil(node_id)
4209 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4210 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4211 let blkty = fcx.node_ty(blk.id);
4212 if ty::type_is_error(blkty) {
4213 fcx.write_error(blk.id);
4215 let nilty = ty::mk_nil(fcx.tcx());
4216 demand::suptype(fcx, blk.span, nilty, blkty);
4220 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4222 expected: Expectation<'tcx>) {
4224 let mut fcx_ps = fcx.ps.borrow_mut();
4225 let unsafety_state = fcx_ps.recurse(blk);
4226 replace(&mut *fcx_ps, unsafety_state)
4229 let mut warned = false;
4230 let mut any_diverges = false;
4231 let mut any_err = false;
4232 for s in blk.stmts.iter() {
4233 check_stmt(fcx, &**s);
4234 let s_id = ast_util::stmt_id(&**s);
4235 let s_ty = fcx.node_ty(s_id);
4236 if any_diverges && !warned && match s.node {
4237 ast::StmtDecl(ref decl, _) => {
4239 ast::DeclLocal(_) => true,
4243 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4249 .add_lint(lint::builtin::UNREACHABLE_CODE,
4252 "unreachable statement".to_string());
4255 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4256 any_err = any_err || ty::type_is_error(s_ty);
4259 None => if any_err {
4260 fcx.write_error(blk.id);
4261 } else if any_diverges {
4262 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4264 fcx.write_nil(blk.id);
4267 if any_diverges && !warned {
4271 .add_lint(lint::builtin::UNREACHABLE_CODE,
4274 "unreachable expression".to_string());
4276 let ety = match expected {
4277 ExpectHasType(ety) => {
4278 check_expr_coercable_to_type(fcx, &**e, ety);
4282 check_expr_with_expectation(fcx, &**e, expected);
4288 fcx.write_error(blk.id);
4289 } else if any_diverges {
4290 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4292 fcx.write_ty(blk.id, ety);
4297 *fcx.ps.borrow_mut() = prev;
4300 /// Checks a constant appearing in a type. At the moment this is just the
4301 /// length expression in a fixed-length vector, but someday it might be
4302 /// extended to type-level numeric literals.
4303 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4305 expected_type: Ty<'tcx>) {
4306 let inh = static_inherited_fields(ccx);
4307 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4308 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4311 fn check_const(ccx: &CrateCtxt,
4315 let inh = static_inherited_fields(ccx);
4316 let rty = ty::node_id_to_type(ccx.tcx, id);
4317 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4318 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4319 check_const_with_ty(&fcx, sp, e, declty);
4322 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4326 // Gather locals in statics (because of block expressions).
4327 // This is technically unnecessary because locals in static items are forbidden,
4328 // but prevents type checking from blowing up before const checking can properly
4330 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4332 check_expr_with_hint(fcx, e, declty);
4333 demand::coerce(fcx, e.span, declty, e);
4334 vtable::select_all_fcx_obligations_or_error(fcx);
4335 regionck::regionck_expr(fcx, e);
4336 writeback::resolve_type_vars_in_expr(fcx, e);
4339 /// Checks whether a type can be represented in memory. In particular, it
4340 /// identifies types that contain themselves without indirection through a
4341 /// pointer, which would mean their size is unbounded. This is different from
4342 /// the question of whether a type can be instantiated. See the definition of
4343 /// `check_instantiable`.
4344 pub fn check_representable(tcx: &ty::ctxt,
4346 item_id: ast::NodeId,
4347 designation: &str) -> bool {
4348 let rty = ty::node_id_to_type(tcx, item_id);
4350 // Check that it is possible to represent this type. This call identifies
4351 // (1) types that contain themselves and (2) types that contain a different
4352 // recursive type. It is only necessary to throw an error on those that
4353 // contain themselves. For case 2, there must be an inner type that will be
4354 // caught by case 1.
4355 match ty::is_type_representable(tcx, sp, rty) {
4356 ty::SelfRecursive => {
4357 span_err!(tcx.sess, sp, E0072,
4358 "illegal recursive {} type; \
4359 wrap the inner value in a box to make it representable",
4363 ty::Representable | ty::ContainsRecursive => (),
4368 /// Checks whether a type can be created without an instance of itself.
4369 /// This is similar but different from the question of whether a type
4370 /// can be represented. For example, the following type:
4372 /// enum foo { None, Some(foo) }
4374 /// is instantiable but is not representable. Similarly, the type
4376 /// enum foo { Some(@foo) }
4378 /// is representable, but not instantiable.
4379 pub fn check_instantiable(tcx: &ty::ctxt,
4381 item_id: ast::NodeId)
4383 let item_ty = ty::node_id_to_type(tcx, item_id);
4384 if !ty::is_instantiable(tcx, item_ty) {
4385 span_err!(tcx.sess, sp, E0073,
4386 "this type cannot be instantiated without an \
4387 instance of itself");
4388 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4389 ppaux::ty_to_string(tcx, item_ty));
4396 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4397 let t = ty::node_id_to_type(tcx, id);
4398 if ty::type_needs_subst(t) {
4399 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4403 ty::ty_struct(did, substs) => {
4404 let fields = ty::lookup_struct_fields(tcx, did);
4405 if fields.is_empty() {
4406 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4409 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4410 if !fields.iter().all(
4411 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4412 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4415 if !ty::type_is_machine(e) {
4416 span_err!(tcx.sess, sp, E0077,
4417 "SIMD vector element type should be machine type");
4425 pub fn check_enum_variants(ccx: &CrateCtxt,
4427 vs: &[P<ast::Variant>],
4430 fn disr_in_range(ccx: &CrateCtxt,
4432 disr: ty::Disr) -> bool {
4433 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4435 ast::TyU8 => disr as u8 as Disr == disr,
4436 ast::TyU16 => disr as u16 as Disr == disr,
4437 ast::TyU32 => disr as u32 as Disr == disr,
4438 ast::TyU64 => disr as u64 as Disr == disr,
4439 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4442 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4444 ast::TyI8 => disr as i8 as Disr == disr,
4445 ast::TyI16 => disr as i16 as Disr == disr,
4446 ast::TyI32 => disr as i32 as Disr == disr,
4447 ast::TyI64 => disr as i64 as Disr == disr,
4448 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4452 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4453 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4457 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4458 vs: &[P<ast::Variant>],
4460 hint: attr::ReprAttr)
4461 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4463 let rty = ty::node_id_to_type(ccx.tcx, id);
4464 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4465 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4466 let mut prev_disr_val: Option<ty::Disr> = None;
4468 for v in vs.iter() {
4470 // If the discriminant value is specified explicitly in the enum check whether the
4471 // initialization expression is valid, otherwise use the last value plus one.
4472 let mut current_disr_val = match prev_disr_val {
4473 Some(prev_disr_val) => prev_disr_val + 1,
4474 None => ty::INITIAL_DISCRIMINANT_VALUE
4477 match v.node.disr_expr {
4479 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4481 let inh = static_inherited_fields(ccx);
4482 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4483 let declty = match hint {
4484 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4485 attr::ReprInt(_, attr::SignedInt(ity)) => {
4486 ty::mk_mach_int(fcx.tcx(), ity)
4488 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4489 ty::mk_mach_uint(fcx.tcx(), ity)
4492 check_const_with_ty(&fcx, e.span, &**e, declty);
4493 // check_expr (from check_const pass) doesn't guarantee
4494 // that the expression is in a form that eval_const_expr can
4495 // handle, so we may still get an internal compiler error
4497 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4498 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4499 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4501 span_err!(ccx.tcx.sess, e.span, E0079,
4502 "expected signed integer constant");
4505 span_err!(ccx.tcx.sess, e.span, E0080,
4506 "expected constant: {}", *err);
4513 // Check for duplicate discriminant values
4514 match disr_vals.iter().position(|&x| x == current_disr_val) {
4516 span_err!(ccx.tcx.sess, v.span, E0081,
4517 "discriminant value `{}` already exists", disr_vals[i]);
4518 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4519 "conflicting discriminant here")
4523 // Check for unrepresentable discriminant values
4525 attr::ReprAny | attr::ReprExtern => (),
4526 attr::ReprInt(sp, ity) => {
4527 if !disr_in_range(ccx, ity, current_disr_val) {
4528 span_err!(ccx.tcx.sess, v.span, E0082,
4529 "discriminant value outside specified type");
4530 span_note!(ccx.tcx.sess, sp,
4531 "discriminant type specified here");
4534 attr::ReprPacked => {
4535 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4538 disr_vals.push(current_disr_val);
4540 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4542 prev_disr_val = Some(current_disr_val);
4544 variants.push(variant_info);
4550 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4551 [].get(0).unwrap_or(&attr::ReprAny);
4553 if hint != attr::ReprAny && vs.len() <= 1 {
4555 span_err!(ccx.tcx.sess, sp, E0083,
4556 "unsupported representation for univariant enum");
4558 span_err!(ccx.tcx.sess, sp, E0084,
4559 "unsupported representation for zero-variant enum");
4563 let variants = do_check(ccx, vs, id, hint);
4565 // cache so that ty::enum_variants won't repeat this work
4566 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4568 check_representable(ccx.tcx, sp, id, "enum");
4570 // Check that it is possible to instantiate this enum:
4572 // This *sounds* like the same that as representable, but it's
4573 // not. See def'n of `check_instantiable()` for details.
4574 check_instantiable(ccx.tcx, sp, id);
4577 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4578 lookup_def_ccx(fcx.ccx, sp, id)
4581 // Returns the type parameter count and the type for the given definition.
4582 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4585 -> TypeScheme<'tcx> {
4587 def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
4588 let typ = fcx.local_ty(sp, nid);
4589 return no_params(typ);
4591 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4592 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4593 def::DefStruct(id) | def::DefConst(id) => {
4594 return ty::lookup_item_type(fcx.ccx.tcx, id);
4598 def::DefAssociatedTy(..) |
4599 def::DefAssociatedPath(..) |
4601 def::DefTyParam(..) => {
4602 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4604 def::DefMod(..) | def::DefForeignMod(..) => {
4605 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4607 def::DefUse(..) => {
4608 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4610 def::DefRegion(..) => {
4611 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4613 def::DefTyParamBinder(..) => {
4614 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4616 def::DefLabel(..) => {
4617 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4619 def::DefSelfTy(..) => {
4620 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4625 // Instantiates the given path, which must refer to an item with the given
4626 // number of type parameters and type.
4627 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4629 type_scheme: TypeScheme<'tcx>,
4630 opt_self_ty: Option<Ty<'tcx>>,
4633 node_id: ast::NodeId) {
4634 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4635 path.repr(fcx.tcx()),
4636 def.repr(fcx.tcx()),
4638 type_scheme.repr(fcx.tcx()));
4640 // We need to extract the type parameters supplied by the user in
4641 // the path `path`. Due to the current setup, this is a bit of a
4642 // tricky-process; the problem is that resolve only tells us the
4643 // end-point of the path resolution, and not the intermediate steps.
4644 // Luckily, we can (at least for now) deduce the intermediate steps
4645 // just from the end-point.
4647 // There are basically three cases to consider:
4649 // 1. Reference to a *type*, such as a struct or enum:
4651 // mod a { struct Foo<T> { ... } }
4653 // Because we don't allow types to be declared within one
4654 // another, a path that leads to a type will always look like
4655 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4656 // that only the final segment can have type parameters, and
4657 // they are located in the TypeSpace.
4659 // *Note:* Generally speaking, references to types don't
4660 // actually pass through this function, but rather the
4661 // `ast_ty_to_ty` function in `astconv`. However, in the case
4662 // of struct patterns (and maybe literals) we do invoke
4663 // `instantiate_path` to get the general type of an instance of
4664 // a struct. (In these cases, there are actually no type
4665 // parameters permitted at present, but perhaps we will allow
4666 // them in the future.)
4668 // 1b. Reference to a enum variant or tuple-like struct:
4670 // struct foo<T>(...)
4671 // enum E<T> { foo(...) }
4673 // In these cases, the parameters are declared in the type
4676 // 2. Reference to a *fn item*:
4680 // In this case, the path will again always have the form
4681 // `a::b::foo::<T>` where only the final segment should have
4682 // type parameters. However, in this case, those parameters are
4683 // declared on a value, and hence are in the `FnSpace`.
4685 // 3. Reference to a *method*:
4687 // impl<A> SomeStruct<A> {
4691 // Here we can have a path like
4692 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4693 // may appear in two places. The penultimate segment,
4694 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4695 // final segment, `foo::<B>` contains parameters in fn space.
4697 // The first step then is to categorize the segments appropriately.
4699 assert!(path.segments.len() >= 1);
4700 let mut segment_spaces: Vec<_>;
4702 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4703 def::DefSelfTy(..) |
4704 def::DefStruct(..) |
4705 def::DefVariant(..) |
4706 def::DefTyParamBinder(..) |
4708 def::DefAssociatedTy(..) |
4709 def::DefAssociatedPath(..) |
4711 def::DefPrimTy(..) |
4712 def::DefTyParam(..) => {
4713 // Everything but the final segment should have no
4714 // parameters at all.
4715 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4716 segment_spaces.push(Some(subst::TypeSpace));
4719 // Case 2. Reference to a top-level value.
4722 def::DefStatic(..) => {
4723 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4724 segment_spaces.push(Some(subst::FnSpace));
4727 // Case 3. Reference to a method.
4728 def::DefStaticMethod(_, providence) |
4729 def::DefMethod(_, _, providence) => {
4730 assert!(path.segments.len() >= 2);
4733 def::FromTrait(trait_did) => {
4734 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4736 def::FromImpl(_) => {}
4739 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4740 segment_spaces.push(Some(subst::TypeSpace));
4741 segment_spaces.push(Some(subst::FnSpace));
4744 // Other cases. Various nonsense that really shouldn't show up
4745 // here. If they do, an error will have been reported
4746 // elsewhere. (I hope)
4748 def::DefForeignMod(..) |
4751 def::DefRegion(..) |
4753 def::DefUpvar(..) => {
4754 segment_spaces = repeat(None).take(path.segments.len()).collect();
4757 assert_eq!(segment_spaces.len(), path.segments.len());
4759 debug!("segment_spaces={:?}", segment_spaces);
4761 // Next, examine the definition, and determine how many type
4762 // parameters we expect from each space.
4763 let type_defs = &type_scheme.generics.types;
4764 let region_defs = &type_scheme.generics.regions;
4766 // Now that we have categorized what space the parameters for each
4767 // segment belong to, let's sort out the parameters that the user
4768 // provided (if any) into their appropriate spaces. We'll also report
4769 // errors if type parameters are provided in an inappropriate place.
4770 let mut substs = Substs::empty();
4771 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4774 report_error_if_segment_contains_type_parameters(fcx, segment);
4778 push_explicit_parameters_from_segment_to_substs(fcx,
4788 if let Some(self_ty) = opt_self_ty {
4789 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4790 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4791 substs.types.push(subst::SelfSpace, self_ty);
4794 // Now we have to compare the types that the user *actually*
4795 // provided against the types that were *expected*. If the user
4796 // did not provide any types, then we want to substitute inference
4797 // variables. If the user provided some types, we may still need
4798 // to add defaults. If the user provided *too many* types, that's
4800 for &space in ParamSpace::all().iter() {
4801 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4802 assert_eq!(substs.types.len(space), type_defs.len(space));
4804 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4805 assert_eq!(substs.regions().len(space), region_defs.len(space));
4808 // The things we are substituting into the type should not contain
4809 // escaping late-bound regions, and nor should the base type scheme.
4810 assert!(!substs.has_regions_escaping_depth(0));
4811 assert!(!type_scheme.has_escaping_regions());
4813 // Add all the obligations that are required, substituting and
4814 // normalized appropriately.
4815 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4816 fcx.add_obligations_for_parameters(
4817 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4820 // Substitute the values for the type parameters into the type of
4821 // the referenced item.
4822 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4824 fcx.write_ty(node_id, ty_substituted);
4825 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4828 fn report_error_if_segment_contains_type_parameters(
4830 segment: &ast::PathSegment)
4832 for typ in segment.parameters.types().iter() {
4833 span_err!(fcx.tcx().sess, typ.span, E0085,
4834 "type parameters may not appear here");
4838 for lifetime in segment.parameters.lifetimes().iter() {
4839 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4840 "lifetime parameters may not appear here");
4845 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4846 /// parameters are provided, then reports an error and clears the output vector.
4848 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4849 /// use inference variables. This seems less likely to lead to derived errors.
4851 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4852 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4853 /// here because we can easily use the precise span of the N+1'th parameter.
4854 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4855 fcx: &FnCtxt<'a, 'tcx>,
4856 space: subst::ParamSpace,
4858 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4859 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4860 segment: &ast::PathSegment,
4861 substs: &mut Substs<'tcx>)
4863 match segment.parameters {
4864 ast::AngleBracketedParameters(ref data) => {
4865 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4866 fcx, space, type_defs, region_defs, data, substs);
4869 ast::ParenthesizedParameters(ref data) => {
4870 span_err!(fcx.tcx().sess, span, E0238,
4871 "parenthesized parameters may only be used with a trait");
4872 push_explicit_parenthesized_parameters_from_segment_to_substs(
4873 fcx, space, span, type_defs, data, substs);
4878 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4879 fcx: &FnCtxt<'a, 'tcx>,
4880 space: subst::ParamSpace,
4881 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4882 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4883 data: &ast::AngleBracketedParameterData,
4884 substs: &mut Substs<'tcx>)
4887 let type_count = type_defs.len(space);
4888 assert_eq!(substs.types.len(space), 0);
4889 for (i, typ) in data.types.iter().enumerate() {
4890 let t = fcx.to_ty(&**typ);
4892 substs.types.push(space, t);
4893 } else if i == type_count {
4894 span_err!(fcx.tcx().sess, typ.span, E0087,
4895 "too many type parameters provided: \
4896 expected at most {} parameter(s), \
4897 found {} parameter(s)",
4898 type_count, data.types.len());
4899 substs.types.truncate(space, 0);
4905 if data.bindings.len() > 0 {
4906 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4907 "unexpected binding of associated item in expression path \
4908 (only allowed in type paths)");
4912 let region_count = region_defs.len(space);
4913 assert_eq!(substs.regions().len(space), 0);
4914 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4915 let r = ast_region_to_region(fcx.tcx(), lifetime);
4916 if i < region_count {
4917 substs.mut_regions().push(space, r);
4918 } else if i == region_count {
4919 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4920 "too many lifetime parameters provided: \
4921 expected {} parameter(s), found {} parameter(s)",
4923 data.lifetimes.len());
4924 substs.mut_regions().truncate(space, 0);
4932 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4933 /// but intended for `Foo(A,B) -> C` form. This expands to
4934 /// roughly the same thing as `Foo<(A,B),C>`. One important
4935 /// difference has to do with the treatment of anonymous
4936 /// regions, which are translated into bound regions (NYI).
4937 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4938 fcx: &FnCtxt<'a, 'tcx>,
4939 space: subst::ParamSpace,
4941 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4942 data: &ast::ParenthesizedParameterData,
4943 substs: &mut Substs<'tcx>)
4945 let type_count = type_defs.len(space);
4947 span_err!(fcx.tcx().sess, span, E0167,
4948 "parenthesized form always supplies 2 type parameters, \
4949 but only {} parameter(s) were expected",
4953 let input_tys: Vec<Ty> =
4954 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4957 ty::mk_tup(fcx.tcx(), input_tys);
4959 if type_count >= 1 {
4960 substs.types.push(space, tuple_ty);
4963 let output_ty: Option<Ty> =
4964 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4967 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4969 if type_count >= 2 {
4970 substs.types.push(space, output_ty);
4974 fn adjust_type_parameters<'a, 'tcx>(
4975 fcx: &FnCtxt<'a, 'tcx>,
4978 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4979 substs: &mut Substs<'tcx>)
4981 let provided_len = substs.types.len(space);
4982 let desired = defs.get_slice(space);
4983 let required_len = desired.iter()
4984 .take_while(|d| d.default.is_none())
4987 debug!("adjust_type_parameters(space={:?}, \
4996 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4997 assert!(provided_len <= desired.len());
4999 // Nothing specified at all: supply inference variables for
5001 if provided_len == 0 {
5002 substs.types.replace(space,
5003 fcx.infcx().next_ty_vars(desired.len()));
5007 // Too few parameters specified: report an error and use Err
5009 if provided_len < required_len {
5011 if desired.len() != required_len { "at least " } else { "" };
5012 span_err!(fcx.tcx().sess, span, E0089,
5013 "too few type parameters provided: expected {}{} parameter(s) \
5014 , found {} parameter(s)",
5015 qualifier, required_len, provided_len);
5016 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5020 // Otherwise, add in any optional parameters that the user
5021 // omitted. The case of *too many* parameters is handled
5023 // push_explicit_parameters_from_segment_to_substs(). Note
5024 // that the *default* type are expressed in terms of all prior
5025 // parameters, so we have to substitute as we go with the
5026 // partial substitution that we have built up.
5027 for i in range(provided_len, desired.len()) {
5028 let default = desired[i].default.unwrap();
5029 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5030 substs.types.push(space, default);
5032 assert_eq!(substs.types.len(space), desired.len());
5034 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5037 fn adjust_region_parameters(
5041 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5042 substs: &mut Substs)
5044 let provided_len = substs.mut_regions().len(space);
5045 let desired = defs.get_slice(space);
5047 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5048 assert!(provided_len <= desired.len());
5050 // If nothing was provided, just use inference variables.
5051 if provided_len == 0 {
5052 substs.mut_regions().replace(
5054 fcx.infcx().region_vars_for_defs(span, desired));
5058 // If just the right number were provided, everybody is happy.
5059 if provided_len == desired.len() {
5063 // Otherwise, too few were provided. Report an error and then
5064 // use inference variables.
5065 span_err!(fcx.tcx().sess, span, E0090,
5066 "too few lifetime parameters provided: expected {} parameter(s), \
5067 found {} parameter(s)",
5068 desired.len(), provided_len);
5070 substs.mut_regions().replace(
5072 fcx.infcx().region_vars_for_defs(span, desired));
5076 // Resolves `typ` by a single level if `typ` is a type variable. If no
5077 // resolution is possible, then an error is reported.
5078 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
5079 mut ty: Ty<'tcx>) -> Ty<'tcx> {
5080 // If `ty` is a type variable, see whether we already know what it is.
5081 ty = fcx.infcx().shallow_resolve(ty);
5083 // If not, try resolve pending fcx obligations. Those can shed light.
5085 // FIXME(#18391) -- This current strategy can lead to bad performance in
5086 // extreme cases. We probably ought to smarter in general about
5087 // only resolving when we need help and only resolving obligations
5088 // will actually help.
5089 if ty::type_is_ty_var(ty) {
5090 vtable::select_fcx_obligations_where_possible(fcx);
5091 ty = fcx.infcx().shallow_resolve(ty);
5095 if ty::type_is_ty_var(ty) {
5096 fcx.type_error_message(sp, |_actual| {
5097 "the type of this value must be known in this \
5098 context".to_string()
5100 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5101 ty = fcx.tcx().types.err;
5107 // Returns true if b contains a break that can exit from b
5108 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5109 // First: is there an unlabeled break immediately
5111 (loop_query(&*b, |e| {
5113 ast::ExprBreak(_) => true,
5117 // Second: is there a labeled break with label
5118 // <id> nested anywhere inside the loop?
5119 (block_query(b, |e| {
5121 ast::ExprBreak(Some(_)) => {
5122 match cx.def_map.borrow().get(&e.id) {
5123 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5131 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5133 tps: &OwnedSlice<ast::TyParam>,
5135 debug!("check_bounds_are_used(n_tps={}, ty={})",
5136 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5138 // make a vector of booleans initially false, set to true when used
5139 if tps.len() == 0u { return; }
5140 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5142 ty::walk_ty(ty, |t| {
5144 ty::ty_param(ParamTy {idx, ..}) => {
5145 debug!("Found use of ty param num {}", idx);
5146 tps_used[idx as uint] = true;
5152 for (i, b) in tps_used.iter().enumerate() {
5154 span_err!(ccx.tcx.sess, span, E0091,
5155 "type parameter `{}` is unused",
5156 token::get_ident(tps[i].ident));
5161 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5162 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5163 let name = token::intern(format!("P{}", n).as_slice());
5164 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5168 let name = token::get_ident(it.ident);
5169 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5170 let split : Vec<&str> = name.get().split('_').collect();
5171 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5173 //We only care about the operation here
5174 let (n_tps, inputs, output) = match split[1] {
5175 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5179 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5181 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5184 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5185 "min" | "umax" | "umin" => {
5186 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5190 (0, Vec::new(), ty::mk_nil(tcx))
5193 span_err!(tcx.sess, it.span, E0092,
5194 "unrecognized atomic operation function: `{}`", op);
5198 (n_tps, inputs, ty::FnConverging(output))
5199 } else if name.get() == "abort" || name.get() == "unreachable" {
5200 (0, Vec::new(), ty::FnDiverging)
5202 let (n_tps, inputs, output) = match name.get() {
5203 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5205 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5206 "init" => (1u, Vec::new(), param(ccx, 0)),
5207 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5208 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5209 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5210 "move_val_init" => {
5213 ty::mk_mut_rptr(tcx,
5214 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5221 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5222 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5225 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5227 Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[]); }
5229 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5231 mutbl: ast::MutImmutable
5233 (1u, Vec::new(), td_ptr)
5235 "type_id" => (1u, Vec::new(), ccx.tcx.types.u64),
5239 ty::mk_ptr(tcx, ty::mt {
5241 mutbl: ast::MutImmutable
5245 ty::mk_ptr(tcx, ty::mt {
5247 mutbl: ast::MutImmutable
5250 "copy_memory" | "copy_nonoverlapping_memory" |
5251 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5254 ty::mk_ptr(tcx, ty::mt {
5256 mutbl: ast::MutMutable
5258 ty::mk_ptr(tcx, ty::mt {
5260 mutbl: ast::MutImmutable
5266 "set_memory" | "volatile_set_memory" => {
5269 ty::mk_ptr(tcx, ty::mt {
5271 mutbl: ast::MutMutable
5278 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5279 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5282 vec!( tcx.types.f32, tcx.types.i32 ),
5287 vec!( tcx.types.f64, tcx.types.i32 ),
5290 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5291 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5292 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5293 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5296 vec!( tcx.types.f32, tcx.types.f32 ),
5301 vec!( tcx.types.f64, tcx.types.f64 ),
5304 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5305 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5306 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5307 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5308 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5309 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5310 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5311 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5312 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5313 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5316 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5321 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5324 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5325 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5326 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5327 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5328 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5329 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5330 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5331 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5332 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5333 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5334 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5335 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5336 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5337 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5338 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5339 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5340 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5341 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5342 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5343 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5344 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5345 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5346 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5347 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5348 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5349 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5350 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5351 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5352 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5353 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5354 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5357 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5359 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5361 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5362 (0, vec!(tcx.types.i8, tcx.types.i8),
5363 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5365 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5366 (0, vec!(tcx.types.i16, tcx.types.i16),
5367 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5369 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5370 (0, vec!(tcx.types.i32, tcx.types.i32),
5371 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5373 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5374 (0, vec!(tcx.types.i64, tcx.types.i64),
5375 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5377 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5378 (0, vec!(tcx.types.u8, tcx.types.u8),
5379 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5381 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5382 (0, vec!(tcx.types.u16, tcx.types.u16),
5383 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5385 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5386 (0, vec!(tcx.types.u32, tcx.types.u32),
5387 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5389 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5390 (0, vec!(tcx.types.u64, tcx.types.u64),
5391 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5393 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5395 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5398 span_err!(tcx.sess, it.span, E0093,
5399 "unrecognized intrinsic function: `{}`", *other);
5403 (n_tps, inputs, ty::FnConverging(output))
5405 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5406 unsafety: ast::Unsafety::Unsafe,
5407 abi: abi::RustIntrinsic,
5408 sig: ty::Binder(FnSig {
5414 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5415 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5416 if i_n_tps != n_tps {
5417 span_err!(tcx.sess, it.span, E0094,
5418 "intrinsic has wrong number of type \
5419 parameters: found {}, expected {}",
5422 require_same_types(tcx,
5429 format!("intrinsic has wrong type: expected `{}`",
5430 ppaux::ty_to_string(ccx.tcx, fty))