1 // Copyright 2012-2015 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::mem_categorization as mc;
91 use middle::mem_categorization::McResult;
92 use middle::pat_util::{self, pat_id_map};
93 use middle::region::{self, CodeExtent};
94 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
96 use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
97 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
98 use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
99 use middle::ty::liberate_late_bound_regions;
100 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
101 use middle::ty_fold::{TypeFolder, TypeFoldable};
102 use rscope::RegionScope;
103 use session::Session;
104 use {CrateCtxt, lookup_def_ccx, require_same_types};
107 use util::common::{block_query, indenter, loop_query};
108 use util::ppaux::{self, Repr};
109 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
110 use util::lev_distance::lev_distance;
112 use std::cell::{Cell, Ref, RefCell};
113 use std::collections::hash_map::Entry::{Occupied, Vacant};
114 use std::mem::replace;
116 use std::iter::repeat;
118 use syntax::{self, abi, attr};
119 use syntax::attr::AttrMetaMethods;
120 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
121 use syntax::ast_util::{self, local_def, PostExpansionMethod};
122 use syntax::codemap::{self, Span};
123 use syntax::owned_slice::OwnedSlice;
124 use syntax::parse::token;
125 use syntax::print::pprust;
127 use syntax::visit::{self, Visitor};
145 /// closures defined within the function. For example:
148 /// bar(move|| { ... })
151 /// Here, the function `foo()` and the closure passed to
152 /// `bar()` will each have their own `FnCtxt`, but they will
153 /// share the inherited fields.
154 pub struct Inherited<'a, 'tcx: 'a> {
155 infcx: infer::InferCtxt<'a, 'tcx>,
156 locals: RefCell<NodeMap<Ty<'tcx>>>,
157 param_env: ty::ParameterEnvironment<'a, 'tcx>,
160 node_types: RefCell<NodeMap<Ty<'tcx>>>,
161 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
162 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
163 method_map: MethodMap<'tcx>,
164 upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
165 closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
166 closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
167 object_cast_map: ObjectCastMap<'tcx>,
169 // A mapping from each fn's id to its signature, with all bound
170 // regions replaced with free ones. Unlike the other tables, this
171 // one is never copied into the tcx: it is only used by regionck.
172 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
174 // Tracks trait obligations incurred during this function body.
175 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
177 // When we process a call like `c()` where `c` is a closure type,
178 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
179 // `FnOnce` closure. In that case, we defer full resolution of the
180 // call until upvar inference can kick in and make the
181 // decision. We keep these deferred resolutions grouped by the
182 // def-id of the closure, so that once we decide, we can easily go
183 // back and process them.
184 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
187 trait DeferredCallResolution<'tcx> {
188 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
191 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
193 /// When type-checking an expression, we propagate downward
194 /// whatever type hint we are able in the form of an `Expectation`.
196 enum Expectation<'tcx> {
197 /// We know nothing about what type this expression should have.
200 /// This expression should have the type given (or some subtype)
201 ExpectHasType(Ty<'tcx>),
203 /// This expression will be cast to the `Ty`
204 ExpectCastableToType(Ty<'tcx>),
206 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
207 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
208 ExpectRvalueLikeUnsized(Ty<'tcx>),
211 impl<'tcx> Expectation<'tcx> {
212 // Disregard "castable to" expectations because they
213 // can lead us astray. Consider for example `if cond
214 // {22} else {c} as u8` -- if we propagate the
215 // "castable to u8" constraint to 22, it will pick the
216 // type 22u8, which is overly constrained (c might not
217 // be a u8). In effect, the problem is that the
218 // "castable to" expectation is not the tightest thing
219 // we can say, so we want to drop it in this case.
220 // The tightest thing we can say is "must unify with
221 // else branch". Note that in the case of a "has type"
222 // constraint, this limitation does not hold.
224 // If the expected type is just a type variable, then don't use
225 // an expected type. Otherwise, we might write parts of the type
226 // when checking the 'then' block which are incompatible with the
228 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
230 ExpectHasType(ety) => {
231 let ety = fcx.infcx().shallow_resolve(ety);
232 if !ty::type_is_ty_var(ety) {
238 ExpectRvalueLikeUnsized(ety) => {
239 ExpectRvalueLikeUnsized(ety)
246 #[derive(Copy, Clone)]
247 pub struct UnsafetyState {
248 pub def: ast::NodeId,
249 pub unsafety: ast::Unsafety,
254 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
255 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
258 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
259 match self.unsafety {
260 // If this unsafe, then if the outer function was already marked as
261 // unsafe we shouldn't attribute the unsafe'ness to the block. This
262 // way the block can be warned about instead of ignoring this
263 // extraneous block (functions are never warned about).
264 ast::Unsafety::Unsafe if self.from_fn => *self,
267 let (unsafety, def) = match blk.rules {
268 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
269 ast::DefaultBlock => (unsafety, self.def),
271 UnsafetyState{ def: def,
279 /// Whether `check_binop` is part of an assignment or not.
280 /// Used to know whether we allow user overloads and to print
281 /// better messages on error.
283 enum IsBinopAssignment{
289 pub struct FnCtxt<'a, 'tcx: 'a> {
290 body_id: ast::NodeId,
292 // This flag is set to true if, during the writeback phase, we encounter
293 // a type error in this function.
294 writeback_errors: Cell<bool>,
296 // Number of errors that had been reported when we started
297 // checking this function. On exit, if we find that *more* errors
298 // have been reported, we will skip regionck and other work that
299 // expects the types within the function to be consistent.
300 err_count_on_creation: uint,
302 ret_ty: ty::FnOutput<'tcx>,
304 ps: RefCell<UnsafetyState>,
306 inh: &'a Inherited<'a, 'tcx>,
308 ccx: &'a CrateCtxt<'a, 'tcx>,
311 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
312 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
313 let ty = self.node_ty(id);
314 self.resolve_type_vars_or_error(&ty)
316 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
317 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
318 self.resolve_type_vars_or_error(&ty)
320 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
321 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
322 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
324 fn node_method_ty(&self, method_call: ty::MethodCall)
325 -> Option<Ty<'tcx>> {
326 self.inh.method_map.borrow()
328 .map(|method| method.ty)
329 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
331 fn node_method_origin(&self, method_call: ty::MethodCall)
332 -> Option<ty::MethodOrigin<'tcx>>
334 self.inh.method_map.borrow()
336 .map(|method| method.origin.clone())
338 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
339 &self.inh.adjustments
341 fn is_method_call(&self, id: ast::NodeId) -> bool {
342 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
344 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
345 self.param_env().temporary_scope(rvalue_id)
347 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
348 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
352 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
353 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
357 fn closure_kind(&self,
359 -> Option<ty::ClosureKind>
361 self.inh.closure_kinds.borrow().get(&def_id).cloned()
364 fn closure_type(&self,
366 substs: &subst::Substs<'tcx>)
367 -> ty::ClosureTy<'tcx>
369 self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs)
372 fn closure_upvars(&self,
374 substs: &Substs<'tcx>)
375 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
377 ty::closure_upvars(self, def_id, substs)
381 impl<'a, 'tcx> Inherited<'a, 'tcx> {
382 fn new(tcx: &'a ty::ctxt<'tcx>,
383 param_env: ty::ParameterEnvironment<'a, 'tcx>)
384 -> Inherited<'a, 'tcx> {
386 infcx: infer::new_infer_ctxt(tcx),
387 locals: RefCell::new(NodeMap()),
388 param_env: param_env,
389 node_types: RefCell::new(NodeMap()),
390 item_substs: RefCell::new(NodeMap()),
391 adjustments: RefCell::new(NodeMap()),
392 method_map: RefCell::new(FnvHashMap()),
393 object_cast_map: RefCell::new(NodeMap()),
394 upvar_capture_map: RefCell::new(FnvHashMap()),
395 closure_tys: RefCell::new(DefIdMap()),
396 closure_kinds: RefCell::new(DefIdMap()),
397 fn_sig_map: RefCell::new(NodeMap()),
398 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
399 deferred_call_resolutions: RefCell::new(DefIdMap()),
403 fn normalize_associated_types_in<T>(&self,
404 typer: &ty::ClosureTyper<'tcx>,
406 body_id: ast::NodeId,
409 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
411 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
412 assoc::normalize_associated_types_in(&self.infcx,
414 &mut *fulfillment_cx, span,
421 // Used by check_const and check_enum_variants
422 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
423 inh: &'a Inherited<'a, 'tcx>,
424 rty: ty::FnOutput<'tcx>,
425 body_id: ast::NodeId)
426 -> FnCtxt<'a, 'tcx> {
429 writeback_errors: Cell::new(false),
430 err_count_on_creation: ccx.tcx.sess.err_count(),
432 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
438 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
439 -> Inherited<'a, 'tcx> {
440 // It's kind of a kludge to manufacture a fake function context
441 // and statement context, but we might as well do write the code only once
442 let param_env = ty::empty_parameter_environment(ccx.tcx);
443 Inherited::new(ccx.tcx, param_env)
446 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
448 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
449 fn visit_item(&mut self, i: &'tcx ast::Item) {
450 check_item(self.ccx, i);
451 visit::walk_item(self, i);
454 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
456 ast::TyFixedLengthVec(_, ref expr) => {
457 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
462 visit::walk_ty(self, t);
466 pub fn check_item_types(ccx: &CrateCtxt) {
467 let krate = ccx.tcx.map.krate();
468 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
469 visit::walk_crate(&mut visit, krate);
471 // If types are not well-formed, it leads to all manner of errors
472 // downstream, so stop reporting errors at this point.
473 ccx.tcx.sess.abort_if_errors();
475 let mut visit = CheckItemTypesVisitor { ccx: ccx };
476 visit::walk_crate(&mut visit, krate);
478 ccx.tcx.sess.abort_if_errors();
481 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
482 decl: &'tcx ast::FnDecl,
483 body: &'tcx ast::Block,
487 param_env: ty::ParameterEnvironment<'a, 'tcx>)
490 ty::ty_bare_fn(_, ref fn_ty) => {
491 let inh = Inherited::new(ccx.tcx, param_env);
493 // Compute the fty from point of view of inside fn.
495 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
497 liberate_late_bound_regions(ccx.tcx,
498 region::DestructionScopeData::new(body.id),
501 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
503 let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
504 decl, fn_id, body, &inh);
506 vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
507 upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
508 vtable::select_all_fcx_obligations_or_error(&fcx);
509 regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
510 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
512 _ => ccx.tcx.sess.impossible_case(body.span,
513 "check_bare_fn: function type expected")
517 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
518 fcx: &'a FnCtxt<'a, 'tcx>
521 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
522 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
525 // infer the variable's type
526 let var_ty = self.fcx.infcx().next_ty_var();
527 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
531 // take type that the user specified
532 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
539 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
540 // Add explicitly-declared locals.
541 fn visit_local(&mut self, local: &'tcx ast::Local) {
542 let o_ty = match local.ty {
543 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
546 self.assign(local.span, local.id, o_ty);
547 debug!("Local variable {} is assigned type {}",
548 self.fcx.pat_to_string(&*local.pat),
549 self.fcx.infcx().ty_to_string(
550 self.fcx.inh.locals.borrow()[local.id].clone()));
551 visit::walk_local(self, local);
554 // Add pattern bindings.
555 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
556 if let ast::PatIdent(_, ref path1, _) = p.node {
557 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
558 let var_ty = self.assign(p.span, p.id, None);
560 self.fcx.require_type_is_sized(var_ty, p.span,
561 traits::VariableType(p.id));
563 debug!("Pattern binding {} is assigned to {} with type {}",
564 token::get_ident(path1.node),
565 self.fcx.infcx().ty_to_string(
566 self.fcx.inh.locals.borrow()[p.id].clone()),
567 var_ty.repr(self.fcx.tcx()));
570 visit::walk_pat(self, p);
573 fn visit_block(&mut self, b: &'tcx ast::Block) {
574 // non-obvious: the `blk` variable maps to region lb, so
575 // we have to keep this up-to-date. This
576 // is... unfortunate. It'd be nice to not need this.
577 visit::walk_block(self, b);
580 // Since an expr occurs as part of the type fixed size arrays we
581 // need to record the type for that node
582 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
584 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
585 self.visit_ty(&**ty);
586 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
588 _ => visit::walk_ty(self, t)
592 // Don't descend into fns and items
593 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
594 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
595 fn visit_item(&mut self, _: &ast::Item) { }
599 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
600 /// body and returns the function context used for that purpose, since in the case of a fn item
601 /// there is still a bit more to do.
604 /// * inherited: other fields inherited from the enclosing fn (if any)
605 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
606 unsafety: ast::Unsafety,
607 unsafety_id: ast::NodeId,
608 fn_sig: &ty::FnSig<'tcx>,
609 decl: &'tcx ast::FnDecl,
611 body: &'tcx ast::Block,
612 inherited: &'a Inherited<'a, 'tcx>)
616 let err_count_on_creation = tcx.sess.err_count();
618 let arg_tys = &fn_sig.inputs[];
619 let ret_ty = fn_sig.output;
621 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
626 // Create the function context. This is either derived from scratch or,
627 // in the case of function expressions, based on the outer context.
630 writeback_errors: Cell::new(false),
631 err_count_on_creation: err_count_on_creation,
633 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
638 // Remember return type so that regionck can access it later.
639 let mut fn_sig_tys: Vec<Ty> =
644 if let ty::FnConverging(ret_ty) = ret_ty {
645 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
646 fn_sig_tys.push(ret_ty);
649 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
651 fn_sig_tys.repr(tcx));
653 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
656 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
658 // Add formal parameters.
659 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
660 // Create type variables for each argument.
661 pat_util::pat_bindings(
664 |_bm, pat_id, sp, _path| {
665 let var_ty = visit.assign(sp, pat_id, None);
666 fcx.require_type_is_sized(var_ty, sp,
667 traits::VariableType(pat_id));
670 // Check the pattern.
673 map: pat_id_map(&tcx.def_map, &*input.pat),
675 _match::check_pat(&pcx, &*input.pat, *arg_ty);
678 visit.visit_block(body);
681 check_block_with_expected(&fcx, body, match ret_ty {
682 ty::FnConverging(result_type) => ExpectHasType(result_type),
683 ty::FnDiverging => NoExpectation
686 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
687 fcx.write_ty(input.id, *arg);
693 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
696 check_representable(tcx, span, id, "struct");
697 check_instantiable(tcx, span, id);
699 if ty::lookup_simd(tcx, local_def(id)) {
700 check_simd(tcx, span, id);
704 pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
705 debug!("check_item(it.id={}, it.ident={})",
707 ty::item_path_str(ccx.tcx, local_def(it.id)));
708 let _indenter = indenter();
711 ast::ItemStatic(_, _, ref e) |
712 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
713 ast::ItemEnum(ref enum_definition, _) => {
714 check_enum_variants(ccx,
716 &enum_definition.variants[],
719 ast::ItemFn(ref decl, _, _, _, ref body) => {
720 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
721 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
722 check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
724 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
725 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
727 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
729 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
730 Some(impl_trait_ref) => {
731 check_impl_items_against_trait(ccx,
739 for impl_item in impl_items {
741 ast::MethodImplItem(ref m) => {
742 check_method_body(ccx, &impl_pty.generics, &**m);
744 ast::TypeImplItem(_) => {
745 // Nothing to do here.
751 ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
752 check_trait_on_unimplemented(ccx, generics, it);
753 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
754 for trait_method in trait_methods {
755 match *trait_method {
756 RequiredMethod(..) => {
757 // Nothing to do, since required methods don't have
760 ProvidedMethod(ref m) => {
761 check_method_body(ccx, &trait_def.generics, &**m);
763 TypeTraitItem(_) => {
769 ast::ItemStruct(..) => {
770 check_struct(ccx, it.id, it.span);
772 ast::ItemTy(ref t, ref generics) => {
773 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
774 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
776 ast::ItemForeignMod(ref m) => {
777 if m.abi == abi::RustIntrinsic {
778 for item in &m.items {
779 check_intrinsic_type(ccx, &**item);
782 for item in &m.items {
783 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
784 if !pty.generics.types.is_empty() {
785 span_err!(ccx.tcx.sess, item.span, E0044,
786 "foreign items may not have type parameters");
789 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
790 if fn_decl.variadic && m.abi != abi::C {
791 span_err!(ccx.tcx.sess, item.span, E0045,
792 "variadic function must have C calling convention");
798 _ => {/* nothing to do */ }
802 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
803 generics: &ast::Generics,
805 if let Some(ref attr) = item.attrs.iter().find(|a| {
806 a.check_name("rustc_on_unimplemented")
808 if let Some(ref istring) = attr.value_str() {
809 let parser = Parser::new(&istring);
810 let types = &*generics.ty_params;
811 for token in parser {
813 Piece::String(_) => (), // Normal string, no need to check it
814 Piece::NextArgument(a) => match a.position {
815 // `{Self}` is allowed
816 Position::ArgumentNamed(s) if s == "Self" => (),
817 // So is `{A}` if A is a type parameter
818 Position::ArgumentNamed(s) => match types.iter().find(|t| {
819 t.ident.as_str() == s
823 span_err!(ccx.tcx.sess, attr.span, E0230,
824 "there is no type parameter \
826 s, item.ident.as_str());
829 // `{:1}` and `{}` are not to be used
830 Position::ArgumentIs(_) | Position::ArgumentNext => {
831 span_err!(ccx.tcx.sess, attr.span, E0231,
832 "only named substitution \
833 parameters are allowed");
839 span_err!(ccx.tcx.sess, attr.span, E0232,
840 "this attribute must have a value, \
841 eg `#[rustc_on_unimplemented = \"foo\"]`")
846 /// Type checks a method body.
850 /// * `item_generics`: generics defined on the impl/trait that contains
852 /// * `self_bound`: bound for the `Self` type parameter, if any
853 /// * `method`: the method definition
854 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
855 item_generics: &ty::Generics<'tcx>,
856 method: &'tcx ast::Method) {
857 debug!("check_method_body(item_generics={}, method.id={})",
858 item_generics.repr(ccx.tcx),
860 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
862 let fty = ty::node_id_to_type(ccx.tcx, method.id);
863 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
866 &*method.pe_fn_decl(),
874 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
876 impl_trait_ref: &ty::TraitRef<'tcx>,
877 impl_items: &[ast::ImplItem]) {
878 // Locate trait methods
880 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
882 // Check existing impl methods to see if they are both present in trait
883 // and compatible with trait signature
884 for impl_item in impl_items {
886 ast::MethodImplItem(ref impl_method) => {
887 let impl_method_def_id = local_def(impl_method.id);
888 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
891 // If this is an impl of a trait method, find the
892 // corresponding method definition in the trait.
893 let opt_trait_method_ty =
895 .find(|ti| ti.name() == impl_item_ty.name());
896 match opt_trait_method_ty {
897 Some(trait_method_ty) => {
898 match (trait_method_ty, &impl_item_ty) {
899 (&ty::MethodTraitItem(ref trait_method_ty),
900 &ty::MethodTraitItem(ref impl_method_ty)) => {
901 compare_impl_method(ccx.tcx,
904 impl_method.pe_body().id,
909 // This is span_bug as it should have already been
910 // caught in resolve.
913 &format!("item `{}` is of a different kind from its trait `{}`",
914 token::get_name(impl_item_ty.name()),
915 impl_trait_ref.repr(tcx)));
920 // This is span_bug as it should have already been
921 // caught in resolve.
924 &format!("method `{}` is not a member of trait `{}`",
925 token::get_name(impl_item_ty.name()),
926 impl_trait_ref.repr(tcx)));
930 ast::TypeImplItem(ref typedef) => {
931 let typedef_def_id = local_def(typedef.id);
932 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
935 // If this is an impl of an associated type, find the
936 // corresponding type definition in the trait.
937 let opt_associated_type =
939 .find(|ti| ti.name() == typedef_ty.name());
940 match opt_associated_type {
941 Some(associated_type) => {
942 match (associated_type, &typedef_ty) {
943 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
945 // This is `span_bug` as it should have
946 // already been caught in resolve.
949 &format!("item `{}` is of a different kind from its trait `{}`",
950 token::get_name(typedef_ty.name()),
951 impl_trait_ref.repr(tcx)));
956 // This is `span_bug` as it should have already been
957 // caught in resolve.
961 "associated type `{}` is not a member of \
963 token::get_name(typedef_ty.name()),
964 impl_trait_ref.repr(tcx)));
971 // Check for missing items from trait
972 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
973 let mut missing_methods = Vec::new();
974 for trait_item in &*trait_items {
976 ty::MethodTraitItem(ref trait_method) => {
978 impl_items.iter().any(|ii| {
980 ast::MethodImplItem(ref m) => {
981 m.pe_ident().name == trait_method.name
983 ast::TypeImplItem(_) => false,
987 provided_methods.iter().any(|m| m.name == trait_method.name);
988 if !is_implemented && !is_provided {
989 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
992 ty::TypeTraitItem(ref associated_type) => {
993 let is_implemented = impl_items.iter().any(|ii| {
995 ast::TypeImplItem(ref typedef) => {
996 typedef.ident.name == associated_type.name
998 ast::MethodImplItem(_) => false,
1001 if !is_implemented {
1002 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1008 if !missing_methods.is_empty() {
1009 span_err!(tcx.sess, impl_span, E0046,
1010 "not all trait items implemented, missing: {}",
1011 missing_methods.connect(", "));
1015 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1022 let tstr = fcx.infcx().ty_to_string(t_1);
1023 fcx.type_error_message(span, |actual| {
1024 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1027 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1028 let mtstr = match mt {
1029 ast::MutMutable => "mut ",
1030 ast::MutImmutable => ""
1032 if ty::type_is_trait(t_1) {
1033 span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
1035 span_help!(fcx.tcx().sess, span,
1036 "consider using an implicit coercion to `&{}{}` instead",
1040 ty::ty_uniq(..) => {
1041 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
1044 span_help!(fcx.tcx().sess, e_span,
1045 "consider using a box or reference as appropriate");
1048 fcx.write_error(id);
1052 fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1057 fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1061 fcx.type_error_message(span, |actual| {
1062 format!("illegal cast; cast through an \
1063 integer first: `{}` as `{}`",
1065 fcx.infcx().ty_to_string(t_1))
1069 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1070 let t_e_is_scalar = ty::type_is_scalar(t_e);
1071 let t_e_is_integral = ty::type_is_integral(t_e);
1072 let t_e_is_float = ty::type_is_floating_point(t_e);
1073 let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
1075 let t_1_is_scalar = ty::type_is_scalar(t_1);
1076 let t_1_is_char = ty::type_is_char(t_1);
1077 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1078 let t_1_is_float = ty::type_is_floating_point(t_1);
1080 // casts to scalars other than `char` and `bare fn` are trivial
1081 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 t_1_is_char {
1086 let t_e = fcx.infcx().shallow_resolve(t_e);
1087 if t_e.sty != ty::ty_uint(ast::TyU8) {
1088 fcx.type_error_message(span, |actual| {
1089 format!("only `u8` can be cast as \
1090 `char`, not `{}`", actual)
1093 } else if t_1.sty == ty::ty_bool {
1094 span_err!(fcx.tcx().sess, span, E0054,
1095 "cannot cast as `bool`, compare with zero instead");
1096 } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
1097 t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
1098 // Casts to float must go through an integer or boolean
1099 cast_through_integer_err(fcx, span, t_1, t_e)
1100 } else if t_e_is_c_enum && t_1_is_trivial {
1101 if ty::type_is_unsafe_ptr(t_1) {
1102 // ... and likewise with C enum -> *T
1103 cast_through_integer_err(fcx, span, t_1, t_e)
1105 // casts from C-like enums are allowed
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 !(t_e_is_scalar && 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))
1161 fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
1162 cast_expr: &ast::Expr,
1165 let id = cast_expr.id;
1166 let span = cast_expr.span;
1168 // Find the type of `e`. Supply hints based on the type we are casting to,
1170 let t_1 = fcx.to_ty(t);
1171 let t_1 = structurally_resolved_type(fcx, span, t_1);
1173 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1175 let t_e = fcx.expr_ty(e);
1177 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1178 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1180 if ty::type_is_error(t_e) {
1181 fcx.write_error(id);
1185 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1186 report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
1190 if ty::type_is_trait(t_1) {
1191 // This will be looked up later on.
1192 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1193 fcx.write_ty(id, t_1);
1197 let t_1 = structurally_resolved_type(fcx, span, t_1);
1198 let t_e = structurally_resolved_type(fcx, span, t_e);
1200 check_cast_inner(fcx, span, t_1, t_e, e);
1201 fcx.write_ty(id, t_1);
1204 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1205 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1207 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1208 ty::lookup_item_type(self.tcx(), id)
1211 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1212 ty::lookup_trait_def(self.tcx(), id)
1215 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1216 Some(&self.inh.param_env.free_substs)
1219 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1220 self.infcx().next_ty_var()
1223 fn projected_ty_from_poly_trait_ref(&self,
1225 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1226 item_name: ast::Name)
1229 let (trait_ref, _) =
1230 self.infcx().replace_late_bound_regions_with_fresh_var(
1232 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1235 self.normalize_associated_type(span, trait_ref, item_name)
1238 fn projected_ty(&self,
1240 trait_ref: Rc<ty::TraitRef<'tcx>>,
1241 item_name: ast::Name)
1244 self.normalize_associated_type(span, trait_ref, item_name)
1248 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1249 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1251 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1255 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1259 pub fn sess(&self) -> &Session {
1263 pub fn err_count_since_creation(&self) -> uint {
1264 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1267 /// Resolves type variables in `ty` if possible. Unlike the infcx
1268 /// version, this version will also select obligations if it seems
1269 /// useful, in an effort to get more type information.
1270 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1271 // No ty::infer()? Nothing needs doing.
1272 if !ty::type_has_ty_infer(ty) {
1276 // If `ty` is a type variable, see whether we already know what it is.
1277 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1278 if !ty::type_has_ty_infer(ty) {
1282 // If not, try resolving any new fcx obligations that have cropped up.
1283 vtable::select_new_fcx_obligations(self);
1284 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1285 if !ty::type_has_ty_infer(ty) {
1289 // If not, try resolving *all* pending obligations as much as
1290 // possible. This can help substantially when there are
1291 // indirect dependencies that don't seem worth tracking
1293 vtable::select_fcx_obligations_where_possible(self);
1294 self.infcx().resolve_type_vars_if_possible(&ty)
1297 /// Resolves all type variables in `t` and then, if any were left
1298 /// unresolved, substitutes an error type. This is used after the
1299 /// main checking when doing a second pass before writeback. The
1300 /// justification is that writeback will produce an error for
1301 /// these unconstrained type variables.
1302 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1303 let t = self.infcx().resolve_type_vars_if_possible(t);
1304 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1307 fn record_deferred_call_resolution(&self,
1308 closure_def_id: ast::DefId,
1309 r: DeferredCallResolutionHandler<'tcx>) {
1310 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1311 let mut vec = match deferred_call_resolutions.entry(closure_def_id) {
1312 Occupied(entry) => entry.into_mut(),
1313 Vacant(entry) => entry.insert(Vec::new()),
1318 fn remove_deferred_call_resolutions(&self,
1319 closure_def_id: ast::DefId)
1320 -> Vec<DeferredCallResolutionHandler<'tcx>>
1322 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1323 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1326 pub fn tag(&self) -> String {
1327 format!("{:?}", self as *const FnCtxt)
1330 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1331 match self.inh.locals.borrow().get(&nid) {
1334 self.tcx().sess.span_bug(
1336 &format!("no type for local variable {}",
1342 /// Apply "fallbacks" to some types
1343 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1344 pub fn default_type_parameters(&self) {
1345 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1346 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1347 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1348 if self.infcx().type_var_diverges(resolved) {
1349 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1351 match self.infcx().type_is_unconstrained_numeric(resolved) {
1352 UnconstrainedInt => {
1353 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1355 UnconstrainedFloat => {
1356 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1365 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1366 debug!("write_ty({}, {}) in fcx {}",
1367 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1368 self.inh.node_types.borrow_mut().insert(node_id, ty);
1371 pub fn write_object_cast(&self,
1373 trait_ref: ty::PolyTraitRef<'tcx>) {
1374 debug!("write_object_cast key={} trait_ref={}",
1375 key, trait_ref.repr(self.tcx()));
1376 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1379 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1380 if !substs.substs.is_noop() {
1381 debug!("write_substs({}, {}) in fcx {}",
1383 substs.repr(self.tcx()),
1386 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1390 pub fn write_autoderef_adjustment(&self,
1391 node_id: ast::NodeId,
1394 if derefs == 0 { return; }
1395 self.write_adjustment(
1398 ty::AdjustDerefRef(ty::AutoDerefRef {
1404 pub fn write_adjustment(&self,
1405 node_id: ast::NodeId,
1407 adj: ty::AutoAdjustment<'tcx>) {
1408 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1410 if adj.is_identity() {
1414 // Careful: adjustments can imply trait obligations if we are
1415 // casting from a concrete type to an object type. I think
1416 // it'd probably be nicer to move the logic that creates the
1417 // obligation into the code that creates the adjustment, but
1418 // that's a bit awkward, so instead we go digging and pull the
1419 // obligation out here.
1420 self.register_adjustment_obligations(span, &adj);
1421 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1424 /// Basically whenever we are converting from a type scheme into
1425 /// the fn body space, we always want to normalize associated
1426 /// types as well. This function combines the two.
1427 fn instantiate_type_scheme<T>(&self,
1429 substs: &Substs<'tcx>,
1432 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1434 let value = value.subst(self.tcx(), substs);
1435 let result = self.normalize_associated_types_in(span, &value);
1436 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1437 value.repr(self.tcx()),
1438 substs.repr(self.tcx()),
1439 result.repr(self.tcx()));
1443 /// As `instantiate_type_scheme`, but for the bounds found in a
1444 /// generic type scheme.
1445 fn instantiate_bounds(&self,
1447 substs: &Substs<'tcx>,
1448 bounds: &ty::GenericPredicates<'tcx>)
1449 -> ty::InstantiatedPredicates<'tcx>
1451 ty::InstantiatedPredicates {
1452 predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1457 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1458 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1460 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1463 fn normalize_associated_type(&self,
1465 trait_ref: Rc<ty::TraitRef<'tcx>>,
1466 item_name: ast::Name)
1469 let cause = traits::ObligationCause::new(span,
1471 traits::ObligationCauseCode::MiscObligation);
1472 self.inh.fulfillment_cx
1474 .normalize_projection_type(self.infcx(),
1477 trait_ref: trait_ref,
1478 item_name: item_name,
1483 fn register_adjustment_obligations(&self,
1485 adj: &ty::AutoAdjustment<'tcx>) {
1487 ty::AdjustReifyFnPointer(..) => {
1489 ty::AdjustDerefRef(ref d_r) => {
1492 self.register_autoref_obligations(span, a_r);
1500 fn register_autoref_obligations(&self,
1502 autoref: &ty::AutoRef<'tcx>) {
1504 ty::AutoUnsize(ref unsize) => {
1505 self.register_unsize_obligations(span, unsize);
1507 ty::AutoPtr(_, _, None) |
1508 ty::AutoUnsafe(_, None) => {
1510 ty::AutoPtr(_, _, Some(ref a_r)) |
1511 ty::AutoUnsafe(_, Some(ref a_r)) => {
1512 self.register_autoref_obligations(span, &**a_r)
1514 ty::AutoUnsizeUniq(ref unsize) => {
1515 self.register_unsize_obligations(span, unsize);
1520 fn register_unsize_obligations(&self,
1522 unsize: &ty::UnsizeKind<'tcx>) {
1523 debug!("register_unsize_obligations: unsize={:?}", unsize);
1526 ty::UnsizeLength(..) => {}
1527 ty::UnsizeStruct(ref u, _) => {
1528 self.register_unsize_obligations(span, &**u)
1530 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1531 vtable::check_object_safety(self.tcx(), ty_trait, span);
1533 // If the type is `Foo+'a`, ensures that the type
1534 // being cast to `Foo+'a` implements `Foo`:
1535 vtable::register_object_cast_obligations(self,
1540 // If the type is `Foo+'a`, ensures that the type
1541 // being cast to `Foo+'a` outlives `'a`:
1542 let cause = traits::ObligationCause { span: span,
1543 body_id: self.body_id,
1544 code: traits::ObjectCastObligation(self_ty) };
1545 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1550 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1551 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1552 /// Registers any trait obligations specified on `def_id` at the same time.
1554 /// Note that function is only intended to be used with types (notably, not fns). This is
1555 /// because it doesn't do any instantiation of late-bound regions.
1556 pub fn instantiate_type(&self,
1559 -> TypeAndSubsts<'tcx>
1562 ty::lookup_item_type(self.tcx(), def_id);
1563 let type_predicates =
1564 ty::lookup_predicates(self.tcx(), def_id);
1566 self.infcx().fresh_substs_for_generics(
1568 &type_scheme.generics);
1570 self.instantiate_bounds(span, &substs, &type_predicates);
1571 self.add_obligations_for_parameters(
1572 traits::ObligationCause::new(
1575 traits::ItemObligation(def_id)),
1578 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1586 /// Returns the type that this AST path refers to. If the path has no type
1587 /// parameters and the corresponding type has type parameters, fresh type
1588 /// and/or region variables are substituted.
1590 /// This is used when checking the constructor in struct literals.
1591 fn instantiate_struct_literal_ty(&self,
1594 -> TypeAndSubsts<'tcx>
1596 let tcx = self.tcx();
1598 let ty::TypeScheme { generics, ty: decl_ty } =
1599 ty::lookup_item_type(tcx, did);
1602 generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1604 let needs_defaults =
1606 path.segments.iter().all(|s| s.parameters.is_empty());
1608 let substs = if needs_defaults {
1610 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1612 self.infcx().region_vars_for_defs(path.span,
1613 generics.regions.get_slice(TypeSpace));
1614 Substs::new_type(tps, rps)
1616 astconv::ast_path_substs_for_ty(self, self, &generics, path)
1619 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1621 TypeAndSubsts { substs: substs, ty: ty }
1624 pub fn write_nil(&self, node_id: ast::NodeId) {
1625 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1627 pub fn write_error(&self, node_id: ast::NodeId) {
1628 self.write_ty(node_id, self.tcx().types.err);
1631 pub fn require_type_meets(&self,
1634 code: traits::ObligationCauseCode<'tcx>,
1635 bound: ty::BuiltinBound)
1637 self.register_builtin_bound(
1640 traits::ObligationCause::new(span, self.body_id, code));
1643 pub fn require_type_is_sized(&self,
1646 code: traits::ObligationCauseCode<'tcx>)
1648 self.require_type_meets(ty, span, code, ty::BoundSized);
1651 pub fn require_expr_have_sized_type(&self,
1653 code: traits::ObligationCauseCode<'tcx>)
1655 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1658 pub fn type_is_known_to_be_sized(&self,
1663 traits::type_known_to_meet_builtin_bound(self.infcx(),
1670 pub fn register_builtin_bound(&self,
1672 builtin_bound: ty::BuiltinBound,
1673 cause: traits::ObligationCause<'tcx>)
1675 self.inh.fulfillment_cx.borrow_mut()
1676 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1679 pub fn register_predicate(&self,
1680 obligation: traits::PredicateObligation<'tcx>)
1682 debug!("register_predicate({})",
1683 obligation.repr(self.tcx()));
1684 self.inh.fulfillment_cx
1686 .register_predicate_obligation(self.infcx(), obligation);
1689 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1690 let t = ast_ty_to_ty(self, self, ast_t);
1692 let mut bounds_checker = wf::BoundsChecker::new(self,
1696 bounds_checker.check_ty(t);
1701 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1702 pat.repr(self.tcx())
1705 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1706 match self.inh.node_types.borrow().get(&ex.id) {
1709 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1715 /// Apply `adjustment` to the type of `expr`
1716 pub fn adjust_expr_ty(&self,
1718 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1721 let raw_ty = self.expr_ty(expr);
1722 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1723 let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1724 ty::adjust_ty(self.tcx(),
1729 |method_call| self.inh.method_map.borrow()
1731 .map(|method| resolve_ty(method.ty)))
1734 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1735 match self.inh.node_types.borrow().get(&id) {
1737 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1739 self.tcx().sess.bug(
1740 &format!("no type for node {}: {} in fcx {}",
1741 id, self.tcx().map.node_to_string(id),
1747 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1748 self.inh.item_substs.borrow()
1751 pub fn opt_node_ty_substs<F>(&self,
1754 F: FnOnce(&ty::ItemSubsts<'tcx>),
1756 match self.inh.item_substs.borrow().get(&id) {
1762 pub fn mk_subty(&self,
1763 a_is_expected: bool,
1764 origin: infer::TypeOrigin,
1767 -> Result<(), ty::type_err<'tcx>> {
1768 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1771 pub fn mk_eqty(&self,
1772 a_is_expected: bool,
1773 origin: infer::TypeOrigin,
1776 -> Result<(), ty::type_err<'tcx>> {
1777 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1780 pub fn mk_subr(&self,
1781 origin: infer::SubregionOrigin<'tcx>,
1784 infer::mk_subr(self.infcx(), origin, sub, sup)
1787 pub fn type_error_message<M>(&self,
1790 actual_ty: Ty<'tcx>,
1791 err: Option<&ty::type_err<'tcx>>) where
1792 M: FnOnce(String) -> String,
1794 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1797 pub fn report_mismatched_types(&self,
1801 err: &ty::type_err<'tcx>) {
1802 self.infcx().report_mismatched_types(sp, e, a, err)
1805 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1806 /// outlive the region `r`.
1807 pub fn register_region_obligation(&self,
1810 cause: traits::ObligationCause<'tcx>)
1812 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1813 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1816 pub fn add_default_region_param_bounds(&self,
1817 substs: &Substs<'tcx>,
1820 for &ty in substs.types.iter() {
1821 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1822 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1823 traits::MiscObligation);
1824 self.register_region_obligation(ty, default_bound, cause);
1828 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1829 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1830 /// trait/region obligations.
1832 /// For example, if there is a function:
1835 /// fn foo<'a,T:'a>(...)
1838 /// and a reference:
1844 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1845 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1846 pub fn add_obligations_for_parameters(&self,
1847 cause: traits::ObligationCause<'tcx>,
1848 predicates: &ty::InstantiatedPredicates<'tcx>)
1850 assert!(!predicates.has_escaping_regions());
1852 debug!("add_obligations_for_parameters(predicates={})",
1853 predicates.repr(self.tcx()));
1855 let obligations = traits::predicates_for_generics(self.tcx(),
1859 obligations.map_move(|o| self.register_predicate(o));
1862 // Only for fields! Returns <none> for methods>
1863 // Indifferent to privacy flags
1864 pub fn lookup_field_ty(&self,
1866 class_id: ast::DefId,
1867 items: &[ty::field_ty],
1868 fieldname: ast::Name,
1869 substs: &subst::Substs<'tcx>)
1872 let o_field = items.iter().find(|f| f.name == fieldname);
1873 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1874 .map(|t| self.normalize_associated_types_in(span, &t))
1877 pub fn lookup_tup_field_ty(&self,
1879 class_id: ast::DefId,
1880 items: &[ty::field_ty],
1882 substs: &subst::Substs<'tcx>)
1885 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1886 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1887 .map(|t| self.normalize_associated_types_in(span, &t))
1891 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1892 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
1893 // RFC #599 specifies that object lifetime defaults take
1894 // precedence over other defaults. But within a fn body we
1895 // don't have a *default* region, rather we use inference to
1896 // find the *correct* region, which is strictly more general
1897 // (and anyway, within a fn body the right region may not even
1898 // be something the user can write explicitly, since it might
1899 // be some expression).
1900 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1903 fn anon_regions(&self, span: Span, count: uint)
1904 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1905 Ok((0..count).map(|_| {
1906 self.infcx().next_region_var(infer::MiscVariable(span))
1911 #[derive(Copy, Debug, PartialEq, Eq)]
1912 pub enum LvaluePreference {
1917 /// Whether `autoderef` requires types to resolve.
1918 #[derive(Copy, Debug, PartialEq, Eq)]
1919 pub enum UnresolvedTypeAction {
1920 /// Produce an error and return `ty_err` whenever a type cannot
1921 /// be resolved (i.e. it is `ty_infer`).
1923 /// Go on without emitting any errors, and return the unresolved
1924 /// type. Useful for probing, e.g. in coercions.
1928 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1929 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1931 /// Note: this method does not modify the adjustments table. The caller is responsible for
1932 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1933 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1936 opt_expr: Option<&ast::Expr>,
1937 unresolved_type_action: UnresolvedTypeAction,
1938 mut lvalue_pref: LvaluePreference,
1940 -> (Ty<'tcx>, uint, Option<T>)
1941 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1943 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1944 base_ty.repr(fcx.tcx()),
1945 opt_expr.repr(fcx.tcx()),
1948 let mut t = base_ty;
1949 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1950 let resolved_t = match unresolved_type_action {
1951 UnresolvedTypeAction::Error => {
1952 let resolved_t = structurally_resolved_type(fcx, sp, t);
1953 if ty::type_is_error(resolved_t) {
1954 return (resolved_t, autoderefs, None);
1958 UnresolvedTypeAction::Ignore => {
1959 // We can continue even when the type cannot be resolved
1960 // (i.e. it is an inference variable) because `ty::deref`
1961 // and `try_overloaded_deref` both simply return `None`
1962 // in such a case without producing spurious errors.
1963 fcx.resolve_type_vars_if_possible(t)
1967 match should_stop(resolved_t, autoderefs) {
1968 Some(x) => return (resolved_t, autoderefs, Some(x)),
1972 // Otherwise, deref if type is derefable:
1973 let mt = match ty::deref(resolved_t, false) {
1974 Some(mt) => Some(mt),
1976 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1978 // Super subtle: it might seem as though we should
1979 // pass `opt_expr` to `try_overloaded_deref`, so that
1980 // the (implicit) autoref of using an overloaded deref
1981 // would get added to the adjustment table. However we
1982 // do not do that, because it's kind of a
1983 // "meta-adjustment" -- instead, we just leave it
1984 // unrecorded and know that there "will be" an
1985 // autoref. regionck and other bits of the code base,
1986 // when they encounter an overloaded autoderef, have
1987 // to do some reconstructive surgery. This is a pretty
1988 // complex mess that is begging for a proper MIR.
1989 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1995 if mt.mutbl == ast::MutImmutable {
1996 lvalue_pref = NoPreference;
1999 None => return (resolved_t, autoderefs, None)
2003 // We've reached the recursion limit, error gracefully.
2004 span_err!(fcx.tcx().sess, sp, E0055,
2005 "reached the recursion limit while auto-dereferencing {}",
2006 base_ty.repr(fcx.tcx()));
2007 (fcx.tcx().types.err, 0, None)
2010 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2012 method_call: Option<MethodCall>,
2013 base_expr: Option<&ast::Expr>,
2015 lvalue_pref: LvaluePreference)
2016 -> Option<ty::mt<'tcx>>
2018 // Try DerefMut first, if preferred.
2019 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2020 (PreferMutLvalue, Some(trait_did)) => {
2021 method::lookup_in_trait(fcx, span, base_expr,
2022 token::intern("deref_mut"), trait_did,
2028 // Otherwise, fall back to Deref.
2029 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2030 (None, Some(trait_did)) => {
2031 method::lookup_in_trait(fcx, span, base_expr,
2032 token::intern("deref"), trait_did,
2035 (method, _) => method
2038 make_overloaded_lvalue_return_type(fcx, method_call, method)
2041 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2042 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2043 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2044 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2045 method_call: Option<MethodCall>,
2046 method: Option<MethodCallee<'tcx>>)
2047 -> Option<ty::mt<'tcx>>
2051 let ref_ty = // invoked methods have all LB regions instantiated
2052 ty::no_late_bound_regions(
2053 fcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
2055 Some(method_call) => {
2056 fcx.inh.method_map.borrow_mut().insert(method_call,
2062 ty::FnConverging(ref_ty) => {
2063 ty::deref(ref_ty, true)
2065 ty::FnDiverging => {
2066 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2074 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2075 base_expr: &ast::Expr,
2077 lvalue_pref: LvaluePreference,
2080 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2082 // FIXME(#18741) -- this is almost but not quite the same as the
2083 // autoderef that normal method probing does. They could likely be
2086 let (ty, autoderefs, final_mt) = autoderef(fcx,
2090 UnresolvedTypeAction::Error,
2093 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2094 step(adj_ty, autoderefref)
2097 if final_mt.is_some() {
2101 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2102 // do a final unsized coercion to yield [T].
2104 ty::ty_vec(element_ty, Some(n)) => {
2105 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2106 let autoderefref = ty::AutoDerefRef {
2107 autoderefs: autoderefs,
2108 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2110 step(adjusted_ty, autoderefref)
2118 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2119 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2120 /// This loop implements one step in that search; the autoderef loop is implemented by
2121 /// `autoderef_for_index`.
2122 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2123 method_call: MethodCall,
2125 base_expr: &'tcx ast::Expr,
2126 adjusted_ty: Ty<'tcx>,
2127 adjustment: ty::AutoDerefRef<'tcx>,
2128 lvalue_pref: LvaluePreference,
2130 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2132 let tcx = fcx.tcx();
2133 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2135 base_expr.repr(tcx),
2136 adjusted_ty.repr(tcx),
2138 index_ty.repr(tcx));
2140 let input_ty = fcx.infcx().next_ty_var();
2142 // First, try built-in indexing.
2143 match (ty::index(adjusted_ty), &index_ty.sty) {
2144 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2145 debug!("try_index_step: success, using built-in indexing");
2146 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2147 return Some((tcx.types.uint, ty));
2152 // Try `IndexMut` first, if preferred.
2153 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2154 (PreferMutLvalue, Some(trait_did)) => {
2155 method::lookup_in_trait_adjusted(fcx,
2158 token::intern("index_mut"),
2162 Some(vec![input_ty]))
2167 // Otherwise, fall back to `Index`.
2168 let method = match (method, tcx.lang_items.index_trait()) {
2169 (None, Some(trait_did)) => {
2170 method::lookup_in_trait_adjusted(fcx,
2173 token::intern("index"),
2177 Some(vec![input_ty]))
2179 (method, _) => method,
2182 // If some lookup succeeds, write callee into table and extract index/element
2183 // type from the method signature.
2184 // If some lookup succeeded, install method in table
2185 method.and_then(|method| {
2186 debug!("try_index_step: success, using overloaded indexing");
2187 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2188 map(|ret| (input_ty, ret.ty))
2192 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2194 method_fn_ty: Ty<'tcx>,
2195 callee_expr: &'tcx ast::Expr,
2196 args_no_rcvr: &'tcx [P<ast::Expr>],
2197 autoref_args: AutorefArgs,
2198 tuple_arguments: TupleArgumentsFlag,
2199 expected: Expectation<'tcx>)
2200 -> ty::FnOutput<'tcx> {
2201 if ty::type_is_error(method_fn_ty) {
2202 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2204 let err_inputs = match tuple_arguments {
2205 DontTupleArguments => err_inputs,
2206 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2209 check_argument_types(fcx,
2217 ty::FnConverging(fcx.tcx().types.err)
2219 match method_fn_ty.sty {
2220 ty::ty_bare_fn(_, ref fty) => {
2221 // HACK(eddyb) ignore self in the definition (see above).
2222 let expected_arg_tys = expected_types_for_fn_args(fcx,
2226 &fty.sig.0.inputs[1..]);
2227 check_argument_types(fcx,
2229 &fty.sig.0.inputs[1..],
2230 &expected_arg_tys[..],
2238 fcx.tcx().sess.span_bug(callee_expr.span,
2239 "method without bare fn type");
2245 /// Generic function that factors out common logic from function calls, method calls and overloaded
2247 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2249 fn_inputs: &[Ty<'tcx>],
2250 expected_arg_tys: &[Ty<'tcx>],
2251 args: &'tcx [P<ast::Expr>],
2252 autoref_args: AutorefArgs,
2254 tuple_arguments: TupleArgumentsFlag) {
2255 let tcx = fcx.ccx.tcx;
2257 // Grab the argument types, supplying fresh type variables
2258 // if the wrong number of arguments were supplied
2259 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2265 let mut expected_arg_tys = expected_arg_tys;
2266 let expected_arg_count = fn_inputs.len();
2267 let formal_tys = if tuple_arguments == TupleArguments {
2268 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2269 match tuple_type.sty {
2270 ty::ty_tup(ref arg_types) => {
2271 if arg_types.len() != args.len() {
2272 span_err!(tcx.sess, sp, E0057,
2273 "this function takes {} parameter{} but {} parameter{} supplied",
2275 if arg_types.len() == 1 {""} else {"s"},
2277 if args.len() == 1 {" was"} else {"s were"});
2278 expected_arg_tys = &[][];
2279 err_args(fcx.tcx(), args.len())
2281 expected_arg_tys = match expected_arg_tys.get(0) {
2282 Some(&ty) => match ty.sty {
2283 ty::ty_tup(ref tys) => &**tys,
2288 (*arg_types).clone()
2292 span_err!(tcx.sess, sp, E0059,
2293 "cannot use call notation; the first type parameter \
2294 for the function trait is neither a tuple nor unit");
2295 expected_arg_tys = &[][];
2296 err_args(fcx.tcx(), args.len())
2299 } else if expected_arg_count == supplied_arg_count {
2301 } else if variadic {
2302 if supplied_arg_count >= expected_arg_count {
2305 span_err!(tcx.sess, sp, E0060,
2306 "this function takes at least {} parameter{} \
2307 but {} parameter{} supplied",
2309 if expected_arg_count == 1 {""} else {"s"},
2311 if supplied_arg_count == 1 {" was"} else {"s were"});
2312 expected_arg_tys = &[][];
2313 err_args(fcx.tcx(), supplied_arg_count)
2316 span_err!(tcx.sess, sp, E0061,
2317 "this function takes {} parameter{} but {} parameter{} supplied",
2319 if expected_arg_count == 1 {""} else {"s"},
2321 if supplied_arg_count == 1 {" was"} else {"s were"});
2322 expected_arg_tys = &[][];
2323 err_args(fcx.tcx(), supplied_arg_count)
2326 debug!("check_argument_types: formal_tys={:?}",
2327 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2329 // Check the arguments.
2330 // We do this in a pretty awful way: first we typecheck any arguments
2331 // that are not anonymous functions, then we typecheck the anonymous
2332 // functions. This is so that we have more information about the types
2333 // of arguments when we typecheck the functions. This isn't really the
2334 // right way to do this.
2335 let xs = [false, true];
2336 for check_blocks in &xs {
2337 let check_blocks = *check_blocks;
2338 debug!("check_blocks={}", check_blocks);
2340 // More awful hacks: before we check argument types, try to do
2341 // an "opportunistic" vtable resolution of any trait bounds on
2342 // the call. This helps coercions.
2344 vtable::select_new_fcx_obligations(fcx);
2347 // For variadic functions, we don't have a declared type for all of
2348 // the arguments hence we only do our usual type checking with
2349 // the arguments who's types we do know.
2350 let t = if variadic {
2352 } else if tuple_arguments == TupleArguments {
2357 for (i, arg) in args.iter().take(t).enumerate() {
2358 let is_block = match arg.node {
2359 ast::ExprClosure(..) => true,
2363 if is_block == check_blocks {
2364 debug!("checking the argument");
2365 let mut formal_ty = formal_tys[i];
2367 match autoref_args {
2368 AutorefArgs::Yes => {
2369 match formal_ty.sty {
2370 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2373 // So we hit this case when one implements the
2374 // operator traits but leaves an argument as
2375 // just T instead of &T. We'll catch it in the
2376 // mismatch impl/trait method phase no need to
2379 formal_ty = tcx.types.err;
2383 AutorefArgs::No => {}
2386 // The special-cased logic below has three functions:
2387 // 1. Provide as good of an expected type as possible.
2388 let expected = expected_arg_tys.get(i).map(|&ty| {
2389 Expectation::rvalue_hint(ty)
2392 check_expr_with_unifier(fcx, &**arg,
2393 expected.unwrap_or(ExpectHasType(formal_ty)),
2395 // 2. Coerce to the most detailed type that could be coerced
2396 // to, which is `expected_ty` if `rvalue_hint` returns an
2397 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2398 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2399 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2401 // 3. Relate the expected type and the formal one,
2402 // if the expected type was used for the coercion.
2403 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2409 // We also need to make sure we at least write the ty of the other
2410 // arguments which we skipped above.
2412 for arg in args.iter().skip(expected_arg_count) {
2413 check_expr(fcx, &**arg);
2415 // There are a few types which get autopromoted when passed via varargs
2416 // in C but we just error out instead and require explicit casts.
2417 let arg_ty = structurally_resolved_type(fcx, arg.span,
2418 fcx.expr_ty(&**arg));
2420 ty::ty_float(ast::TyF32) => {
2421 fcx.type_error_message(arg.span,
2423 format!("can't pass an {} to variadic \
2424 function, cast to c_double", t)
2427 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2428 fcx.type_error_message(arg.span, |t| {
2429 format!("can't pass {} to variadic \
2430 function, cast to c_int",
2434 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2435 fcx.type_error_message(arg.span, |t| {
2436 format!("can't pass {} to variadic \
2437 function, cast to c_uint",
2447 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2448 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2449 (0..len).map(|_| tcx.types.err).collect()
2452 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2453 call_expr: &ast::Expr,
2454 output: ty::FnOutput<'tcx>) {
2455 fcx.write_ty(call_expr.id, match output {
2456 ty::FnConverging(output_ty) => output_ty,
2457 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2461 // AST fragment checking
2462 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2464 expected: Expectation<'tcx>)
2467 let tcx = fcx.ccx.tcx;
2470 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2471 ast::LitBinary(..) => {
2473 tcx.mk_region(ty::ReStatic),
2474 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2476 ast::LitByte(_) => tcx.types.u8,
2477 ast::LitChar(_) => tcx.types.char,
2478 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2479 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2480 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2481 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2483 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2484 ty::ty_char => Some(tcx.types.u8),
2485 ty::ty_ptr(..) => Some(tcx.types.uint),
2486 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2490 opt_ty.unwrap_or_else(
2491 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2493 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2494 ast::LitFloatUnsuffixed(_) => {
2495 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2497 ty::ty_float(_) => Some(ty),
2501 opt_ty.unwrap_or_else(
2502 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2504 ast::LitBool(_) => tcx.types.bool
2508 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2509 expr: &'tcx ast::Expr,
2510 expected: Ty<'tcx>) {
2511 check_expr_with_unifier(
2512 fcx, expr, ExpectHasType(expected), NoPreference,
2513 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2516 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2517 expr: &'tcx ast::Expr,
2518 expected: Ty<'tcx>) {
2519 check_expr_with_unifier(
2520 fcx, expr, ExpectHasType(expected), NoPreference,
2521 || demand::coerce(fcx, expr.span, expected, expr));
2524 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2525 expected: Ty<'tcx>) {
2526 check_expr_with_unifier(
2527 fcx, expr, ExpectHasType(expected), NoPreference,
2531 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2532 expr: &'tcx ast::Expr,
2533 expected: Expectation<'tcx>) {
2534 check_expr_with_unifier(
2535 fcx, expr, expected, NoPreference,
2539 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2540 expr: &'tcx ast::Expr,
2541 expected: Expectation<'tcx>,
2542 lvalue_pref: LvaluePreference)
2544 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2547 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2548 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2551 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2552 lvalue_pref: LvaluePreference) {
2553 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2556 // determine the `self` type, using fresh variables for all variables
2557 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2558 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2560 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2561 span: Span, // (potential) receiver for this impl
2563 -> TypeAndSubsts<'tcx> {
2564 let tcx = fcx.tcx();
2566 let ity = ty::lookup_item_type(tcx, did);
2567 let (n_tps, rps, raw_ty) =
2568 (ity.generics.types.len(subst::TypeSpace),
2569 ity.generics.regions.get_slice(subst::TypeSpace),
2572 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2573 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2574 let substs = subst::Substs::new_type(tps, rps);
2575 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2577 TypeAndSubsts { substs: substs, ty: substd_ty }
2580 // Controls whether the arguments are automatically referenced. This is useful
2581 // for overloaded binary and unary operators.
2582 #[derive(Copy, PartialEq)]
2583 pub enum AutorefArgs {
2588 /// Controls whether the arguments are tupled. This is used for the call
2591 /// Tupling means that all call-side arguments are packed into a tuple and
2592 /// passed as a single parameter. For example, if tupling is enabled, this
2595 /// fn f(x: (int, int))
2597 /// Can be called as:
2604 #[derive(Clone, Eq, PartialEq)]
2605 enum TupleArgumentsFlag {
2610 /// Unifies the return type with the expected type early, for more coercions
2611 /// and forward type information on the argument expressions.
2612 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2614 expected_ret: Expectation<'tcx>,
2615 formal_ret: ty::FnOutput<'tcx>,
2616 formal_args: &[Ty<'tcx>])
2618 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2619 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2620 fcx.infcx().commit_regions_if_ok(|| {
2621 // Attempt to apply a subtyping relationship between the formal
2622 // return type (likely containing type variables if the function
2623 // is polymorphic) and the expected return type.
2624 // No argument expectations are produced if unification fails.
2625 let origin = infer::Misc(call_span);
2626 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2627 // FIXME(#15760) can't use try! here, FromError doesn't default
2628 // to identity so the resulting type is not constrained.
2629 if let Err(e) = ures {
2633 // Record all the argument types, with the substitutions
2634 // produced from the above subtyping unification.
2635 Ok(formal_args.iter().map(|ty| {
2636 fcx.infcx().resolve_type_vars_if_possible(ty)
2642 }).unwrap_or(vec![]);
2643 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2644 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2645 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2650 /// If an expression has any sub-expressions that result in a type error,
2651 /// inspecting that expression's type with `ty::type_is_error` will return
2652 /// true. Likewise, if an expression is known to diverge, inspecting its
2653 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2654 /// strict, _|_ can appear in the type of an expression that does not,
2655 /// itself, diverge: for example, fn() -> _|_.)
2656 /// Note that inspecting a type's structure *directly* may expose the fact
2657 /// that there are actually multiple representations for `ty_err`, so avoid
2658 /// that when err needs to be handled differently.
2659 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2660 expr: &'tcx ast::Expr,
2661 expected: Expectation<'tcx>,
2662 lvalue_pref: LvaluePreference,
2666 debug!(">> typechecking: expr={} expected={}",
2667 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2669 // Checks a method call.
2670 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2671 expr: &'tcx ast::Expr,
2672 method_name: ast::SpannedIdent,
2673 args: &'tcx [P<ast::Expr>],
2675 expected: Expectation<'tcx>,
2676 lvalue_pref: LvaluePreference) {
2677 let rcvr = &*args[0];
2678 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2680 // no need to check for bot/err -- callee does that
2681 let expr_t = structurally_resolved_type(fcx,
2683 fcx.expr_ty(&*rcvr));
2685 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2686 let fn_ty = match method::lookup(fcx,
2688 method_name.node.name,
2694 let method_ty = method.ty;
2695 let method_call = MethodCall::expr(expr.id);
2696 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2700 method::report_error(fcx, method_name.span, expr_t,
2701 method_name.node.name, rcvr, error);
2702 fcx.write_error(expr.id);
2707 // Call the generic checker.
2708 let ret_ty = check_method_argument_types(fcx,
2717 write_call(fcx, expr, ret_ty);
2720 // A generic function for checking the then and else in an if
2722 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2723 cond_expr: &'tcx ast::Expr,
2724 then_blk: &'tcx ast::Block,
2725 opt_else_expr: Option<&'tcx ast::Expr>,
2728 expected: Expectation<'tcx>) {
2729 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2731 let expected = expected.adjust_for_branches(fcx);
2732 check_block_with_expected(fcx, then_blk, expected);
2733 let then_ty = fcx.node_ty(then_blk.id);
2735 let branches_ty = match opt_else_expr {
2736 Some(ref else_expr) => {
2737 check_expr_with_expectation(fcx, &**else_expr, expected);
2738 let else_ty = fcx.expr_ty(&**else_expr);
2739 infer::common_supertype(fcx.infcx(),
2740 infer::IfExpression(sp),
2746 infer::common_supertype(fcx.infcx(),
2747 infer::IfExpressionWithNoElse(sp),
2750 ty::mk_nil(fcx.tcx()))
2754 let cond_ty = fcx.expr_ty(cond_expr);
2755 let if_ty = if ty::type_is_error(cond_ty) {
2761 fcx.write_ty(id, if_ty);
2764 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2765 op_ex: &'tcx ast::Expr,
2768 trait_did: Option<ast::DefId>,
2770 rhs: Option<&'tcx P<ast::Expr>>,
2772 autoref_args: AutorefArgs) -> Ty<'tcx> where
2775 let method = match trait_did {
2776 Some(trait_did) => {
2777 // We do eager coercions to make using operators
2780 // - If the input is of type &'a T (resp. &'a mut T),
2781 // then reborrow it to &'b T (resp. &'b mut T) where
2782 // 'b <= 'a. This makes things like `x == y`, where
2783 // `x` and `y` are both region pointers, work. We
2784 // could also solve this with variance or different
2785 // traits that don't force left and right to have same
2787 let (adj_ty, adjustment) = match lhs_ty.sty {
2788 ty::ty_rptr(r_in, mt) => {
2789 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2790 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2791 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2792 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2793 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2794 (adjusted_ty, adjustment)
2797 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2801 debug!("adjusted_ty={} adjustment={:?}",
2802 adj_ty.repr(fcx.tcx()),
2805 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2806 trait_did, adjustment, adj_ty, None)
2810 let args = match rhs {
2811 Some(rhs) => slice::ref_slice(rhs),
2816 let method_ty = method.ty;
2817 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2818 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2819 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2820 match check_method_argument_types(fcx,
2828 ty::FnConverging(result_type) => result_type,
2829 ty::FnDiverging => fcx.tcx().types.err
2834 // Check the args anyway
2835 // so we get all the error messages
2836 let expected_ty = fcx.tcx().types.err;
2837 check_method_argument_types(fcx,
2850 // could be either an expr_binop or an expr_assign_binop
2851 fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2852 expr: &'tcx ast::Expr,
2854 lhs: &'tcx ast::Expr,
2855 rhs: &'tcx P<ast::Expr>,
2856 is_binop_assignment: IsBinopAssignment) {
2857 let tcx = fcx.ccx.tcx;
2859 let lvalue_pref = match is_binop_assignment {
2860 BinopAssignment => PreferMutLvalue,
2861 SimpleBinop => NoPreference
2863 check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
2865 // Callee does bot / err checking
2867 structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || {
2868 if ast_util::is_symmetric_binop(op.node) {
2870 check_expr(fcx, &**rhs);
2877 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
2878 // Shift is a special case: rhs must be uint, no matter what lhs is
2879 check_expr(fcx, &**rhs);
2880 let rhs_ty = fcx.expr_ty(&**rhs);
2881 let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty);
2882 if ty::type_is_integral(rhs_ty) {
2883 fcx.write_ty(expr.id, lhs_t);
2885 fcx.type_error_message(
2889 "right-hand-side of a shift operation must have integral type, \
2895 fcx.write_ty(expr.id, fcx.tcx().types.err);
2900 if ty::is_binopable(tcx, lhs_t, op) {
2901 let tvar = fcx.infcx().next_ty_var();
2902 demand::suptype(fcx, expr.span, tvar, lhs_t);
2903 check_expr_has_type(fcx, &**rhs, tvar);
2905 let result_t = match op.node {
2906 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2908 if ty::type_is_simd(tcx, lhs_t) {
2909 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2910 fcx.type_error_message(expr.span,
2912 format!("binary comparison \
2913 operation `{}` not \
2914 supported for floating \
2915 point SIMD vector `{}`",
2916 ast_util::binop_to_string(op.node),
2927 fcx.tcx().types.bool
2933 fcx.write_ty(expr.id, result_t);
2937 if op.node == ast::BiOr || op.node == ast::BiAnd {
2938 // This is an error; one of the operands must have the wrong
2940 fcx.write_error(expr.id);
2941 fcx.write_error(rhs.id);
2942 fcx.type_error_message(expr.span,
2944 format!("binary operation `{}` cannot be applied \
2946 ast_util::binop_to_string(op.node),
2953 // Check for overloaded operators if not an assignment.
2954 let result_t = if is_binop_assignment == SimpleBinop {
2955 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2957 fcx.type_error_message(expr.span,
2959 format!("binary assignment \
2961 cannot be applied to \
2963 ast_util::binop_to_string(op.node),
2968 check_expr(fcx, &**rhs);
2972 fcx.write_ty(expr.id, result_t);
2973 if ty::type_is_error(result_t) {
2974 fcx.write_ty(rhs.id, result_t);
2978 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2979 ex: &'tcx ast::Expr,
2980 lhs_expr: &'tcx ast::Expr,
2981 lhs_resolved_t: Ty<'tcx>,
2983 rhs: &'tcx P<ast::Expr>) -> Ty<'tcx> {
2984 let tcx = fcx.ccx.tcx;
2985 let lang = &tcx.lang_items;
2986 let (name, trait_did) = match op.node {
2987 ast::BiAdd => ("add", lang.add_trait()),
2988 ast::BiSub => ("sub", lang.sub_trait()),
2989 ast::BiMul => ("mul", lang.mul_trait()),
2990 ast::BiDiv => ("div", lang.div_trait()),
2991 ast::BiRem => ("rem", lang.rem_trait()),
2992 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2993 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2994 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2995 ast::BiShl => ("shl", lang.shl_trait()),
2996 ast::BiShr => ("shr", lang.shr_trait()),
2997 ast::BiLt => ("lt", lang.ord_trait()),
2998 ast::BiLe => ("le", lang.ord_trait()),
2999 ast::BiGe => ("ge", lang.ord_trait()),
3000 ast::BiGt => ("gt", lang.ord_trait()),
3001 ast::BiEq => ("eq", lang.eq_trait()),
3002 ast::BiNe => ("ne", lang.eq_trait()),
3003 ast::BiAnd | ast::BiOr => {
3004 check_expr(fcx, &**rhs);
3005 return tcx.types.err;
3008 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3009 trait_did, lhs_expr, Some(rhs), || {
3010 fcx.type_error_message(ex.span, |actual| {
3011 format!("binary operation `{}` cannot be applied to type `{}`",
3012 ast_util::binop_to_string(op.node),
3014 }, lhs_resolved_t, None)
3015 }, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes })
3018 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3021 trait_did: Option<ast::DefId>,
3022 ex: &'tcx ast::Expr,
3023 rhs_expr: &'tcx ast::Expr,
3025 op: ast::UnOp) -> Ty<'tcx> {
3026 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3027 trait_did, rhs_expr, None, || {
3028 fcx.type_error_message(ex.span, |actual| {
3029 format!("cannot apply unary operator `{}` to type `{}`",
3032 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3035 // Check field access expressions
3036 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3037 expr: &'tcx ast::Expr,
3038 lvalue_pref: LvaluePreference,
3039 base: &'tcx ast::Expr,
3040 field: &ast::SpannedIdent) {
3041 let tcx = fcx.ccx.tcx;
3042 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3043 let expr_t = structurally_resolved_type(fcx, expr.span,
3045 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3046 let (_, autoderefs, field_ty) = autoderef(fcx,
3050 UnresolvedTypeAction::Error,
3054 ty::ty_struct(base_id, substs) => {
3055 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3056 let fields = ty::lookup_struct_fields(tcx, base_id);
3057 fcx.lookup_field_ty(expr.span, base_id, &fields[..],
3058 field.node.name, &(*substs))
3065 fcx.write_ty(expr.id, field_ty);
3066 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3072 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3073 fcx.type_error_message(
3076 format!("attempted to take value of method `{}` on type \
3077 `{}`", token::get_ident(field.node), actual)
3081 tcx.sess.span_help(field.span,
3082 "maybe a `()` to call it is missing? \
3083 If not, try an anonymous function");
3085 fcx.type_error_message(
3088 format!("attempted access of field `{}` on \
3089 type `{}`, but no field with that \
3091 token::get_ident(field.node),
3095 if let Some(t) = ty::ty_to_def_id(expr_t) {
3096 suggest_field_names(t, field, tcx, vec![]);
3100 fcx.write_error(expr.id);
3103 // displays hints about the closest matches in field names
3104 fn suggest_field_names<'tcx>(id : DefId,
3105 field : &ast::SpannedIdent,
3106 tcx : &ty::ctxt<'tcx>,
3108 let ident = token::get_ident(field.node);
3110 // only find fits with at least one matching letter
3111 let mut best_dist = name.len();
3112 let fields = ty::lookup_struct_fields(tcx, id);
3113 let mut best = None;
3114 for elem in &fields {
3115 let n = elem.name.as_str();
3116 // ignore already set fields
3117 if skip.iter().any(|&x| x == n) {
3120 let dist = lev_distance(n, name);
3121 if dist < best_dist {
3126 if let Some(n) = best {
3127 tcx.sess.span_help(field.span,
3128 &format!("did you mean `{}`?", n));
3132 // Check tuple index expressions
3133 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3134 expr: &'tcx ast::Expr,
3135 lvalue_pref: LvaluePreference,
3136 base: &'tcx ast::Expr,
3137 idx: codemap::Spanned<uint>) {
3138 let tcx = fcx.ccx.tcx;
3139 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3140 let expr_t = structurally_resolved_type(fcx, expr.span,
3142 let mut tuple_like = false;
3143 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3144 let (_, autoderefs, field_ty) = autoderef(fcx,
3148 UnresolvedTypeAction::Error,
3152 ty::ty_struct(base_id, substs) => {
3153 tuple_like = ty::is_tuple_struct(tcx, base_id);
3155 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3156 let fields = ty::lookup_struct_fields(tcx, base_id);
3157 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
3158 idx.node, &(*substs))
3163 ty::ty_tup(ref v) => {
3165 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3172 fcx.write_ty(expr.id, field_ty);
3173 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3178 fcx.type_error_message(
3182 format!("attempted out-of-bounds tuple index `{}` on \
3187 format!("attempted tuple index `{}` on type `{}`, but the \
3188 type was not a tuple or tuple struct",
3195 fcx.write_error(expr.id);
3198 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3199 struct_ty: Ty<'tcx>,
3201 class_id: ast::DefId,
3202 node_id: ast::NodeId,
3203 substitutions: &'tcx subst::Substs<'tcx>,
3204 field_types: &[ty::field_ty],
3205 ast_fields: &'tcx [ast::Field],
3206 check_completeness: bool,
3207 enum_id_opt: Option<ast::DefId>) {
3208 let tcx = fcx.ccx.tcx;
3210 let mut class_field_map = FnvHashMap();
3211 let mut fields_found = 0;
3212 for field in field_types {
3213 class_field_map.insert(field.name, (field.id, false));
3216 let mut error_happened = false;
3218 // Typecheck each field.
3219 for field in ast_fields {
3220 let mut expected_field_type = tcx.types.err;
3222 let pair = class_field_map.get(&field.ident.node.name).cloned();
3225 fcx.type_error_message(
3227 |actual| match enum_id_opt {
3229 let variant_type = ty::enum_variant_with_id(tcx,
3232 format!("struct variant `{}::{}` has no field named `{}`",
3233 actual, variant_type.name.as_str(),
3234 token::get_ident(field.ident.node))
3237 format!("structure `{}` has no field named `{}`",
3239 token::get_ident(field.ident.node))
3244 // prevent all specified fields from being suggested
3245 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
3246 let actual_id = match enum_id_opt {
3247 Some(_) => class_id,
3248 None => ty::ty_to_def_id(struct_ty).unwrap()
3250 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3251 error_happened = true;
3253 Some((_, true)) => {
3254 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3255 "field `{}` specified more than once",
3256 token::get_ident(field.ident.node));
3257 error_happened = true;
3259 Some((field_id, false)) => {
3260 expected_field_type =
3261 ty::lookup_field_type(
3262 tcx, class_id, field_id, substitutions);
3263 expected_field_type =
3264 fcx.normalize_associated_types_in(
3265 field.span, &expected_field_type);
3266 class_field_map.insert(
3267 field.ident.node.name, (field_id, true));
3272 // Make sure to give a type to the field even if there's
3273 // an error, so we can continue typechecking
3274 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3278 fcx.write_error(node_id);
3281 if check_completeness && !error_happened {
3282 // Make sure the programmer specified all the fields.
3283 assert!(fields_found <= field_types.len());
3284 if fields_found < field_types.len() {
3285 let mut missing_fields = Vec::new();
3286 for class_field in field_types {
3287 let name = class_field.name;
3288 let (_, seen) = class_field_map[name];
3290 missing_fields.push(
3291 format!("`{}`", &token::get_name(name)))
3295 span_err!(tcx.sess, span, E0063,
3296 "missing field{}: {}",
3297 if missing_fields.len() == 1 {""} else {"s"},
3298 missing_fields.connect(", "));
3302 if !error_happened {
3303 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3304 class_id, substitutions));
3308 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3310 span: codemap::Span,
3311 class_id: ast::DefId,
3312 fields: &'tcx [ast::Field],
3313 base_expr: Option<&'tcx ast::Expr>) {
3314 let tcx = fcx.ccx.tcx;
3316 // Generate the struct type.
3318 ty: mut struct_type,
3319 substs: struct_substs
3320 } = fcx.instantiate_type(span, class_id);
3322 // Look up and check the fields.
3323 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3324 check_struct_or_variant_fields(fcx,
3329 fcx.ccx.tcx.mk_substs(struct_substs),
3332 base_expr.is_none(),
3334 if ty::type_is_error(fcx.node_ty(id)) {
3335 struct_type = tcx.types.err;
3338 // Check the base expression if necessary.
3341 Some(base_expr) => {
3342 check_expr_has_type(fcx, &*base_expr, struct_type);
3346 // Write in the resulting type.
3347 fcx.write_ty(id, struct_type);
3350 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3352 span: codemap::Span,
3353 enum_id: ast::DefId,
3354 variant_id: ast::DefId,
3355 fields: &'tcx [ast::Field]) {
3356 let tcx = fcx.ccx.tcx;
3358 // Look up the number of type parameters and the raw type, and
3359 // determine whether the enum is region-parameterized.
3362 substs: substitutions
3363 } = fcx.instantiate_type(span, enum_id);
3365 // Look up and check the enum variant fields.
3366 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3367 check_struct_or_variant_fields(fcx,
3372 fcx.ccx.tcx.mk_substs(substitutions),
3373 &variant_fields[..],
3377 fcx.write_ty(id, enum_type);
3380 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3382 fields: &'tcx [ast::Field],
3383 base_expr: &'tcx Option<P<ast::Expr>>) {
3384 // Make sure to still write the types
3385 // otherwise we might ICE
3386 fcx.write_error(id);
3387 for field in fields {
3388 check_expr(fcx, &*field.expr);
3391 Some(ref base) => check_expr(fcx, &**base),
3396 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3398 let tcx = fcx.ccx.tcx;
3401 ast::ExprBox(ref opt_place, ref subexpr) => {
3402 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3403 check_expr(fcx, &**subexpr);
3405 let mut checked = false;
3406 opt_place.as_ref().map(|place| match place.node {
3407 ast::ExprPath(ref path) => {
3408 // FIXME(pcwalton): For now we hardcode the two permissible
3409 // places: the exchange heap and the managed heap.
3410 let definition = lookup_def(fcx, path.span, place.id);
3411 let def_id = definition.def_id();
3412 let referent_ty = fcx.expr_ty(&**subexpr);
3413 if tcx.lang_items.exchange_heap() == Some(def_id) {
3414 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3422 span_err!(tcx.sess, expr.span, E0066,
3423 "only the managed heap and exchange heap are currently supported");
3424 fcx.write_ty(id, tcx.types.err);
3428 ast::ExprLit(ref lit) => {
3429 let typ = check_lit(fcx, &**lit, expected);
3430 fcx.write_ty(id, typ);
3432 ast::ExprBinary(op, ref lhs, ref rhs) => {
3433 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3435 let lhs_ty = fcx.expr_ty(&**lhs);
3436 let rhs_ty = fcx.expr_ty(&**rhs);
3437 if ty::type_is_error(lhs_ty) ||
3438 ty::type_is_error(rhs_ty) {
3439 fcx.write_error(id);
3442 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3443 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3445 let lhs_t = fcx.expr_ty(&**lhs);
3446 let result_t = fcx.expr_ty(expr);
3447 demand::suptype(fcx, expr.span, result_t, lhs_t);
3449 let tcx = fcx.tcx();
3450 if !ty::expr_is_lval(tcx, &**lhs) {
3451 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3454 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3456 // Overwrite result of check_binop...this preserves existing behavior
3457 // but seems quite dubious with regard to user-defined methods
3458 // and so forth. - Niko
3459 if !ty::type_is_error(result_t) {
3460 fcx.write_nil(expr.id);
3463 ast::ExprUnary(unop, ref oprnd) => {
3464 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3466 ast::UnUniq => match ty.sty {
3467 ty::ty_uniq(ty) => {
3468 Expectation::rvalue_hint(ty)
3474 ast::UnNot | ast::UnNeg => {
3482 let lvalue_pref = match unop {
3483 ast::UnDeref => lvalue_pref,
3486 check_expr_with_expectation_and_lvalue_pref(
3487 fcx, &**oprnd, expected_inner, lvalue_pref);
3488 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3490 if !ty::type_is_error(oprnd_t) {
3493 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3496 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3497 oprnd_t = match ty::deref(oprnd_t, true) {
3499 None => match try_overloaded_deref(fcx, expr.span,
3500 Some(MethodCall::expr(expr.id)),
3501 Some(&**oprnd), oprnd_t, lvalue_pref) {
3504 let is_newtype = match oprnd_t.sty {
3505 ty::ty_struct(did, substs) => {
3506 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3508 && fields[0].name ==
3509 token::special_idents::unnamed_field.name
3514 // This is an obsolete struct deref
3515 span_err!(tcx.sess, expr.span, E0068,
3516 "single-field tuple-structs can \
3517 no longer be dereferenced");
3519 fcx.type_error_message(expr.span, |actual| {
3520 format!("type `{}` cannot be \
3521 dereferenced", actual)
3530 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3532 if !(ty::type_is_integral(oprnd_t) ||
3533 oprnd_t.sty == ty::ty_bool) {
3534 oprnd_t = check_user_unop(fcx, "!", "not",
3535 tcx.lang_items.not_trait(),
3536 expr, &**oprnd, oprnd_t, unop);
3540 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3542 if !(ty::type_is_integral(oprnd_t) ||
3543 ty::type_is_fp(oprnd_t)) {
3544 oprnd_t = check_user_unop(fcx, "-", "neg",
3545 tcx.lang_items.neg_trait(),
3546 expr, &**oprnd, oprnd_t, unop);
3551 fcx.write_ty(id, oprnd_t);
3553 ast::ExprAddrOf(mutbl, ref oprnd) => {
3554 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3556 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3557 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3558 // Lvalues may legitimately have unsized types.
3559 // For example, dereferences of a fat pointer and
3560 // the last field of a struct can be unsized.
3561 ExpectHasType(mt.ty)
3563 Expectation::rvalue_hint(mt.ty)
3569 let lvalue_pref = match mutbl {
3570 ast::MutMutable => PreferMutLvalue,
3571 ast::MutImmutable => NoPreference
3573 check_expr_with_expectation_and_lvalue_pref(fcx,
3578 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3579 let oprnd_t = if ty::type_is_error(tm.ty) {
3582 // Note: at this point, we cannot say what the best lifetime
3583 // is to use for resulting pointer. We want to use the
3584 // shortest lifetime possible so as to avoid spurious borrowck
3585 // errors. Moreover, the longest lifetime will depend on the
3586 // precise details of the value whose address is being taken
3587 // (and how long it is valid), which we don't know yet until type
3588 // inference is complete.
3590 // Therefore, here we simply generate a region variable. The
3591 // region inferencer will then select the ultimate value.
3592 // Finally, borrowck is charged with guaranteeing that the
3593 // value whose address was taken can actually be made to live
3594 // as long as it needs to live.
3595 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3596 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3598 fcx.write_ty(id, oprnd_t);
3600 ast::ExprPath(ref path) => {
3601 let defn = lookup_def(fcx, path.span, id);
3602 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
3603 instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
3605 // We always require that the type provided as the value for
3606 // a type parameter outlives the moment of instantiation.
3607 constrain_path_type_parameters(fcx, expr);
3609 ast::ExprQPath(ref qpath) => {
3610 // Require explicit type params for the trait.
3611 let self_ty = fcx.to_ty(&*qpath.self_type);
3612 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3614 let defn = lookup_def(fcx, expr.span, id);
3615 let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
3616 let mut path = qpath.trait_ref.path.clone();
3617 path.segments.push(qpath.item_path.clone());
3618 instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
3619 defn, expr.span, expr.id);
3621 // We always require that the type provided as the value for
3622 // a type parameter outlives the moment of instantiation.
3623 constrain_path_type_parameters(fcx, expr);
3625 ast::ExprInlineAsm(ref ia) => {
3626 for &(_, ref input) in &ia.inputs {
3627 check_expr(fcx, &**input);
3629 for &(_, ref out, _) in &ia.outputs {
3630 check_expr(fcx, &**out);
3634 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3635 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3636 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3637 ast::ExprRet(ref expr_opt) => {
3639 ty::FnConverging(result_type) => {
3642 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3643 result_type, ty::mk_nil(fcx.tcx())) {
3644 span_err!(tcx.sess, expr.span, E0069,
3645 "`return;` in function returning non-nil");
3648 check_expr_coercable_to_type(fcx, &**e, result_type);
3652 ty::FnDiverging => {
3653 if let Some(ref e) = *expr_opt {
3654 check_expr(fcx, &**e);
3656 span_err!(tcx.sess, expr.span, E0166,
3657 "`return` in a function declared as diverging");
3660 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3662 ast::ExprParen(ref a) => {
3663 check_expr_with_expectation_and_lvalue_pref(fcx,
3667 fcx.write_ty(id, fcx.expr_ty(&**a));
3669 ast::ExprAssign(ref lhs, ref rhs) => {
3670 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3672 let tcx = fcx.tcx();
3673 if !ty::expr_is_lval(tcx, &**lhs) {
3674 span_err!(tcx.sess, expr.span, E0070,
3675 "illegal left-hand side expression");
3678 let lhs_ty = fcx.expr_ty(&**lhs);
3679 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3680 let rhs_ty = fcx.expr_ty(&**rhs);
3682 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3684 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3685 fcx.write_error(id);
3690 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3691 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3692 id, expr.span, expected);
3694 ast::ExprIfLet(..) => {
3695 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3697 ast::ExprWhile(ref cond, ref body, _) => {
3698 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3699 check_block_no_value(fcx, &**body);
3700 let cond_ty = fcx.expr_ty(&**cond);
3701 let body_ty = fcx.node_ty(body.id);
3702 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3703 fcx.write_error(id);
3709 ast::ExprWhileLet(..) => {
3710 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3712 ast::ExprForLoop(..) => {
3713 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3715 ast::ExprLoop(ref body, _) => {
3716 check_block_no_value(fcx, &**body);
3717 if !may_break(tcx, expr.id, &**body) {
3718 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3723 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3724 _match::check_match(fcx, expr, &**discrim, arms, expected, match_src);
3726 ast::ExprClosure(capture, ref decl, ref body) => {
3727 closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected);
3729 ast::ExprBlock(ref b) => {
3730 check_block_with_expected(fcx, &**b, expected);
3731 fcx.write_ty(id, fcx.node_ty(b.id));
3733 ast::ExprCall(ref callee, ref args) => {
3734 callee::check_call(fcx, expr, &**callee, &args[..], expected);
3736 ast::ExprMethodCall(ident, ref tps, ref args) => {
3737 check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
3738 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3739 let args_err = arg_tys.fold(false,
3741 rest_err || ty::type_is_error(a)});
3743 fcx.write_error(id);
3746 ast::ExprCast(ref e, ref t) => {
3747 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3748 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3750 check_cast(fcx, expr, &**e, &**t);
3752 ast::ExprVec(ref args) => {
3753 let uty = expected.to_option(fcx).and_then(|uty| {
3755 ty::ty_vec(ty, _) => Some(ty),
3760 let typ = match uty {
3763 check_expr_coercable_to_type(fcx, &**e, uty);
3768 let t: Ty = fcx.infcx().next_ty_var();
3770 check_expr_has_type(fcx, &**e, t);
3775 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3776 fcx.write_ty(id, typ);
3778 ast::ExprRepeat(ref element, ref count_expr) => {
3779 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3780 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3782 let uty = match expected {
3783 ExpectHasType(uty) => {
3785 ty::ty_vec(ty, _) => Some(ty),
3792 let (element_ty, t) = match uty {
3794 check_expr_coercable_to_type(fcx, &**element, uty);
3798 let t: Ty = fcx.infcx().next_ty_var();
3799 check_expr_has_type(fcx, &**element, t);
3800 (fcx.expr_ty(&**element), t)
3805 // For [foo, ..n] where n > 1, `foo` must have
3807 fcx.require_type_meets(
3814 if ty::type_is_error(element_ty) {
3815 fcx.write_error(id);
3817 let t = ty::mk_vec(tcx, t, Some(count));
3818 fcx.write_ty(id, t);
3821 ast::ExprTup(ref elts) => {
3822 let flds = expected.only_has_type(fcx).and_then(|ty| {
3824 ty::ty_tup(ref flds) => Some(&flds[..]),
3828 let mut err_field = false;
3830 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3831 let t = match flds {
3832 Some(ref fs) if i < fs.len() => {
3834 check_expr_coercable_to_type(fcx, &**e, ety);
3838 check_expr_with_expectation(fcx, &**e, NoExpectation);
3842 err_field = err_field || ty::type_is_error(t);
3846 fcx.write_error(id);
3848 let typ = ty::mk_tup(tcx, elt_ts);
3849 fcx.write_ty(id, typ);
3852 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3853 // Resolve the path.
3854 let def = tcx.def_map.borrow().get(&id).cloned();
3855 let struct_id = match def {
3856 Some(def::DefVariant(enum_id, variant_id, true)) => {
3857 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3858 variant_id, &fields[..]);
3861 Some(def::DefTrait(def_id)) => {
3862 span_err!(tcx.sess, path.span, E0159,
3863 "use of trait `{}` as a struct constructor",
3864 pprust::path_to_string(path));
3865 check_struct_fields_on_error(fcx,
3872 // Verify that this was actually a struct.
3873 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3875 ty::ty_struct(struct_did, _) => {
3876 check_struct_constructor(fcx,
3881 base_expr.as_ref().map(|e| &**e));
3884 span_err!(tcx.sess, path.span, E0071,
3885 "`{}` does not name a structure",
3886 pprust::path_to_string(path));
3887 check_struct_fields_on_error(fcx,
3897 tcx.sess.span_bug(path.span,
3898 "structure constructor wasn't resolved")
3902 // Turn the path into a type and verify that that type unifies with
3903 // the resulting structure type. This is needed to handle type
3904 // parameters correctly.
3905 let actual_structure_type = fcx.expr_ty(&*expr);
3906 if !ty::type_is_error(actual_structure_type) {
3907 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3908 match fcx.mk_subty(false,
3909 infer::Misc(path.span),
3910 actual_structure_type,
3911 type_and_substs.ty) {
3913 Err(type_error) => {
3914 let type_error_description =
3915 ty::type_err_to_str(tcx, &type_error);
3916 span_err!(fcx.tcx().sess, path.span, E0235,
3917 "structure constructor specifies a \
3918 structure of type `{}`, but this \
3919 structure has type `{}`: {}",
3921 .ty_to_string(type_and_substs.ty),
3924 actual_structure_type),
3925 type_error_description);
3926 ty::note_and_explain_type_err(tcx, &type_error);
3931 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3933 ast::ExprField(ref base, ref field) => {
3934 check_field(fcx, expr, lvalue_pref, &**base, field);
3936 ast::ExprTupField(ref base, idx) => {
3937 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3939 ast::ExprIndex(ref base, ref idx) => {
3940 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3941 let base_t = fcx.expr_ty(&**base);
3942 if ty::type_is_error(base_t) {
3943 fcx.write_ty(id, base_t);
3945 check_expr(fcx, &**idx);
3946 let idx_t = fcx.expr_ty(&**idx);
3947 if ty::type_is_error(idx_t) {
3948 fcx.write_ty(id, idx_t);
3950 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3953 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3955 MethodCall::expr(expr.id),
3965 Some((index_ty, element_ty)) => {
3966 // FIXME: we've already checked idx above, we should
3967 // probably just demand subtype or something here.
3968 check_expr_has_type(fcx, &**idx, index_ty);
3969 fcx.write_ty(id, element_ty);
3972 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3973 fcx.type_error_message(
3976 format!("cannot index a value of type `{}`",
3981 fcx.write_ty(id, fcx.tcx().types.err);
3987 ast::ExprRange(ref start, ref end) => {
3988 let t_start = start.as_ref().map(|e| {
3989 check_expr(fcx, &**e);
3992 let t_end = end.as_ref().map(|e| {
3993 check_expr(fcx, &**e);
3997 let idx_type = match (t_start, t_end) {
3998 (Some(ty), None) | (None, Some(ty)) => {
4001 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
4002 ty::type_is_error(t_end)) => {
4003 Some(fcx.tcx().types.err)
4005 (Some(t_start), Some(t_end)) => {
4006 Some(infer::common_supertype(fcx.infcx(),
4007 infer::RangeExpression(expr.span),
4015 // Note that we don't check the type of start/end satisfy any
4016 // bounds because right now the range structs do not have any. If we add
4017 // some bounds, then we'll need to check `t_start` against them here.
4019 let range_type = match idx_type {
4020 Some(idx_type) if ty::type_is_error(idx_type) => {
4024 // Find the did from the appropriate lang item.
4025 let did = match (start, end) {
4026 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
4027 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
4028 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4030 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4034 if let Some(did) = did {
4035 let predicates = ty::lookup_predicates(tcx, did);
4036 let substs = Substs::new_type(vec![idx_type], vec![]);
4037 let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
4038 fcx.add_obligations_for_parameters(
4039 traits::ObligationCause::new(expr.span,
4041 traits::ItemObligation(did)),
4044 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4046 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
4051 // Neither start nor end => RangeFull
4052 if let Some(did) = tcx.lang_items.range_full_struct() {
4053 let substs = Substs::new_type(vec![], vec![]);
4054 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4056 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
4062 fcx.write_ty(id, range_type);
4067 debug!("type of expr({}) {} is...", expr.id,
4068 syntax::print::pprust::expr_to_string(expr));
4069 debug!("... {}, expected is {}",
4070 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4071 expected.repr(tcx));
4076 fn constrain_path_type_parameters(fcx: &FnCtxt,
4079 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4080 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4084 impl<'tcx> Expectation<'tcx> {
4085 /// Provide an expectation for an rvalue expression given an *optional*
4086 /// hint, which is not required for type safety (the resulting type might
4087 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4088 /// is useful in determining the concrete type.
4090 /// The primary use case is where the expected type is a fat pointer,
4091 /// like `&[int]`. For example, consider the following statement:
4093 /// let x: &[int] = &[1, 2, 3];
4095 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4096 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4097 /// expectation `ExpectHasType([int])`, that would be too strong --
4098 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4099 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4100 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4101 /// which still is useful, because it informs integer literals and the like.
4102 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4103 /// for examples of where this comes up,.
4104 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4106 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4107 ExpectRvalueLikeUnsized(ty)
4109 _ => ExpectHasType(ty)
4113 // Resolves `expected` by a single level if it is a variable. If
4114 // there is no expected type or resolution is not possible (e.g.,
4115 // no constraints yet present), just returns `None`.
4116 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4121 ExpectCastableToType(t) => {
4122 ExpectCastableToType(
4123 fcx.infcx().resolve_type_vars_if_possible(&t))
4125 ExpectHasType(t) => {
4127 fcx.infcx().resolve_type_vars_if_possible(&t))
4129 ExpectRvalueLikeUnsized(t) => {
4130 ExpectRvalueLikeUnsized(
4131 fcx.infcx().resolve_type_vars_if_possible(&t))
4136 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4137 match self.resolve(fcx) {
4138 NoExpectation => None,
4139 ExpectCastableToType(ty) |
4141 ExpectRvalueLikeUnsized(ty) => Some(ty),
4145 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4146 match self.resolve(fcx) {
4147 ExpectHasType(ty) => Some(ty),
4153 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4154 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4156 NoExpectation => format!("NoExpectation"),
4157 ExpectHasType(t) => format!("ExpectHasType({})",
4159 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4161 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4167 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
4169 init: &'tcx ast::Expr)
4171 let local_ty = fcx.local_ty(init.span, nid);
4172 check_expr_coercable_to_type(fcx, init, local_ty)
4175 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
4176 let tcx = fcx.ccx.tcx;
4178 let t = fcx.local_ty(local.span, local.id);
4179 fcx.write_ty(local.id, t);
4181 if let Some(ref init) = local.init {
4182 check_decl_initializer(fcx, local.id, &**init);
4183 let init_ty = fcx.expr_ty(&**init);
4184 if ty::type_is_error(init_ty) {
4185 fcx.write_ty(local.id, init_ty);
4189 let pcx = pat_ctxt {
4191 map: pat_id_map(&tcx.def_map, &*local.pat),
4193 _match::check_pat(&pcx, &*local.pat, t);
4194 let pat_ty = fcx.node_ty(local.pat.id);
4195 if ty::type_is_error(pat_ty) {
4196 fcx.write_ty(local.id, pat_ty);
4200 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4202 let mut saw_bot = false;
4203 let mut saw_err = false;
4205 ast::StmtDecl(ref decl, id) => {
4208 ast::DeclLocal(ref l) => {
4209 check_decl_local(fcx, &**l);
4210 let l_t = fcx.node_ty(l.id);
4211 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4212 saw_err = saw_err || ty::type_is_error(l_t);
4214 ast::DeclItem(_) => {/* ignore for now */ }
4217 ast::StmtExpr(ref expr, id) => {
4219 // Check with expected type of ()
4220 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4221 let expr_ty = fcx.expr_ty(&**expr);
4222 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4223 saw_err = saw_err || ty::type_is_error(expr_ty);
4225 ast::StmtSemi(ref expr, id) => {
4227 check_expr(fcx, &**expr);
4228 let expr_ty = fcx.expr_ty(&**expr);
4229 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4230 saw_err |= ty::type_is_error(expr_ty);
4232 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4235 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4238 fcx.write_error(node_id);
4241 fcx.write_nil(node_id)
4245 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4246 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4247 let blkty = fcx.node_ty(blk.id);
4248 if ty::type_is_error(blkty) {
4249 fcx.write_error(blk.id);
4251 let nilty = ty::mk_nil(fcx.tcx());
4252 demand::suptype(fcx, blk.span, nilty, blkty);
4256 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4257 blk: &'tcx ast::Block,
4258 expected: Expectation<'tcx>) {
4260 let mut fcx_ps = fcx.ps.borrow_mut();
4261 let unsafety_state = fcx_ps.recurse(blk);
4262 replace(&mut *fcx_ps, unsafety_state)
4265 let mut warned = false;
4266 let mut any_diverges = false;
4267 let mut any_err = false;
4268 for s in &blk.stmts {
4269 check_stmt(fcx, &**s);
4270 let s_id = ast_util::stmt_id(&**s);
4271 let s_ty = fcx.node_ty(s_id);
4272 if any_diverges && !warned && match s.node {
4273 ast::StmtDecl(ref decl, _) => {
4275 ast::DeclLocal(_) => true,
4279 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4285 .add_lint(lint::builtin::UNREACHABLE_CODE,
4288 "unreachable statement".to_string());
4291 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4292 any_err = any_err || ty::type_is_error(s_ty);
4295 None => if any_err {
4296 fcx.write_error(blk.id);
4297 } else if any_diverges {
4298 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4300 fcx.write_nil(blk.id);
4303 if any_diverges && !warned {
4307 .add_lint(lint::builtin::UNREACHABLE_CODE,
4310 "unreachable expression".to_string());
4312 let ety = match expected {
4313 ExpectHasType(ety) => {
4314 check_expr_coercable_to_type(fcx, &**e, ety);
4318 check_expr_with_expectation(fcx, &**e, expected);
4324 fcx.write_error(blk.id);
4325 } else if any_diverges {
4326 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4328 fcx.write_ty(blk.id, ety);
4333 *fcx.ps.borrow_mut() = prev;
4336 /// Checks a constant appearing in a type. At the moment this is just the
4337 /// length expression in a fixed-length vector, but someday it might be
4338 /// extended to type-level numeric literals.
4339 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4340 expr: &'tcx ast::Expr,
4341 expected_type: Ty<'tcx>) {
4342 let inh = static_inherited_fields(ccx);
4343 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4344 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4347 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4351 let inh = static_inherited_fields(ccx);
4352 let rty = ty::node_id_to_type(ccx.tcx, id);
4353 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4354 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4355 check_const_with_ty(&fcx, sp, e, declty);
4358 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4362 // Gather locals in statics (because of block expressions).
4363 // This is technically unnecessary because locals in static items are forbidden,
4364 // but prevents type checking from blowing up before const checking can properly
4366 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4368 check_expr_with_hint(fcx, e, declty);
4369 demand::coerce(fcx, e.span, declty, e);
4370 vtable::select_all_fcx_obligations_or_error(fcx);
4371 regionck::regionck_expr(fcx, e);
4372 writeback::resolve_type_vars_in_expr(fcx, e);
4375 /// Checks whether a type can be represented in memory. In particular, it
4376 /// identifies types that contain themselves without indirection through a
4377 /// pointer, which would mean their size is unbounded. This is different from
4378 /// the question of whether a type can be instantiated. See the definition of
4379 /// `check_instantiable`.
4380 pub fn check_representable(tcx: &ty::ctxt,
4382 item_id: ast::NodeId,
4383 designation: &str) -> bool {
4384 let rty = ty::node_id_to_type(tcx, item_id);
4386 // Check that it is possible to represent this type. This call identifies
4387 // (1) types that contain themselves and (2) types that contain a different
4388 // recursive type. It is only necessary to throw an error on those that
4389 // contain themselves. For case 2, there must be an inner type that will be
4390 // caught by case 1.
4391 match ty::is_type_representable(tcx, sp, rty) {
4392 ty::SelfRecursive => {
4393 span_err!(tcx.sess, sp, E0072,
4394 "illegal recursive {} type; \
4395 wrap the inner value in a box to make it representable",
4399 ty::Representable | ty::ContainsRecursive => (),
4404 /// Checks whether a type can be created without an instance of itself.
4405 /// This is similar but different from the question of whether a type
4406 /// can be represented. For example, the following type:
4408 /// enum foo { None, Some(foo) }
4410 /// is instantiable but is not representable. Similarly, the type
4412 /// enum foo { Some(@foo) }
4414 /// is representable, but not instantiable.
4415 pub fn check_instantiable(tcx: &ty::ctxt,
4417 item_id: ast::NodeId)
4419 let item_ty = ty::node_id_to_type(tcx, item_id);
4420 if !ty::is_instantiable(tcx, item_ty) {
4421 span_err!(tcx.sess, sp, E0073,
4422 "this type cannot be instantiated without an \
4423 instance of itself");
4424 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4425 ppaux::ty_to_string(tcx, item_ty));
4432 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4433 let t = ty::node_id_to_type(tcx, id);
4434 if ty::type_needs_subst(t) {
4435 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4439 ty::ty_struct(did, substs) => {
4440 let fields = ty::lookup_struct_fields(tcx, did);
4441 if fields.is_empty() {
4442 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4445 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4446 if !fields.iter().all(
4447 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4448 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4451 if !ty::type_is_machine(e) {
4452 span_err!(tcx.sess, sp, E0077,
4453 "SIMD vector element type should be machine type");
4461 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4463 vs: &'tcx [P<ast::Variant>],
4466 fn disr_in_range(ccx: &CrateCtxt,
4468 disr: ty::Disr) -> bool {
4469 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4471 ast::TyU8 => disr as u8 as Disr == disr,
4472 ast::TyU16 => disr as u16 as Disr == disr,
4473 ast::TyU32 => disr as u32 as Disr == disr,
4474 ast::TyU64 => disr as u64 as Disr == disr,
4475 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4478 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4480 ast::TyI8 => disr as i8 as Disr == disr,
4481 ast::TyI16 => disr as i16 as Disr == disr,
4482 ast::TyI32 => disr as i32 as Disr == disr,
4483 ast::TyI64 => disr as i64 as Disr == disr,
4484 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4488 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4489 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4493 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4494 vs: &'tcx [P<ast::Variant>],
4496 hint: attr::ReprAttr)
4497 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4499 let rty = ty::node_id_to_type(ccx.tcx, id);
4500 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4501 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4502 let mut prev_disr_val: Option<ty::Disr> = None;
4506 // If the discriminant value is specified explicitly in the enum check whether the
4507 // initialization expression is valid, otherwise use the last value plus one.
4508 let mut current_disr_val = match prev_disr_val {
4509 Some(prev_disr_val) => prev_disr_val + 1,
4510 None => ty::INITIAL_DISCRIMINANT_VALUE
4513 match v.node.disr_expr {
4515 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4517 let inh = static_inherited_fields(ccx);
4518 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4519 let declty = match hint {
4520 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4521 attr::ReprInt(_, attr::SignedInt(ity)) => {
4522 ty::mk_mach_int(fcx.tcx(), ity)
4524 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4525 ty::mk_mach_uint(fcx.tcx(), ity)
4528 check_const_with_ty(&fcx, e.span, &**e, declty);
4529 // check_expr (from check_const pass) doesn't guarantee
4530 // that the expression is in a form that eval_const_expr can
4531 // handle, so we may still get an internal compiler error
4533 match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
4534 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4535 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4537 span_err!(ccx.tcx.sess, e.span, E0079,
4538 "expected signed integer constant");
4541 span_err!(ccx.tcx.sess, e.span, E0080,
4542 "expected constant: {}", *err);
4549 // Check for duplicate discriminant values
4550 match disr_vals.iter().position(|&x| x == current_disr_val) {
4552 span_err!(ccx.tcx.sess, v.span, E0081,
4553 "discriminant value `{}` already exists", disr_vals[i]);
4554 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4555 "conflicting discriminant here")
4559 // Check for unrepresentable discriminant values
4561 attr::ReprAny | attr::ReprExtern => (),
4562 attr::ReprInt(sp, ity) => {
4563 if !disr_in_range(ccx, ity, current_disr_val) {
4564 span_err!(ccx.tcx.sess, v.span, E0082,
4565 "discriminant value outside specified type");
4566 span_note!(ccx.tcx.sess, sp,
4567 "discriminant type specified here");
4570 attr::ReprPacked => {
4571 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4574 disr_vals.push(current_disr_val);
4576 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4578 prev_disr_val = Some(current_disr_val);
4580 variants.push(variant_info);
4586 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4587 [].get(0).unwrap_or(&attr::ReprAny);
4589 if hint != attr::ReprAny && vs.len() <= 1 {
4591 span_err!(ccx.tcx.sess, sp, E0083,
4592 "unsupported representation for univariant enum");
4594 span_err!(ccx.tcx.sess, sp, E0084,
4595 "unsupported representation for zero-variant enum");
4599 let variants = do_check(ccx, vs, id, hint);
4601 // cache so that ty::enum_variants won't repeat this work
4602 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4604 check_representable(ccx.tcx, sp, id, "enum");
4606 // Check that it is possible to instantiate this enum:
4608 // This *sounds* like the same that as representable, but it's
4609 // not. See def'n of `check_instantiable()` for details.
4610 check_instantiable(ccx.tcx, sp, id);
4613 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4614 lookup_def_ccx(fcx.ccx, sp, id)
4617 // Returns the type parameter count and the type for the given definition.
4618 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4621 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
4623 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4624 let typ = fcx.local_ty(sp, nid);
4625 (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
4626 ty::GenericPredicates::empty())
4628 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4629 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4630 def::DefStruct(id) | def::DefConst(id) => {
4631 (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
4635 def::DefAssociatedTy(..) |
4636 def::DefAssociatedPath(..) |
4638 def::DefTyParam(..) |
4640 def::DefForeignMod(..) |
4642 def::DefRegion(..) |
4643 def::DefTyParamBinder(..) |
4645 def::DefSelfTy(..) => {
4646 fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
4651 // Instantiates the given path, which must refer to an item with the given
4652 // number of type parameters and type.
4653 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4655 type_scheme: TypeScheme<'tcx>,
4656 type_predicates: &ty::GenericPredicates<'tcx>,
4657 opt_self_ty: Option<Ty<'tcx>>,
4660 node_id: ast::NodeId) {
4661 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4662 path.repr(fcx.tcx()),
4663 def.repr(fcx.tcx()),
4665 type_scheme.repr(fcx.tcx()));
4667 // We need to extract the type parameters supplied by the user in
4668 // the path `path`. Due to the current setup, this is a bit of a
4669 // tricky-process; the problem is that resolve only tells us the
4670 // end-point of the path resolution, and not the intermediate steps.
4671 // Luckily, we can (at least for now) deduce the intermediate steps
4672 // just from the end-point.
4674 // There are basically three cases to consider:
4676 // 1. Reference to a *type*, such as a struct or enum:
4678 // mod a { struct Foo<T> { ... } }
4680 // Because we don't allow types to be declared within one
4681 // another, a path that leads to a type will always look like
4682 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4683 // that only the final segment can have type parameters, and
4684 // they are located in the TypeSpace.
4686 // *Note:* Generally speaking, references to types don't
4687 // actually pass through this function, but rather the
4688 // `ast_ty_to_ty` function in `astconv`. However, in the case
4689 // of struct patterns (and maybe literals) we do invoke
4690 // `instantiate_path` to get the general type of an instance of
4691 // a struct. (In these cases, there are actually no type
4692 // parameters permitted at present, but perhaps we will allow
4693 // them in the future.)
4695 // 1b. Reference to a enum variant or tuple-like struct:
4697 // struct foo<T>(...)
4698 // enum E<T> { foo(...) }
4700 // In these cases, the parameters are declared in the type
4703 // 2. Reference to a *fn item*:
4707 // In this case, the path will again always have the form
4708 // `a::b::foo::<T>` where only the final segment should have
4709 // type parameters. However, in this case, those parameters are
4710 // declared on a value, and hence are in the `FnSpace`.
4712 // 3. Reference to a *method*:
4714 // impl<A> SomeStruct<A> {
4718 // Here we can have a path like
4719 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4720 // may appear in two places. The penultimate segment,
4721 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4722 // final segment, `foo::<B>` contains parameters in fn space.
4724 // The first step then is to categorize the segments appropriately.
4726 assert!(path.segments.len() >= 1);
4727 let mut segment_spaces: Vec<_>;
4729 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4730 def::DefSelfTy(..) |
4731 def::DefStruct(..) |
4732 def::DefVariant(..) |
4733 def::DefTyParamBinder(..) |
4735 def::DefAssociatedTy(..) |
4736 def::DefAssociatedPath(..) |
4738 def::DefPrimTy(..) |
4739 def::DefTyParam(..) => {
4740 // Everything but the final segment should have no
4741 // parameters at all.
4742 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4743 segment_spaces.push(Some(subst::TypeSpace));
4746 // Case 2. Reference to a top-level value.
4749 def::DefStatic(..) => {
4750 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4751 segment_spaces.push(Some(subst::FnSpace));
4754 // Case 3. Reference to a method.
4755 def::DefStaticMethod(_, providence) |
4756 def::DefMethod(_, _, providence) => {
4757 assert!(path.segments.len() >= 2);
4760 def::FromTrait(trait_did) => {
4761 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4763 def::FromImpl(_) => {}
4766 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4767 segment_spaces.push(Some(subst::TypeSpace));
4768 segment_spaces.push(Some(subst::FnSpace));
4771 // Other cases. Various nonsense that really shouldn't show up
4772 // here. If they do, an error will have been reported
4773 // elsewhere. (I hope)
4775 def::DefForeignMod(..) |
4778 def::DefRegion(..) |
4780 def::DefUpvar(..) => {
4781 segment_spaces = repeat(None).take(path.segments.len()).collect();
4784 assert_eq!(segment_spaces.len(), path.segments.len());
4786 debug!("segment_spaces={:?}", segment_spaces);
4788 // Next, examine the definition, and determine how many type
4789 // parameters we expect from each space.
4790 let type_defs = &type_scheme.generics.types;
4791 let region_defs = &type_scheme.generics.regions;
4793 // Now that we have categorized what space the parameters for each
4794 // segment belong to, let's sort out the parameters that the user
4795 // provided (if any) into their appropriate spaces. We'll also report
4796 // errors if type parameters are provided in an inappropriate place.
4797 let mut substs = Substs::empty();
4798 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4801 report_error_if_segment_contains_type_parameters(fcx, segment);
4805 push_explicit_parameters_from_segment_to_substs(fcx,
4815 if let Some(self_ty) = opt_self_ty {
4816 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4817 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4818 substs.types.push(subst::SelfSpace, self_ty);
4821 // Now we have to compare the types that the user *actually*
4822 // provided against the types that were *expected*. If the user
4823 // did not provide any types, then we want to substitute inference
4824 // variables. If the user provided some types, we may still need
4825 // to add defaults. If the user provided *too many* types, that's
4827 for &space in &ParamSpace::all() {
4828 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4829 assert_eq!(substs.types.len(space), type_defs.len(space));
4831 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4832 assert_eq!(substs.regions().len(space), region_defs.len(space));
4835 // The things we are substituting into the type should not contain
4836 // escaping late-bound regions, and nor should the base type scheme.
4837 assert!(!substs.has_regions_escaping_depth(0));
4838 assert!(!type_scheme.has_escaping_regions());
4840 // Add all the obligations that are required, substituting and
4841 // normalized appropriately.
4842 let bounds = fcx.instantiate_bounds(span, &substs, &type_predicates);
4843 fcx.add_obligations_for_parameters(
4844 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4847 // Substitute the values for the type parameters into the type of
4848 // the referenced item.
4849 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4851 fcx.write_ty(node_id, ty_substituted);
4852 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4855 fn report_error_if_segment_contains_type_parameters(
4857 segment: &ast::PathSegment)
4859 for typ in &segment.parameters.types() {
4860 span_err!(fcx.tcx().sess, typ.span, E0085,
4861 "type parameters may not appear here");
4865 for lifetime in &segment.parameters.lifetimes() {
4866 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4867 "lifetime parameters may not appear here");
4872 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4873 /// parameters are provided, then reports an error and clears the output vector.
4875 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4876 /// use inference variables. This seems less likely to lead to derived errors.
4878 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4879 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4880 /// here because we can easily use the precise span of the N+1'th parameter.
4881 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4882 fcx: &FnCtxt<'a, 'tcx>,
4883 space: subst::ParamSpace,
4885 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4886 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4887 segment: &ast::PathSegment,
4888 substs: &mut Substs<'tcx>)
4890 match segment.parameters {
4891 ast::AngleBracketedParameters(ref data) => {
4892 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4893 fcx, space, type_defs, region_defs, data, substs);
4896 ast::ParenthesizedParameters(ref data) => {
4897 span_err!(fcx.tcx().sess, span, E0238,
4898 "parenthesized parameters may only be used with a trait");
4899 push_explicit_parenthesized_parameters_from_segment_to_substs(
4900 fcx, space, span, type_defs, data, substs);
4905 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4906 fcx: &FnCtxt<'a, 'tcx>,
4907 space: subst::ParamSpace,
4908 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4909 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4910 data: &ast::AngleBracketedParameterData,
4911 substs: &mut Substs<'tcx>)
4914 let type_count = type_defs.len(space);
4915 assert_eq!(substs.types.len(space), 0);
4916 for (i, typ) in data.types.iter().enumerate() {
4917 let t = fcx.to_ty(&**typ);
4919 substs.types.push(space, t);
4920 } else if i == type_count {
4921 span_err!(fcx.tcx().sess, typ.span, E0087,
4922 "too many type parameters provided: \
4923 expected at most {} parameter(s), \
4924 found {} parameter(s)",
4925 type_count, data.types.len());
4926 substs.types.truncate(space, 0);
4932 if data.bindings.len() > 0 {
4933 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4934 "unexpected binding of associated item in expression path \
4935 (only allowed in type paths)");
4939 let region_count = region_defs.len(space);
4940 assert_eq!(substs.regions().len(space), 0);
4941 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4942 let r = ast_region_to_region(fcx.tcx(), lifetime);
4943 if i < region_count {
4944 substs.mut_regions().push(space, r);
4945 } else if i == region_count {
4946 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4947 "too many lifetime parameters provided: \
4948 expected {} parameter(s), found {} parameter(s)",
4950 data.lifetimes.len());
4951 substs.mut_regions().truncate(space, 0);
4959 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4960 /// but intended for `Foo(A,B) -> C` form. This expands to
4961 /// roughly the same thing as `Foo<(A,B),C>`. One important
4962 /// difference has to do with the treatment of anonymous
4963 /// regions, which are translated into bound regions (NYI).
4964 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4965 fcx: &FnCtxt<'a, 'tcx>,
4966 space: subst::ParamSpace,
4968 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4969 data: &ast::ParenthesizedParameterData,
4970 substs: &mut Substs<'tcx>)
4972 let type_count = type_defs.len(space);
4974 span_err!(fcx.tcx().sess, span, E0167,
4975 "parenthesized form always supplies 2 type parameters, \
4976 but only {} parameter(s) were expected",
4980 let input_tys: Vec<Ty> =
4981 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4984 ty::mk_tup(fcx.tcx(), input_tys);
4986 if type_count >= 1 {
4987 substs.types.push(space, tuple_ty);
4990 let output_ty: Option<Ty> =
4991 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
4994 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
4996 if type_count >= 2 {
4997 substs.types.push(space, output_ty);
5001 fn adjust_type_parameters<'a, 'tcx>(
5002 fcx: &FnCtxt<'a, 'tcx>,
5005 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5006 substs: &mut Substs<'tcx>)
5008 let provided_len = substs.types.len(space);
5009 let desired = defs.get_slice(space);
5010 let required_len = desired.iter()
5011 .take_while(|d| d.default.is_none())
5014 debug!("adjust_type_parameters(space={:?}, \
5023 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5024 assert!(provided_len <= desired.len());
5026 // Nothing specified at all: supply inference variables for
5028 if provided_len == 0 {
5029 substs.types.replace(space,
5030 fcx.infcx().next_ty_vars(desired.len()));
5034 // Too few parameters specified: report an error and use Err
5036 if provided_len < required_len {
5038 if desired.len() != required_len { "at least " } else { "" };
5039 span_err!(fcx.tcx().sess, span, E0089,
5040 "too few type parameters provided: expected {}{} parameter(s) \
5041 , found {} parameter(s)",
5042 qualifier, required_len, provided_len);
5043 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5047 // Otherwise, add in any optional parameters that the user
5048 // omitted. The case of *too many* parameters is handled
5050 // push_explicit_parameters_from_segment_to_substs(). Note
5051 // that the *default* type are expressed in terms of all prior
5052 // parameters, so we have to substitute as we go with the
5053 // partial substitution that we have built up.
5054 for i in provided_len..desired.len() {
5055 let default = desired[i].default.unwrap();
5056 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5057 substs.types.push(space, default);
5059 assert_eq!(substs.types.len(space), desired.len());
5061 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5064 fn adjust_region_parameters(
5068 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5069 substs: &mut Substs)
5071 let provided_len = substs.mut_regions().len(space);
5072 let desired = defs.get_slice(space);
5074 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5075 assert!(provided_len <= desired.len());
5077 // If nothing was provided, just use inference variables.
5078 if provided_len == 0 {
5079 substs.mut_regions().replace(
5081 fcx.infcx().region_vars_for_defs(span, desired));
5085 // If just the right number were provided, everybody is happy.
5086 if provided_len == desired.len() {
5090 // Otherwise, too few were provided. Report an error and then
5091 // use inference variables.
5092 span_err!(fcx.tcx().sess, span, E0090,
5093 "too few lifetime parameters provided: expected {} parameter(s), \
5094 found {} parameter(s)",
5095 desired.len(), provided_len);
5097 substs.mut_regions().replace(
5099 fcx.infcx().region_vars_for_defs(span, desired));
5103 fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
5107 where F: Fn() -> Ty<'tcx>
5109 let mut ty = fcx.resolve_type_vars_if_possible(ty);
5111 if ty::type_is_ty_var(ty) {
5112 let alternative = f();
5115 if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
5116 fcx.type_error_message(sp, |_actual| {
5117 "the type of this value must be known in this context".to_string()
5119 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5120 ty = fcx.tcx().types.err;
5122 demand::suptype(fcx, sp, alternative, ty);
5130 // Resolves `typ` by a single level if `typ` is a type variable. If no
5131 // resolution is possible, then an error is reported.
5132 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5137 structurally_resolve_type_or_else(fcx, sp, ty, || {
5142 // Returns true if b contains a break that can exit from b
5143 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5144 // First: is there an unlabeled break immediately
5146 (loop_query(&*b, |e| {
5148 ast::ExprBreak(_) => true,
5152 // Second: is there a labeled break with label
5153 // <id> nested anywhere inside the loop?
5154 (block_query(b, |e| {
5156 ast::ExprBreak(Some(_)) => {
5157 match cx.def_map.borrow().get(&e.id) {
5158 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5166 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5168 tps: &OwnedSlice<ast::TyParam>,
5170 debug!("check_bounds_are_used(n_tps={}, ty={})",
5171 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5173 // make a vector of booleans initially false, set to true when used
5174 if tps.len() == 0 { return; }
5175 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5177 ty::walk_ty(ty, |t| {
5179 ty::ty_param(ParamTy {idx, ..}) => {
5180 debug!("Found use of ty param num {}", idx);
5181 tps_used[idx as uint] = true;
5187 for (i, b) in tps_used.iter().enumerate() {
5189 span_err!(ccx.tcx.sess, span, E0091,
5190 "type parameter `{}` is unused",
5191 token::get_ident(tps[i].ident));
5196 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5197 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5198 let name = token::intern(&format!("P{}", n));
5199 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5203 let name = token::get_ident(it.ident);
5204 let (n_tps, inputs, output) = if name.starts_with("atomic_") {
5205 let split : Vec<&str> = name.split('_').collect();
5206 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5208 //We only care about the operation here
5209 let (n_tps, inputs, output) = match split[1] {
5210 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5214 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5216 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5219 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5220 "min" | "umax" | "umin" => {
5221 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5225 (0, Vec::new(), ty::mk_nil(tcx))
5228 span_err!(tcx.sess, it.span, E0092,
5229 "unrecognized atomic operation function: `{}`", op);
5233 (n_tps, inputs, ty::FnConverging(output))
5234 } else if &name[..] == "abort" || &name[..] == "unreachable" {
5235 (0, Vec::new(), ty::FnDiverging)
5237 let (n_tps, inputs, output) = match &name[..] {
5238 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5240 "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.uint),
5241 "init" => (1, Vec::new(), param(ccx, 0)),
5242 "uninit" => (1, Vec::new(), param(ccx, 0)),
5243 "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5244 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5245 "move_val_init" => {
5248 ty::mk_mut_rptr(tcx,
5249 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5256 "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
5257 "owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
5260 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5262 Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); }
5264 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5266 mutbl: ast::MutImmutable
5268 (1, Vec::new(), td_ptr)
5270 "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
5274 ty::mk_ptr(tcx, ty::mt {
5276 mutbl: ast::MutImmutable
5280 ty::mk_ptr(tcx, ty::mt {
5282 mutbl: ast::MutImmutable
5285 "copy_memory" | "copy_nonoverlapping_memory" |
5286 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5289 ty::mk_ptr(tcx, ty::mt {
5291 mutbl: ast::MutMutable
5293 ty::mk_ptr(tcx, ty::mt {
5295 mutbl: ast::MutImmutable
5301 "set_memory" | "volatile_set_memory" => {
5304 ty::mk_ptr(tcx, ty::mt {
5306 mutbl: ast::MutMutable
5313 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5314 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5317 vec!( tcx.types.f32, tcx.types.i32 ),
5322 vec!( tcx.types.f64, tcx.types.i32 ),
5325 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5326 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5327 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5328 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5331 vec!( tcx.types.f32, tcx.types.f32 ),
5336 vec!( tcx.types.f64, tcx.types.f64 ),
5339 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5340 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5341 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5342 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5343 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5344 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5345 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5346 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5347 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5348 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5351 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5356 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5359 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5360 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5361 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5362 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5363 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5364 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5365 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5366 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5367 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5368 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5369 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5370 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5371 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5372 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5373 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5374 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5375 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5376 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5377 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5378 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5379 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5380 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5381 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5382 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5383 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5384 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5385 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5386 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5387 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5388 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5389 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5392 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5394 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5396 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5397 (0, vec!(tcx.types.i8, tcx.types.i8),
5398 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5400 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5401 (0, vec!(tcx.types.i16, tcx.types.i16),
5402 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5404 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5405 (0, vec!(tcx.types.i32, tcx.types.i32),
5406 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5408 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5409 (0, vec!(tcx.types.i64, tcx.types.i64),
5410 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5412 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5413 (0, vec!(tcx.types.u8, tcx.types.u8),
5414 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5416 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5417 (0, vec!(tcx.types.u16, tcx.types.u16),
5418 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5420 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5421 (0, vec!(tcx.types.u32, tcx.types.u32),
5422 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5424 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5425 (0, vec!(tcx.types.u64, tcx.types.u64),
5426 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5428 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5430 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5433 span_err!(tcx.sess, it.span, E0093,
5434 "unrecognized intrinsic function: `{}`", *other);
5438 (n_tps, inputs, ty::FnConverging(output))
5440 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5441 unsafety: ast::Unsafety::Unsafe,
5442 abi: abi::RustIntrinsic,
5443 sig: ty::Binder(FnSig {
5449 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5450 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5451 if i_n_tps != n_tps {
5452 span_err!(tcx.sess, it.span, E0094,
5453 "intrinsic has wrong number of type \
5454 parameters: found {}, expected {}",
5457 require_same_types(tcx,
5464 format!("intrinsic has wrong type: expected `{}`",
5465 ppaux::ty_to_string(ccx.tcx, fty))