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::CodeExtent;
94 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
96 use middle::ty::{FnSig, 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, no_params, 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};
144 /// closures defined within the function. For example:
147 /// bar(move|| { ... })
150 /// Here, the function `foo()` and the closure passed to
151 /// `bar()` will each have their own `FnCtxt`, but they will
152 /// share the inherited fields.
153 pub struct Inherited<'a, 'tcx: 'a> {
154 infcx: infer::InferCtxt<'a, 'tcx>,
155 locals: RefCell<NodeMap<Ty<'tcx>>>,
156 param_env: ty::ParameterEnvironment<'a, 'tcx>,
159 node_types: RefCell<NodeMap<Ty<'tcx>>>,
160 item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
161 adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
162 method_map: MethodMap<'tcx>,
163 upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
164 closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
165 closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
166 object_cast_map: ObjectCastMap<'tcx>,
168 // A mapping from each fn's id to its signature, with all bound
169 // regions replaced with free ones. Unlike the other tables, this
170 // one is never copied into the tcx: it is only used by regionck.
171 fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
173 // Tracks trait obligations incurred during this function body.
174 fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
176 // When we process a call like `c()` where `c` is a closure type,
177 // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
178 // `FnOnce` closure. In that case, we defer full resolution of the
179 // call until upvar inference can kick in and make the
180 // decision. We keep these deferred resolutions grouped by the
181 // def-id of the closure, so that once we decide, we can easily go
182 // back and process them.
183 deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
186 trait DeferredCallResolution<'tcx> {
187 fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
190 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
192 /// When type-checking an expression, we propagate downward
193 /// whatever type hint we are able in the form of an `Expectation`.
195 enum Expectation<'tcx> {
196 /// We know nothing about what type this expression should have.
199 /// This expression should have the type given (or some subtype)
200 ExpectHasType(Ty<'tcx>),
202 /// This expression will be cast to the `Ty`
203 ExpectCastableToType(Ty<'tcx>),
205 /// This rvalue expression will be wrapped in `&` or `Box` and coerced
206 /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
207 ExpectRvalueLikeUnsized(Ty<'tcx>),
210 impl<'tcx> Expectation<'tcx> {
211 // Disregard "castable to" expectations because they
212 // can lead us astray. Consider for example `if cond
213 // {22} else {c} as u8` -- if we propagate the
214 // "castable to u8" constraint to 22, it will pick the
215 // type 22u8, which is overly constrained (c might not
216 // be a u8). In effect, the problem is that the
217 // "castable to" expectation is not the tightest thing
218 // we can say, so we want to drop it in this case.
219 // The tightest thing we can say is "must unify with
220 // else branch". Note that in the case of a "has type"
221 // constraint, this limitation does not hold.
223 // If the expected type is just a type variable, then don't use
224 // an expected type. Otherwise, we might write parts of the type
225 // when checking the 'then' block which are incompatible with the
227 fn adjust_for_branches<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
229 ExpectHasType(ety) => {
230 let ety = fcx.infcx().shallow_resolve(ety);
231 if !ty::type_is_ty_var(ety) {
237 ExpectRvalueLikeUnsized(ety) => {
238 ExpectRvalueLikeUnsized(ety)
245 #[derive(Copy, Clone)]
246 pub struct UnsafetyState {
247 pub def: ast::NodeId,
248 pub unsafety: ast::Unsafety,
253 pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState {
254 UnsafetyState { def: def, unsafety: unsafety, from_fn: true }
257 pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState {
258 match self.unsafety {
259 // If this unsafe, then if the outer function was already marked as
260 // unsafe we shouldn't attribute the unsafe'ness to the block. This
261 // way the block can be warned about instead of ignoring this
262 // extraneous block (functions are never warned about).
263 ast::Unsafety::Unsafe if self.from_fn => *self,
266 let (unsafety, def) = match blk.rules {
267 ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id),
268 ast::DefaultBlock => (unsafety, self.def),
270 UnsafetyState{ def: def,
278 /// Whether `check_binop` is part of an assignment or not.
279 /// Used to know whether we allow user overloads and to print
280 /// better messages on error.
282 enum IsBinopAssignment{
288 pub struct FnCtxt<'a, 'tcx: 'a> {
289 body_id: ast::NodeId,
291 // This flag is set to true if, during the writeback phase, we encounter
292 // a type error in this function.
293 writeback_errors: Cell<bool>,
295 // Number of errors that had been reported when we started
296 // checking this function. On exit, if we find that *more* errors
297 // have been reported, we will skip regionck and other work that
298 // expects the types within the function to be consistent.
299 err_count_on_creation: uint,
301 ret_ty: ty::FnOutput<'tcx>,
303 ps: RefCell<UnsafetyState>,
305 inh: &'a Inherited<'a, 'tcx>,
307 ccx: &'a CrateCtxt<'a, 'tcx>,
310 impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
311 fn tcx(&self) -> &ty::ctxt<'tcx> {
314 fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
315 let ty = self.node_ty(id);
316 self.resolve_type_vars_or_error(&ty)
318 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
319 let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
320 self.resolve_type_vars_or_error(&ty)
322 fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
323 let ty = self.infcx().resolve_type_vars_if_possible(&ty);
324 !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
326 fn node_method_ty(&self, method_call: ty::MethodCall)
327 -> Option<Ty<'tcx>> {
328 self.inh.method_map.borrow()
330 .map(|method| method.ty)
331 .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
333 fn node_method_origin(&self, method_call: ty::MethodCall)
334 -> Option<ty::MethodOrigin<'tcx>>
336 self.inh.method_map.borrow()
338 .map(|method| method.origin.clone())
340 fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
341 &self.inh.adjustments
343 fn is_method_call(&self, id: ast::NodeId) -> bool {
344 self.inh.method_map.borrow().contains_key(&ty::MethodCall::expr(id))
346 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
347 self.param_env().temporary_scope(rvalue_id)
349 fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
350 self.inh.upvar_capture_map.borrow().get(&upvar_id).cloned()
354 impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
355 fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
359 fn closure_kind(&self,
361 -> Option<ty::ClosureKind>
363 self.inh.closure_kinds.borrow().get(&def_id).cloned()
366 fn closure_type(&self,
368 substs: &subst::Substs<'tcx>)
369 -> ty::ClosureTy<'tcx>
371 self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs)
374 fn closure_upvars(&self,
376 substs: &Substs<'tcx>)
377 -> Option<Vec<ty::ClosureUpvar<'tcx>>>
379 ty::closure_upvars(self, def_id, substs)
383 impl<'a, 'tcx> Inherited<'a, 'tcx> {
384 fn new(tcx: &'a ty::ctxt<'tcx>,
385 param_env: ty::ParameterEnvironment<'a, 'tcx>)
386 -> Inherited<'a, 'tcx> {
388 infcx: infer::new_infer_ctxt(tcx),
389 locals: RefCell::new(NodeMap()),
390 param_env: param_env,
391 node_types: RefCell::new(NodeMap()),
392 item_substs: RefCell::new(NodeMap()),
393 adjustments: RefCell::new(NodeMap()),
394 method_map: RefCell::new(FnvHashMap()),
395 object_cast_map: RefCell::new(NodeMap()),
396 upvar_capture_map: RefCell::new(FnvHashMap()),
397 closure_tys: RefCell::new(DefIdMap()),
398 closure_kinds: RefCell::new(DefIdMap()),
399 fn_sig_map: RefCell::new(NodeMap()),
400 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
401 deferred_call_resolutions: RefCell::new(DefIdMap()),
405 fn normalize_associated_types_in<T>(&self,
406 typer: &ty::ClosureTyper<'tcx>,
408 body_id: ast::NodeId,
411 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
413 let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
414 assoc::normalize_associated_types_in(&self.infcx,
416 &mut *fulfillment_cx, span,
423 // Used by check_const and check_enum_variants
424 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
425 inh: &'a Inherited<'a, 'tcx>,
426 rty: ty::FnOutput<'tcx>,
427 body_id: ast::NodeId)
428 -> FnCtxt<'a, 'tcx> {
431 writeback_errors: Cell::new(false),
432 err_count_on_creation: ccx.tcx.sess.err_count(),
434 ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)),
440 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
441 -> Inherited<'a, 'tcx> {
442 // It's kind of a kludge to manufacture a fake function context
443 // and statement context, but we might as well do write the code only once
444 let param_env = ty::empty_parameter_environment(ccx.tcx);
445 Inherited::new(ccx.tcx, param_env)
448 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
450 impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
451 fn visit_item(&mut self, i: &'tcx ast::Item) {
452 check_item(self.ccx, i);
453 visit::walk_item(self, i);
456 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
458 ast::TyFixedLengthVec(_, ref expr) => {
459 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
464 visit::walk_ty(self, t);
468 pub fn check_item_types(ccx: &CrateCtxt) {
469 let krate = ccx.tcx.map.krate();
470 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
471 visit::walk_crate(&mut visit, krate);
473 // If types are not well-formed, it leads to all manner of errors
474 // downstream, so stop reporting errors at this point.
475 ccx.tcx.sess.abort_if_errors();
477 let mut visit = CheckItemTypesVisitor { ccx: ccx };
478 visit::walk_crate(&mut visit, krate);
480 ccx.tcx.sess.abort_if_errors();
483 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
484 decl: &'tcx ast::FnDecl,
485 body: &'tcx ast::Block,
488 param_env: ty::ParameterEnvironment<'a, 'tcx>)
491 ty::ty_bare_fn(_, ref fn_ty) => {
492 let inh = Inherited::new(ccx.tcx, param_env);
494 // Compute the fty from point of view of inside fn.
496 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
498 liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig);
500 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
502 let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
503 decl, id, body, &inh);
505 vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
506 upvar::closure_analyze_fn(&fcx, id, decl, body);
507 vtable::select_all_fcx_obligations_or_error(&fcx);
508 regionck::regionck_fn(&fcx, id, decl, body);
509 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
511 _ => ccx.tcx.sess.impossible_case(body.span,
512 "check_bare_fn: function type expected")
516 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
517 fcx: &'a FnCtxt<'a, 'tcx>
520 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
521 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
524 // infer the variable's type
525 let var_ty = self.fcx.infcx().next_ty_var();
526 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
530 // take type that the user specified
531 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
538 impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
539 // Add explicitly-declared locals.
540 fn visit_local(&mut self, local: &'tcx ast::Local) {
541 let o_ty = match local.ty {
542 Some(ref ty) => Some(self.fcx.to_ty(&**ty)),
545 self.assign(local.span, local.id, o_ty);
546 debug!("Local variable {} is assigned type {}",
547 self.fcx.pat_to_string(&*local.pat),
548 self.fcx.infcx().ty_to_string(
549 self.fcx.inh.locals.borrow()[local.id].clone()));
550 visit::walk_local(self, local);
553 // Add pattern bindings.
554 fn visit_pat(&mut self, p: &'tcx ast::Pat) {
555 if let ast::PatIdent(_, ref path1, _) = p.node {
556 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) {
557 let var_ty = self.assign(p.span, p.id, None);
559 self.fcx.require_type_is_sized(var_ty, p.span,
560 traits::VariableType(p.id));
562 debug!("Pattern binding {} is assigned to {} with type {}",
563 token::get_ident(path1.node),
564 self.fcx.infcx().ty_to_string(
565 self.fcx.inh.locals.borrow()[p.id].clone()),
566 var_ty.repr(self.fcx.tcx()));
569 visit::walk_pat(self, p);
572 fn visit_block(&mut self, b: &'tcx ast::Block) {
573 // non-obvious: the `blk` variable maps to region lb, so
574 // we have to keep this up-to-date. This
575 // is... unfortunate. It'd be nice to not need this.
576 visit::walk_block(self, b);
579 // Since an expr occurs as part of the type fixed size arrays we
580 // need to record the type for that node
581 fn visit_ty(&mut self, t: &'tcx ast::Ty) {
583 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
584 self.visit_ty(&**ty);
585 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
587 _ => visit::walk_ty(self, t)
591 // Don't descend into fns and items
592 fn visit_fn(&mut self, _: visit::FnKind<'tcx>, _: &'tcx ast::FnDecl,
593 _: &'tcx ast::Block, _: Span, _: ast::NodeId) { }
594 fn visit_item(&mut self, _: &ast::Item) { }
598 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
599 /// body and returns the function context used for that purpose, since in the case of a fn item
600 /// there is still a bit more to do.
603 /// * inherited: other fields inherited from the enclosing fn (if any)
604 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
605 unsafety: ast::Unsafety,
606 unsafety_id: ast::NodeId,
607 fn_sig: &ty::FnSig<'tcx>,
608 decl: &'tcx ast::FnDecl,
610 body: &'tcx ast::Block,
611 inherited: &'a Inherited<'a, 'tcx>)
615 let err_count_on_creation = tcx.sess.err_count();
617 let arg_tys = &fn_sig.inputs[];
618 let ret_ty = fn_sig.output;
620 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
625 // Create the function context. This is either derived from scratch or,
626 // in the case of function expressions, based on the outer context.
629 writeback_errors: Cell::new(false),
630 err_count_on_creation: err_count_on_creation,
632 ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)),
637 // Remember return type so that regionck can access it later.
638 let mut fn_sig_tys: Vec<Ty> =
643 if let ty::FnConverging(ret_ty) = ret_ty {
644 fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
645 fn_sig_tys.push(ret_ty);
648 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
650 fn_sig_tys.repr(tcx));
652 inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys);
655 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
657 // Add formal parameters.
658 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
659 // Create type variables for each argument.
660 pat_util::pat_bindings(
663 |_bm, pat_id, sp, _path| {
664 let var_ty = visit.assign(sp, pat_id, None);
665 fcx.require_type_is_sized(var_ty, sp,
666 traits::VariableType(pat_id));
669 // Check the pattern.
672 map: pat_id_map(&tcx.def_map, &*input.pat),
674 _match::check_pat(&pcx, &*input.pat, *arg_ty);
677 visit.visit_block(body);
680 check_block_with_expected(&fcx, body, match ret_ty {
681 ty::FnConverging(result_type) => ExpectHasType(result_type),
682 ty::FnDiverging => NoExpectation
685 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
686 fcx.write_ty(input.id, *arg);
692 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
695 check_representable(tcx, span, id, "struct");
696 check_instantiable(tcx, span, id);
698 if ty::lookup_simd(tcx, local_def(id)) {
699 check_simd(tcx, span, id);
703 pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
704 debug!("check_item(it.id={}, it.ident={})",
706 ty::item_path_str(ccx.tcx, local_def(it.id)));
707 let _indenter = indenter();
710 ast::ItemStatic(_, _, ref e) |
711 ast::ItemConst(_, ref e) => check_const(ccx, it.span, &**e, it.id),
712 ast::ItemEnum(ref enum_definition, _) => {
713 check_enum_variants(ccx,
715 &enum_definition.variants[],
718 ast::ItemFn(ref decl, _, _, _, ref body) => {
719 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
720 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
721 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
723 ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
724 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
726 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
728 match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
729 Some(impl_trait_ref) => {
730 check_impl_items_against_trait(ccx,
733 impl_items.as_slice());
738 for impl_item in impl_items {
740 ast::MethodImplItem(ref m) => {
741 check_method_body(ccx, &impl_pty.generics, &**m);
743 ast::TypeImplItem(_) => {
744 // Nothing to do here.
750 ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
751 check_trait_on_unimplemented(ccx, generics, it);
752 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
753 for trait_method in trait_methods {
754 match *trait_method {
755 RequiredMethod(..) => {
756 // Nothing to do, since required methods don't have
759 ProvidedMethod(ref m) => {
760 check_method_body(ccx, &trait_def.generics, &**m);
762 TypeTraitItem(_) => {
768 ast::ItemStruct(..) => {
769 check_struct(ccx, it.id, it.span);
771 ast::ItemTy(ref t, ref generics) => {
772 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
773 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
775 ast::ItemForeignMod(ref m) => {
776 if m.abi == abi::RustIntrinsic {
777 for item in &m.items {
778 check_intrinsic_type(ccx, &**item);
781 for item in &m.items {
782 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
783 if !pty.generics.types.is_empty() {
784 span_err!(ccx.tcx.sess, item.span, E0044,
785 "foreign items may not have type parameters");
788 if let ast::ForeignItemFn(ref fn_decl, _) = item.node {
789 if fn_decl.variadic && m.abi != abi::C {
790 span_err!(ccx.tcx.sess, item.span, E0045,
791 "variadic function must have C calling convention");
797 _ => {/* nothing to do */ }
801 fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
802 generics: &ast::Generics,
804 if let Some(ref attr) = item.attrs.iter().find(|&: a| {
805 a.check_name("rustc_on_unimplemented")
807 if let Some(ref istring) = attr.value_str() {
808 let parser = Parser::new(istring.get());
809 let types = generics.ty_params.as_slice();
810 for token in parser {
812 Piece::String(_) => (), // Normal string, no need to check it
813 Piece::NextArgument(a) => match a.position {
814 // `{Self}` is allowed
815 Position::ArgumentNamed(s) if s == "Self" => (),
816 // So is `{A}` if A is a type parameter
817 Position::ArgumentNamed(s) => match types.iter().find(|t| {
818 t.ident.as_str() == s
822 span_err!(ccx.tcx.sess, attr.span, E0230,
823 "there is no type parameter \
825 s, item.ident.as_str());
828 // `{:1}` and `{}` are not to be used
829 Position::ArgumentIs(_) | Position::ArgumentNext => {
830 span_err!(ccx.tcx.sess, attr.span, E0231,
831 "only named substitution \
832 parameters are allowed");
838 span_err!(ccx.tcx.sess, attr.span, E0232,
839 "this attribute must have a value, \
840 eg `#[rustc_on_unimplemented = \"foo\"]`")
845 /// Type checks a method body.
849 /// * `item_generics`: generics defined on the impl/trait that contains
851 /// * `self_bound`: bound for the `Self` type parameter, if any
852 /// * `method`: the method definition
853 fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
854 item_generics: &ty::Generics<'tcx>,
855 method: &'tcx ast::Method) {
856 debug!("check_method_body(item_generics={}, method.id={})",
857 item_generics.repr(ccx.tcx),
859 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
861 let fty = ty::node_id_to_type(ccx.tcx, method.id);
862 debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
865 &*method.pe_fn_decl(),
872 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
874 impl_trait_ref: &ty::TraitRef<'tcx>,
875 impl_items: &[ast::ImplItem]) {
876 // Locate trait methods
878 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
880 // Check existing impl methods to see if they are both present in trait
881 // and compatible with trait signature
882 for impl_item in impl_items {
884 ast::MethodImplItem(ref impl_method) => {
885 let impl_method_def_id = local_def(impl_method.id);
886 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
889 // If this is an impl of a trait method, find the
890 // corresponding method definition in the trait.
891 let opt_trait_method_ty =
893 .find(|ti| ti.name() == impl_item_ty.name());
894 match opt_trait_method_ty {
895 Some(trait_method_ty) => {
896 match (trait_method_ty, &impl_item_ty) {
897 (&ty::MethodTraitItem(ref trait_method_ty),
898 &ty::MethodTraitItem(ref impl_method_ty)) => {
899 compare_impl_method(ccx.tcx,
902 impl_method.pe_body().id,
907 // This is span_bug as it should have already been
908 // caught in resolve.
911 format!("item `{}` is of a different kind from its trait `{}`",
912 token::get_name(impl_item_ty.name()),
913 impl_trait_ref.repr(tcx)).as_slice());
918 // This is span_bug as it should have already been
919 // caught in resolve.
922 format!("method `{}` is not a member of trait `{}`",
923 token::get_name(impl_item_ty.name()),
924 impl_trait_ref.repr(tcx)).as_slice());
928 ast::TypeImplItem(ref typedef) => {
929 let typedef_def_id = local_def(typedef.id);
930 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
933 // If this is an impl of an associated type, find the
934 // corresponding type definition in the trait.
935 let opt_associated_type =
937 .find(|ti| ti.name() == typedef_ty.name());
938 match opt_associated_type {
939 Some(associated_type) => {
940 match (associated_type, &typedef_ty) {
941 (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
943 // This is `span_bug` as it should have
944 // already been caught in resolve.
947 format!("item `{}` is of a different kind from its trait `{}`",
948 token::get_name(typedef_ty.name()),
949 impl_trait_ref.repr(tcx)).as_slice());
954 // This is `span_bug` as it should have already been
955 // caught in resolve.
959 "associated type `{}` is not a member of \
961 token::get_name(typedef_ty.name()),
962 impl_trait_ref.repr(tcx)).as_slice());
969 // Check for missing items from trait
970 let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
971 let mut missing_methods = Vec::new();
972 for trait_item in &*trait_items {
974 ty::MethodTraitItem(ref trait_method) => {
976 impl_items.iter().any(|ii| {
978 ast::MethodImplItem(ref m) => {
979 m.pe_ident().name == trait_method.name
981 ast::TypeImplItem(_) => false,
985 provided_methods.iter().any(|m| m.name == trait_method.name);
986 if !is_implemented && !is_provided {
987 missing_methods.push(format!("`{}`", token::get_name(trait_method.name)));
990 ty::TypeTraitItem(ref associated_type) => {
991 let is_implemented = impl_items.iter().any(|ii| {
993 ast::TypeImplItem(ref typedef) => {
994 typedef.ident.name == associated_type.name
996 ast::MethodImplItem(_) => false,
1000 missing_methods.push(format!("`{}`", token::get_name(associated_type.name)));
1006 if !missing_methods.is_empty() {
1007 span_err!(tcx.sess, impl_span, E0046,
1008 "not all trait items implemented, missing: {}",
1009 missing_methods.connect(", "));
1013 fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1020 let tstr = fcx.infcx().ty_to_string(t_1);
1021 fcx.type_error_message(span, |actual| {
1022 format!("cast to unsized type: `{}` as `{}`", actual, tstr)
1025 ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
1026 let mtstr = match mt {
1027 ast::MutMutable => "mut ",
1028 ast::MutImmutable => ""
1030 if ty::type_is_trait(t_1) {
1031 span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr);
1033 span_help!(fcx.tcx().sess, span,
1034 "consider using an implicit coercion to `&{}{}` instead",
1038 ty::ty_uniq(..) => {
1039 span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr);
1042 span_help!(fcx.tcx().sess, e_span,
1043 "consider using a box or reference as appropriate");
1046 fcx.write_error(id);
1050 fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1055 fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1059 fcx.type_error_message(span, |actual| {
1060 format!("illegal cast; cast through an \
1061 integer first: `{}` as `{}`",
1063 fcx.infcx().ty_to_string(t_1))
1067 let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
1068 let t_e_is_scalar = ty::type_is_scalar(t_e);
1069 let t_e_is_integral = ty::type_is_integral(t_e);
1070 let t_e_is_float = ty::type_is_floating_point(t_e);
1071 let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
1073 let t_1_is_scalar = ty::type_is_scalar(t_1);
1074 let t_1_is_char = ty::type_is_char(t_1);
1075 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1076 let t_1_is_float = ty::type_is_floating_point(t_1);
1078 // casts to scalars other than `char` and `bare fn` are trivial
1079 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1081 if t_e_is_bare_fn_item && t_1_is_bare_fn {
1082 demand::coerce(fcx, e.span, t_1, &*e);
1083 } else if t_1_is_char {
1084 let t_e = fcx.infcx().shallow_resolve(t_e);
1085 if t_e.sty != ty::ty_uint(ast::TyU8) {
1086 fcx.type_error_message(span, |actual| {
1087 format!("only `u8` can be cast as \
1088 `char`, not `{}`", actual)
1091 } else if t_1.sty == ty::ty_bool {
1092 span_err!(fcx.tcx().sess, span, E0054,
1093 "cannot cast as `bool`, compare with zero instead");
1094 } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
1095 t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
1096 // Casts to float must go through an integer or boolean
1097 cast_through_integer_err(fcx, span, t_1, t_e)
1098 } else if t_e_is_c_enum && t_1_is_trivial {
1099 if ty::type_is_unsafe_ptr(t_1) {
1100 // ... and likewise with C enum -> *T
1101 cast_through_integer_err(fcx, span, t_1, t_e)
1103 // casts from C-like enums are allowed
1104 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1105 fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
1106 t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
1108 ty::ty_vec(_, Some(_)) => {}
1111 if ty::type_needs_infer(t2) {
1112 // This prevents this special case from going off when casting
1113 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1118 let el = ty::sequence_element_type(fcx.tcx(), t1);
1119 infer::mk_eqty(fcx.infcx(),
1126 // Due to the limitations of LLVM global constants,
1127 // region pointers end up pointing at copies of
1128 // vector elements instead of the original values.
1129 // To allow unsafe pointers to work correctly, we
1130 // need to special-case obtaining an unsafe pointer
1131 // from a region pointer to a vector.
1133 /* this cast is only allowed from &[T, ..n] to *T or
1135 match (&t_e.sty, &t_1.sty) {
1136 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1137 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1138 if types_compatible(fcx, e.span, mt1, mt2) => {
1139 /* this case is allowed */
1142 demand::coerce(fcx, e.span, t_1, &*e);
1145 } else if !(t_e_is_scalar && t_1_is_trivial) {
1147 If more type combinations should be supported than are
1148 supported here, then file an enhancement issue and
1149 record the issue number in this comment.
1151 fcx.type_error_message(span, |actual| {
1152 format!("non-scalar cast: `{}` as `{}`",
1154 fcx.infcx().ty_to_string(t_1))
1159 fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
1160 cast_expr: &ast::Expr,
1163 let id = cast_expr.id;
1164 let span = cast_expr.span;
1166 // Find the type of `e`. Supply hints based on the type we are casting to,
1168 let t_1 = fcx.to_ty(t);
1169 let t_1 = structurally_resolved_type(fcx, span, t_1);
1171 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
1173 let t_e = fcx.expr_ty(e);
1175 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1176 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1178 if ty::type_is_error(t_e) {
1179 fcx.write_error(id);
1183 if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
1184 report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
1188 if ty::type_is_trait(t_1) {
1189 // This will be looked up later on.
1190 vtable::check_object_cast(fcx, cast_expr, e, t_1);
1191 fcx.write_ty(id, t_1);
1195 let t_1 = structurally_resolved_type(fcx, span, t_1);
1196 let t_e = structurally_resolved_type(fcx, span, t_e);
1198 check_cast_inner(fcx, span, t_1, t_e, e);
1199 fcx.write_ty(id, t_1);
1202 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1203 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1205 fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
1206 ty::lookup_item_type(self.tcx(), id)
1209 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
1210 ty::lookup_trait_def(self.tcx(), id)
1213 fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
1214 Some(&self.inh.param_env.free_substs)
1217 fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
1218 self.infcx().next_ty_var()
1221 fn projected_ty_from_poly_trait_ref(&self,
1223 poly_trait_ref: ty::PolyTraitRef<'tcx>,
1224 item_name: ast::Name)
1227 let (trait_ref, _) =
1228 self.infcx().replace_late_bound_regions_with_fresh_var(
1230 infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
1233 self.normalize_associated_type(span, trait_ref, item_name)
1236 fn projected_ty(&self,
1238 trait_ref: Rc<ty::TraitRef<'tcx>>,
1239 item_name: ast::Name)
1242 self.normalize_associated_type(span, trait_ref, item_name)
1246 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1247 fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
1249 pub fn infcx(&self) -> &infer::InferCtxt<'a,'tcx> {
1253 pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> {
1257 pub fn sess(&self) -> &Session {
1261 pub fn err_count_since_creation(&self) -> uint {
1262 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1265 /// Resolves type variables in `ty` if possible. Unlike the infcx
1266 /// version, this version will also select obligations if it seems
1267 /// useful, in an effort to get more type information.
1268 fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1269 // No ty::infer()? Nothing needs doing.
1270 if !ty::type_has_ty_infer(ty) {
1274 // If `ty` is a type variable, see whether we already know what it is.
1275 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1276 if !ty::type_has_ty_infer(ty) {
1280 // If not, try resolving any new fcx obligations that have cropped up.
1281 vtable::select_new_fcx_obligations(self);
1282 ty = self.infcx().resolve_type_vars_if_possible(&ty);
1283 if !ty::type_has_ty_infer(ty) {
1287 // If not, try resolving *all* pending obligations as much as
1288 // possible. This can help substantially when there are
1289 // indirect dependencies that don't seem worth tracking
1291 vtable::select_fcx_obligations_where_possible(self);
1292 self.infcx().resolve_type_vars_if_possible(&ty)
1295 /// Resolves all type variables in `t` and then, if any were left
1296 /// unresolved, substitutes an error type. This is used after the
1297 /// main checking when doing a second pass before writeback. The
1298 /// justification is that writeback will produce an error for
1299 /// these unconstrained type variables.
1300 fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
1301 let t = self.infcx().resolve_type_vars_if_possible(t);
1302 if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
1305 fn record_deferred_call_resolution(&self,
1306 closure_def_id: ast::DefId,
1307 r: DeferredCallResolutionHandler<'tcx>) {
1308 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1309 let mut vec = match deferred_call_resolutions.entry(closure_def_id) {
1310 Occupied(entry) => entry.into_mut(),
1311 Vacant(entry) => entry.insert(Vec::new()),
1316 fn remove_deferred_call_resolutions(&self,
1317 closure_def_id: ast::DefId)
1318 -> Vec<DeferredCallResolutionHandler<'tcx>>
1320 let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut();
1321 deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
1324 pub fn tag(&self) -> String {
1325 format!("{:?}", self as *const FnCtxt)
1328 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
1329 match self.inh.locals.borrow().get(&nid) {
1332 self.tcx().sess.span_bug(
1334 &format!("no type for local variable {}",
1340 /// Apply "fallbacks" to some types
1341 /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1342 pub fn default_type_parameters(&self) {
1343 use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
1344 for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
1345 let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1346 if self.infcx().type_var_diverges(resolved) {
1347 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1349 match self.infcx().type_is_unconstrained_numeric(resolved) {
1350 UnconstrainedInt => {
1351 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1353 UnconstrainedFloat => {
1354 demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1363 pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
1364 debug!("write_ty({}, {}) in fcx {}",
1365 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1366 self.inh.node_types.borrow_mut().insert(node_id, ty);
1369 pub fn write_object_cast(&self,
1371 trait_ref: ty::PolyTraitRef<'tcx>) {
1372 debug!("write_object_cast key={} trait_ref={}",
1373 key, trait_ref.repr(self.tcx()));
1374 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1377 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
1378 if !substs.substs.is_noop() {
1379 debug!("write_substs({}, {}) in fcx {}",
1381 substs.repr(self.tcx()),
1384 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1388 pub fn write_autoderef_adjustment(&self,
1389 node_id: ast::NodeId,
1392 if derefs == 0 { return; }
1393 self.write_adjustment(
1396 ty::AdjustDerefRef(ty::AutoDerefRef {
1402 pub fn write_adjustment(&self,
1403 node_id: ast::NodeId,
1405 adj: ty::AutoAdjustment<'tcx>) {
1406 debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
1408 if adj.is_identity() {
1412 // Careful: adjustments can imply trait obligations if we are
1413 // casting from a concrete type to an object type. I think
1414 // it'd probably be nicer to move the logic that creates the
1415 // obligation into the code that creates the adjustment, but
1416 // that's a bit awkward, so instead we go digging and pull the
1417 // obligation out here.
1418 self.register_adjustment_obligations(span, &adj);
1419 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1422 /// Basically whenever we are converting from a type scheme into
1423 /// the fn body space, we always want to normalize associated
1424 /// types as well. This function combines the two.
1425 fn instantiate_type_scheme<T>(&self,
1427 substs: &Substs<'tcx>,
1430 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1432 let value = value.subst(self.tcx(), substs);
1433 let result = self.normalize_associated_types_in(span, &value);
1434 debug!("instantiate_type_scheme(value={}, substs={}) = {}",
1435 value.repr(self.tcx()),
1436 substs.repr(self.tcx()),
1437 result.repr(self.tcx()));
1441 /// As `instantiate_type_scheme`, but for the bounds found in a
1442 /// generic type scheme.
1443 fn instantiate_bounds(&self,
1445 substs: &Substs<'tcx>,
1446 generics: &ty::Generics<'tcx>)
1447 -> ty::GenericBounds<'tcx>
1450 predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
1455 fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
1456 where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
1458 self.inh.normalize_associated_types_in(self, span, self.body_id, value)
1461 fn normalize_associated_type(&self,
1463 trait_ref: Rc<ty::TraitRef<'tcx>>,
1464 item_name: ast::Name)
1467 let cause = traits::ObligationCause::new(span,
1469 traits::ObligationCauseCode::MiscObligation);
1470 self.inh.fulfillment_cx
1472 .normalize_projection_type(self.infcx(),
1475 trait_ref: trait_ref,
1476 item_name: item_name,
1481 fn register_adjustment_obligations(&self,
1483 adj: &ty::AutoAdjustment<'tcx>) {
1485 ty::AdjustReifyFnPointer(..) => {
1487 ty::AdjustDerefRef(ref d_r) => {
1490 self.register_autoref_obligations(span, a_r);
1498 fn register_autoref_obligations(&self,
1500 autoref: &ty::AutoRef<'tcx>) {
1502 ty::AutoUnsize(ref unsize) => {
1503 self.register_unsize_obligations(span, unsize);
1505 ty::AutoPtr(_, _, None) |
1506 ty::AutoUnsafe(_, None) => {
1508 ty::AutoPtr(_, _, Some(ref a_r)) |
1509 ty::AutoUnsafe(_, Some(ref a_r)) => {
1510 self.register_autoref_obligations(span, &**a_r)
1512 ty::AutoUnsizeUniq(ref unsize) => {
1513 self.register_unsize_obligations(span, unsize);
1518 fn register_unsize_obligations(&self,
1520 unsize: &ty::UnsizeKind<'tcx>) {
1521 debug!("register_unsize_obligations: unsize={:?}", unsize);
1524 ty::UnsizeLength(..) => {}
1525 ty::UnsizeStruct(ref u, _) => {
1526 self.register_unsize_obligations(span, &**u)
1528 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1529 vtable::check_object_safety(self.tcx(), ty_trait, span);
1531 // If the type is `Foo+'a`, ensures that the type
1532 // being cast to `Foo+'a` implements `Foo`:
1533 vtable::register_object_cast_obligations(self,
1538 // If the type is `Foo+'a`, ensures that the type
1539 // being cast to `Foo+'a` outlives `'a`:
1540 let cause = traits::ObligationCause { span: span,
1541 body_id: self.body_id,
1542 code: traits::ObjectCastObligation(self_ty) };
1543 self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause);
1548 /// Returns the type of `def_id` with all generics replaced by by fresh type/region variables.
1549 /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
1550 /// Registers any trait obligations specified on `def_id` at the same time.
1552 /// Note that function is only intended to be used with types (notably, not fns). This is
1553 /// because it doesn't do any instantiation of late-bound regions.
1554 pub fn instantiate_type(&self,
1557 -> TypeAndSubsts<'tcx>
1560 ty::lookup_item_type(self.tcx(), def_id);
1562 self.infcx().fresh_substs_for_generics(
1564 &type_scheme.generics);
1566 self.instantiate_bounds(span, &substs, &type_scheme.generics);
1567 self.add_obligations_for_parameters(
1568 traits::ObligationCause::new(
1571 traits::ItemObligation(def_id)),
1574 self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
1582 /// Returns the type that this AST path refers to. If the path has no type
1583 /// parameters and the corresponding type has type parameters, fresh type
1584 /// and/or region variables are substituted.
1586 /// This is used when checking the constructor in struct literals.
1587 fn instantiate_struct_literal_ty(&self,
1590 -> TypeAndSubsts<'tcx>
1592 let tcx = self.tcx();
1594 let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
1597 generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1599 let needs_defaults =
1601 path.segments.iter().all(|s| s.parameters.is_empty());
1603 let substs = if needs_defaults {
1605 self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1607 self.infcx().region_vars_for_defs(path.span,
1608 generics.regions.get_slice(TypeSpace));
1609 Substs::new_type(tps, rps)
1611 astconv::ast_path_substs_for_ty(self, self, &generics, path)
1614 let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1616 TypeAndSubsts { substs: substs, ty: ty }
1619 pub fn write_nil(&self, node_id: ast::NodeId) {
1620 self.write_ty(node_id, ty::mk_nil(self.tcx()));
1622 pub fn write_error(&self, node_id: ast::NodeId) {
1623 self.write_ty(node_id, self.tcx().types.err);
1626 pub fn require_type_meets(&self,
1629 code: traits::ObligationCauseCode<'tcx>,
1630 bound: ty::BuiltinBound)
1632 self.register_builtin_bound(
1635 traits::ObligationCause::new(span, self.body_id, code));
1638 pub fn require_type_is_sized(&self,
1641 code: traits::ObligationCauseCode<'tcx>)
1643 self.require_type_meets(ty, span, code, ty::BoundSized);
1646 pub fn require_expr_have_sized_type(&self,
1648 code: traits::ObligationCauseCode<'tcx>)
1650 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1653 pub fn type_is_known_to_be_sized(&self,
1658 traits::type_known_to_meet_builtin_bound(self.infcx(),
1665 pub fn register_builtin_bound(&self,
1667 builtin_bound: ty::BuiltinBound,
1668 cause: traits::ObligationCause<'tcx>)
1670 self.inh.fulfillment_cx.borrow_mut()
1671 .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
1674 pub fn register_predicate(&self,
1675 obligation: traits::PredicateObligation<'tcx>)
1677 debug!("register_predicate({})",
1678 obligation.repr(self.tcx()));
1679 self.inh.fulfillment_cx
1681 .register_predicate_obligation(self.infcx(), obligation);
1684 pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
1685 let t = ast_ty_to_ty(self, self, ast_t);
1687 let mut bounds_checker = wf::BoundsChecker::new(self,
1689 CodeExtent::from_node_id(self.body_id),
1691 bounds_checker.check_ty(t);
1696 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1697 pat.repr(self.tcx())
1700 pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
1701 match self.inh.node_types.borrow().get(&ex.id) {
1704 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
1710 /// Apply `adjustment` to the type of `expr`
1711 pub fn adjust_expr_ty(&self,
1713 adjustment: Option<&ty::AutoAdjustment<'tcx>>)
1716 let raw_ty = self.expr_ty(expr);
1717 let raw_ty = self.infcx().shallow_resolve(raw_ty);
1718 let resolve_ty = |&: ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
1719 ty::adjust_ty(self.tcx(),
1724 |method_call| self.inh.method_map.borrow()
1726 .map(|method| resolve_ty(method.ty)))
1729 pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
1730 match self.inh.node_types.borrow().get(&id) {
1732 None if self.err_count_since_creation() != 0 => self.tcx().types.err,
1734 self.tcx().sess.bug(
1735 &format!("no type for node {}: {} in fcx {}",
1736 id, self.tcx().map.node_to_string(id),
1742 pub fn item_substs(&self) -> Ref<NodeMap<ty::ItemSubsts<'tcx>>> {
1743 self.inh.item_substs.borrow()
1746 pub fn opt_node_ty_substs<F>(&self,
1749 F: FnOnce(&ty::ItemSubsts<'tcx>),
1751 match self.inh.item_substs.borrow().get(&id) {
1757 pub fn mk_subty(&self,
1758 a_is_expected: bool,
1759 origin: infer::TypeOrigin,
1762 -> Result<(), ty::type_err<'tcx>> {
1763 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1766 pub fn mk_eqty(&self,
1767 a_is_expected: bool,
1768 origin: infer::TypeOrigin,
1771 -> Result<(), ty::type_err<'tcx>> {
1772 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1775 pub fn mk_subr(&self,
1776 origin: infer::SubregionOrigin<'tcx>,
1779 infer::mk_subr(self.infcx(), origin, sub, sup)
1782 pub fn type_error_message<M>(&self,
1785 actual_ty: Ty<'tcx>,
1786 err: Option<&ty::type_err<'tcx>>) where
1787 M: FnOnce(String) -> String,
1789 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1792 pub fn report_mismatched_types(&self,
1796 err: &ty::type_err<'tcx>) {
1797 self.infcx().report_mismatched_types(sp, e, a, err)
1800 /// Registers an obligation for checking later, during regionck, that the type `ty` must
1801 /// outlive the region `r`.
1802 pub fn register_region_obligation(&self,
1805 cause: traits::ObligationCause<'tcx>)
1807 let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
1808 fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
1811 pub fn add_default_region_param_bounds(&self,
1812 substs: &Substs<'tcx>,
1815 for &ty in substs.types.iter() {
1816 let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
1817 let cause = traits::ObligationCause::new(expr.span, self.body_id,
1818 traits::MiscObligation);
1819 self.register_region_obligation(ty, default_bound, cause);
1823 /// Given a fully substituted set of bounds (`generic_bounds`), and the values with which each
1824 /// type/region parameter was instantiated (`substs`), creates and registers suitable
1825 /// trait/region obligations.
1827 /// For example, if there is a function:
1830 /// fn foo<'a,T:'a>(...)
1833 /// and a reference:
1839 /// Then we will create a fresh region variable `'$0` and a fresh type variable `$1` for `'a`
1840 /// and `T`. This routine will add a region obligation `$1:'$0` and register it locally.
1841 pub fn add_obligations_for_parameters(&self,
1842 cause: traits::ObligationCause<'tcx>,
1843 generic_bounds: &ty::GenericBounds<'tcx>)
1845 assert!(!generic_bounds.has_escaping_regions());
1847 debug!("add_obligations_for_parameters(generic_bounds={})",
1848 generic_bounds.repr(self.tcx()));
1850 let obligations = traits::predicates_for_generics(self.tcx(),
1854 obligations.map_move(|o| self.register_predicate(o));
1857 // Only for fields! Returns <none> for methods>
1858 // Indifferent to privacy flags
1859 pub fn lookup_field_ty(&self,
1861 class_id: ast::DefId,
1862 items: &[ty::field_ty],
1863 fieldname: ast::Name,
1864 substs: &subst::Substs<'tcx>)
1867 let o_field = items.iter().find(|f| f.name == fieldname);
1868 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1869 .map(|t| self.normalize_associated_types_in(span, &t))
1872 pub fn lookup_tup_field_ty(&self,
1874 class_id: ast::DefId,
1875 items: &[ty::field_ty],
1877 substs: &subst::Substs<'tcx>)
1880 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
1881 o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
1882 .map(|t| self.normalize_associated_types_in(span, &t))
1886 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
1887 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1888 Some(self.infcx().next_region_var(infer::MiscVariable(span)))
1891 fn anon_regions(&self, span: Span, count: uint)
1892 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
1893 Ok((0..count).map(|_| {
1894 self.infcx().next_region_var(infer::MiscVariable(span))
1899 #[derive(Copy, Debug, PartialEq, Eq)]
1900 pub enum LvaluePreference {
1905 /// Whether `autoderef` requires types to resolve.
1906 #[derive(Copy, Debug, PartialEq, Eq)]
1907 pub enum UnresolvedTypeAction {
1908 /// Produce an error and return `ty_err` whenever a type cannot
1909 /// be resolved (i.e. it is `ty_infer`).
1911 /// Go on without emitting any errors, and return the unresolved
1912 /// type. Useful for probing, e.g. in coercions.
1916 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
1917 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
1919 /// Note: this method does not modify the adjustments table. The caller is responsible for
1920 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
1921 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
1924 opt_expr: Option<&ast::Expr>,
1925 unresolved_type_action: UnresolvedTypeAction,
1926 mut lvalue_pref: LvaluePreference,
1928 -> (Ty<'tcx>, uint, Option<T>)
1929 where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
1931 debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})",
1932 base_ty.repr(fcx.tcx()),
1933 opt_expr.repr(fcx.tcx()),
1936 let mut t = base_ty;
1937 for autoderefs in 0..fcx.tcx().sess.recursion_limit.get() {
1938 let resolved_t = match unresolved_type_action {
1939 UnresolvedTypeAction::Error => {
1940 let resolved_t = structurally_resolved_type(fcx, sp, t);
1941 if ty::type_is_error(resolved_t) {
1942 return (resolved_t, autoderefs, None);
1946 UnresolvedTypeAction::Ignore => {
1947 // We can continue even when the type cannot be resolved
1948 // (i.e. it is an inference variable) because `ty::deref`
1949 // and `try_overloaded_deref` both simply return `None`
1950 // in such a case without producing spurious errors.
1951 fcx.resolve_type_vars_if_possible(t)
1955 match should_stop(resolved_t, autoderefs) {
1956 Some(x) => return (resolved_t, autoderefs, Some(x)),
1960 // Otherwise, deref if type is derefable:
1961 let mt = match ty::deref(resolved_t, false) {
1962 Some(mt) => Some(mt),
1964 let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
1966 // Super subtle: it might seem as though we should
1967 // pass `opt_expr` to `try_overloaded_deref`, so that
1968 // the (implicit) autoref of using an overloaded deref
1969 // would get added to the adjustment table. However we
1970 // do not do that, because it's kind of a
1971 // "meta-adjustment" -- instead, we just leave it
1972 // unrecorded and know that there "will be" an
1973 // autoref. regionck and other bits of the code base,
1974 // when they encounter an overloaded autoderef, have
1975 // to do some reconstructive surgery. This is a pretty
1976 // complex mess that is begging for a proper MIR.
1977 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1983 if mt.mutbl == ast::MutImmutable {
1984 lvalue_pref = NoPreference;
1987 None => return (resolved_t, autoderefs, None)
1991 // We've reached the recursion limit, error gracefully.
1992 span_err!(fcx.tcx().sess, sp, E0055,
1993 "reached the recursion limit while auto-dereferencing {}",
1994 base_ty.repr(fcx.tcx()));
1995 (fcx.tcx().types.err, 0, None)
1998 fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2000 method_call: Option<MethodCall>,
2001 base_expr: Option<&ast::Expr>,
2003 lvalue_pref: LvaluePreference)
2004 -> Option<ty::mt<'tcx>>
2006 // Try DerefMut first, if preferred.
2007 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2008 (PreferMutLvalue, Some(trait_did)) => {
2009 method::lookup_in_trait(fcx, span, base_expr,
2010 token::intern("deref_mut"), trait_did,
2016 // Otherwise, fall back to Deref.
2017 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2018 (None, Some(trait_did)) => {
2019 method::lookup_in_trait(fcx, span, base_expr,
2020 token::intern("deref"), trait_did,
2023 (method, _) => method
2026 make_overloaded_lvalue_return_type(fcx, method_call, method)
2029 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
2030 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
2031 /// type by one layer to yield `T`. It also inserts the `method-callee` into the method map.
2032 fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2033 method_call: Option<MethodCall>,
2034 method: Option<MethodCallee<'tcx>>)
2035 -> Option<ty::mt<'tcx>>
2039 let ref_ty = // invoked methods have all LB regions instantiated
2040 ty::assert_no_late_bound_regions(
2041 fcx.tcx(), &ty::ty_fn_ret(method.ty));
2043 Some(method_call) => {
2044 fcx.inh.method_map.borrow_mut().insert(method_call,
2050 ty::FnConverging(ref_ty) => {
2051 ty::deref(ref_ty, true)
2053 ty::FnDiverging => {
2054 fcx.tcx().sess.bug("index/deref traits do not define a `!` return")
2062 fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
2063 base_expr: &ast::Expr,
2065 lvalue_pref: LvaluePreference,
2068 F: FnMut(Ty<'tcx>, ty::AutoDerefRef<'tcx>) -> Option<T>,
2070 // FIXME(#18741) -- this is almost but not quite the same as the
2071 // autoderef that normal method probing does. They could likely be
2074 let (ty, autoderefs, final_mt) = autoderef(fcx,
2078 UnresolvedTypeAction::Error,
2081 let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
2082 step(adj_ty, autoderefref)
2085 if final_mt.is_some() {
2089 // After we have fully autoderef'd, if the resulting type is [T, ..n], then
2090 // do a final unsized coercion to yield [T].
2092 ty::ty_vec(element_ty, Some(n)) => {
2093 let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
2094 let autoderefref = ty::AutoDerefRef {
2095 autoderefs: autoderefs,
2096 autoref: Some(ty::AutoUnsize(ty::UnsizeLength(n)))
2098 step(adjusted_ty, autoderefref)
2106 /// To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
2107 /// `base_expr`, looking for a type which either supports builtin indexing or overloaded indexing.
2108 /// This loop implements one step in that search; the autoderef loop is implemented by
2109 /// `autoderef_for_index`.
2110 fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2111 method_call: MethodCall,
2113 base_expr: &'tcx ast::Expr,
2114 adjusted_ty: Ty<'tcx>,
2115 adjustment: ty::AutoDerefRef<'tcx>,
2116 lvalue_pref: LvaluePreference,
2118 -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
2120 let tcx = fcx.tcx();
2121 debug!("try_index_step(expr={}, base_expr.id={}, adjusted_ty={}, adjustment={:?}, index_ty={})",
2123 base_expr.repr(tcx),
2124 adjusted_ty.repr(tcx),
2126 index_ty.repr(tcx));
2128 let input_ty = fcx.infcx().next_ty_var();
2130 // First, try built-in indexing.
2131 match (ty::index(adjusted_ty), &index_ty.sty) {
2132 (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => {
2133 debug!("try_index_step: success, using built-in indexing");
2134 fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
2135 return Some((tcx.types.uint, ty));
2140 // Try `IndexMut` first, if preferred.
2141 let method = match (lvalue_pref, tcx.lang_items.index_mut_trait()) {
2142 (PreferMutLvalue, Some(trait_did)) => {
2143 method::lookup_in_trait_adjusted(fcx,
2146 token::intern("index_mut"),
2150 Some(vec![input_ty]))
2155 // Otherwise, fall back to `Index`.
2156 let method = match (method, tcx.lang_items.index_trait()) {
2157 (None, Some(trait_did)) => {
2158 method::lookup_in_trait_adjusted(fcx,
2161 token::intern("index"),
2165 Some(vec![input_ty]))
2167 (method, _) => method,
2170 // If some lookup succeeds, write callee into table and extract index/element
2171 // type from the method signature.
2172 // If some lookup succeeded, install method in table
2173 method.and_then(|method| {
2174 debug!("try_index_step: success, using overloaded indexing");
2175 make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method)).
2176 map(|ret| (input_ty, ret.ty))
2180 fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2182 method_fn_ty: Ty<'tcx>,
2183 callee_expr: &'tcx ast::Expr,
2184 args_no_rcvr: &'tcx [P<ast::Expr>],
2185 autoref_args: AutorefArgs,
2186 tuple_arguments: TupleArgumentsFlag,
2187 expected: Expectation<'tcx>)
2188 -> ty::FnOutput<'tcx> {
2189 if ty::type_is_error(method_fn_ty) {
2190 let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
2192 let err_inputs = match tuple_arguments {
2193 DontTupleArguments => err_inputs,
2194 TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
2197 check_argument_types(fcx,
2205 ty::FnConverging(fcx.tcx().types.err)
2207 match method_fn_ty.sty {
2208 ty::ty_bare_fn(_, ref fty) => {
2209 // HACK(eddyb) ignore self in the definition (see above).
2210 let expected_arg_tys = expected_types_for_fn_args(fcx,
2214 &fty.sig.0.inputs[1..]);
2215 check_argument_types(fcx,
2217 &fty.sig.0.inputs[1..],
2218 &expected_arg_tys[],
2226 fcx.tcx().sess.span_bug(callee_expr.span,
2227 "method without bare fn type");
2233 /// Generic function that factors out common logic from function calls, method calls and overloaded
2235 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2237 fn_inputs: &[Ty<'tcx>],
2238 expected_arg_tys: &[Ty<'tcx>],
2239 args: &'tcx [P<ast::Expr>],
2240 autoref_args: AutorefArgs,
2242 tuple_arguments: TupleArgumentsFlag) {
2243 let tcx = fcx.ccx.tcx;
2245 // Grab the argument types, supplying fresh type variables
2246 // if the wrong number of arguments were supplied
2247 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2253 let mut expected_arg_tys = expected_arg_tys;
2254 let expected_arg_count = fn_inputs.len();
2255 let formal_tys = if tuple_arguments == TupleArguments {
2256 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2257 match tuple_type.sty {
2258 ty::ty_tup(ref arg_types) => {
2259 if arg_types.len() != args.len() {
2260 span_err!(tcx.sess, sp, E0057,
2261 "this function takes {} parameter{} but {} parameter{} supplied",
2263 if arg_types.len() == 1 {""} else {"s"},
2265 if args.len() == 1 {" was"} else {"s were"});
2266 expected_arg_tys = &[][];
2267 err_args(fcx.tcx(), args.len())
2269 expected_arg_tys = match expected_arg_tys.get(0) {
2270 Some(&ty) => match ty.sty {
2271 ty::ty_tup(ref tys) => &**tys,
2276 (*arg_types).clone()
2280 span_err!(tcx.sess, sp, E0059,
2281 "cannot use call notation; the first type parameter \
2282 for the function trait is neither a tuple nor unit");
2283 expected_arg_tys = &[][];
2284 err_args(fcx.tcx(), args.len())
2287 } else if expected_arg_count == supplied_arg_count {
2289 } else if variadic {
2290 if supplied_arg_count >= expected_arg_count {
2293 span_err!(tcx.sess, sp, E0060,
2294 "this function takes at least {} parameter{} \
2295 but {} parameter{} supplied",
2297 if expected_arg_count == 1 {""} else {"s"},
2299 if supplied_arg_count == 1 {" was"} else {"s were"});
2300 expected_arg_tys = &[][];
2301 err_args(fcx.tcx(), supplied_arg_count)
2304 span_err!(tcx.sess, sp, E0061,
2305 "this function takes {} parameter{} but {} parameter{} supplied",
2307 if expected_arg_count == 1 {""} else {"s"},
2309 if supplied_arg_count == 1 {" was"} else {"s were"});
2310 expected_arg_tys = &[][];
2311 err_args(fcx.tcx(), supplied_arg_count)
2314 debug!("check_argument_types: formal_tys={:?}",
2315 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2317 // Check the arguments.
2318 // We do this in a pretty awful way: first we typecheck any arguments
2319 // that are not anonymous functions, then we typecheck the anonymous
2320 // functions. This is so that we have more information about the types
2321 // of arguments when we typecheck the functions. This isn't really the
2322 // right way to do this.
2323 let xs = [false, true];
2324 for check_blocks in &xs {
2325 let check_blocks = *check_blocks;
2326 debug!("check_blocks={}", check_blocks);
2328 // More awful hacks: before we check argument types, try to do
2329 // an "opportunistic" vtable resolution of any trait bounds on
2330 // the call. This helps coercions.
2332 vtable::select_new_fcx_obligations(fcx);
2335 // For variadic functions, we don't have a declared type for all of
2336 // the arguments hence we only do our usual type checking with
2337 // the arguments who's types we do know.
2338 let t = if variadic {
2340 } else if tuple_arguments == TupleArguments {
2345 for (i, arg) in args.iter().take(t).enumerate() {
2346 let is_block = match arg.node {
2347 ast::ExprClosure(..) => true,
2351 if is_block == check_blocks {
2352 debug!("checking the argument");
2353 let mut formal_ty = formal_tys[i];
2355 match autoref_args {
2356 AutorefArgs::Yes => {
2357 match formal_ty.sty {
2358 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2361 // So we hit this case when one implements the
2362 // operator traits but leaves an argument as
2363 // just T instead of &T. We'll catch it in the
2364 // mismatch impl/trait method phase no need to
2367 formal_ty = tcx.types.err;
2371 AutorefArgs::No => {}
2374 // The special-cased logic below has three functions:
2375 // 1. Provide as good of an expected type as possible.
2376 let expected = expected_arg_tys.get(i).map(|&ty| {
2377 Expectation::rvalue_hint(ty)
2380 check_expr_with_unifier(fcx, &**arg,
2381 expected.unwrap_or(ExpectHasType(formal_ty)),
2383 // 2. Coerce to the most detailed type that could be coerced
2384 // to, which is `expected_ty` if `rvalue_hint` returns an
2385 // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2386 let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
2387 demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
2389 // 3. Relate the expected type and the formal one,
2390 // if the expected type was used for the coercion.
2391 coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
2397 // We also need to make sure we at least write the ty of the other
2398 // arguments which we skipped above.
2400 for arg in args.iter().skip(expected_arg_count) {
2401 check_expr(fcx, &**arg);
2403 // There are a few types which get autopromoted when passed via varargs
2404 // in C but we just error out instead and require explicit casts.
2405 let arg_ty = structurally_resolved_type(fcx, arg.span,
2406 fcx.expr_ty(&**arg));
2408 ty::ty_float(ast::TyF32) => {
2409 fcx.type_error_message(arg.span,
2411 format!("can't pass an {} to variadic \
2412 function, cast to c_double", t)
2415 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2416 fcx.type_error_message(arg.span, |t| {
2417 format!("can't pass {} to variadic \
2418 function, cast to c_int",
2422 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2423 fcx.type_error_message(arg.span, |t| {
2424 format!("can't pass {} to variadic \
2425 function, cast to c_uint",
2435 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
2436 fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
2437 (0..len).map(|_| tcx.types.err).collect()
2440 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2441 call_expr: &ast::Expr,
2442 output: ty::FnOutput<'tcx>) {
2443 fcx.write_ty(call_expr.id, match output {
2444 ty::FnConverging(output_ty) => output_ty,
2445 ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
2449 // AST fragment checking
2450 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2452 expected: Expectation<'tcx>)
2455 let tcx = fcx.ccx.tcx;
2458 ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2459 ast::LitBinary(..) => {
2461 tcx.mk_region(ty::ReStatic),
2462 ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2464 ast::LitByte(_) => tcx.types.u8,
2465 ast::LitChar(_) => tcx.types.char,
2466 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
2467 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
2468 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2469 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2471 ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
2472 ty::ty_char => Some(tcx.types.u8),
2473 ty::ty_ptr(..) => Some(tcx.types.uint),
2474 ty::ty_bare_fn(..) => Some(tcx.types.uint),
2478 opt_ty.unwrap_or_else(
2479 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2481 ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
2482 ast::LitFloatUnsuffixed(_) => {
2483 let opt_ty = expected.to_option(fcx).and_then(|ty| {
2485 ty::ty_float(_) => Some(ty),
2489 opt_ty.unwrap_or_else(
2490 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2492 ast::LitBool(_) => tcx.types.bool
2496 pub fn valid_range_bounds(ccx: &CrateCtxt,
2500 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2501 Some(val) => Some(val <= 0),
2506 pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2507 expr: &'tcx ast::Expr,
2508 expected: Ty<'tcx>) {
2509 check_expr_with_unifier(
2510 fcx, expr, ExpectHasType(expected), NoPreference,
2511 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2514 fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2515 expr: &'tcx ast::Expr,
2516 expected: Ty<'tcx>) {
2517 check_expr_with_unifier(
2518 fcx, expr, ExpectHasType(expected), NoPreference,
2519 || demand::coerce(fcx, expr.span, expected, expr));
2522 fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr,
2523 expected: Ty<'tcx>) {
2524 check_expr_with_unifier(
2525 fcx, expr, ExpectHasType(expected), NoPreference,
2529 fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2530 expr: &'tcx ast::Expr,
2531 expected: Expectation<'tcx>) {
2532 check_expr_with_unifier(
2533 fcx, expr, expected, NoPreference,
2537 fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2538 expr: &'tcx ast::Expr,
2539 expected: Expectation<'tcx>,
2540 lvalue_pref: LvaluePreference)
2542 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2545 fn check_expr<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr) {
2546 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2549 fn check_expr_with_lvalue_pref<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr,
2550 lvalue_pref: LvaluePreference) {
2551 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2554 // determine the `self` type, using fresh variables for all variables
2555 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2556 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2558 pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2559 span: Span, // (potential) receiver for this impl
2561 -> TypeAndSubsts<'tcx> {
2562 let tcx = fcx.tcx();
2564 let ity = ty::lookup_item_type(tcx, did);
2565 let (n_tps, rps, raw_ty) =
2566 (ity.generics.types.len(subst::TypeSpace),
2567 ity.generics.regions.get_slice(subst::TypeSpace),
2570 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2571 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2572 let substs = subst::Substs::new_type(tps, rps);
2573 let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
2575 TypeAndSubsts { substs: substs, ty: substd_ty }
2578 // Controls whether the arguments are automatically referenced. This is useful
2579 // for overloaded binary and unary operators.
2580 #[derive(Copy, PartialEq)]
2581 pub enum AutorefArgs {
2586 /// Controls whether the arguments are tupled. This is used for the call
2589 /// Tupling means that all call-side arguments are packed into a tuple and
2590 /// passed as a single parameter. For example, if tupling is enabled, this
2593 /// fn f(x: (int, int))
2595 /// Can be called as:
2602 #[derive(Clone, Eq, PartialEq)]
2603 enum TupleArgumentsFlag {
2608 /// Unifies the return type with the expected type early, for more coercions
2609 /// and forward type information on the argument expressions.
2610 fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2612 expected_ret: Expectation<'tcx>,
2613 formal_ret: ty::FnOutput<'tcx>,
2614 formal_args: &[Ty<'tcx>])
2616 let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
2617 if let ty::FnConverging(formal_ret_ty) = formal_ret {
2618 fcx.infcx().commit_regions_if_ok(|| {
2619 // Attempt to apply a subtyping relationship between the formal
2620 // return type (likely containing type variables if the function
2621 // is polymorphic) and the expected return type.
2622 // No argument expectations are produced if unification fails.
2623 let origin = infer::Misc(call_span);
2624 let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
2625 // FIXME(#15760) can't use try! here, FromError doesn't default
2626 // to identity so the resulting type is not constrained.
2627 if let Err(e) = ures {
2631 // Record all the argument types, with the substitutions
2632 // produced from the above subtyping unification.
2633 Ok(formal_args.iter().map(|ty| {
2634 fcx.infcx().resolve_type_vars_if_possible(ty)
2640 }).unwrap_or(vec![]);
2641 debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
2642 formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
2643 expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
2648 /// If an expression has any sub-expressions that result in a type error,
2649 /// inspecting that expression's type with `ty::type_is_error` will return
2650 /// true. Likewise, if an expression is known to diverge, inspecting its
2651 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2652 /// strict, _|_ can appear in the type of an expression that does not,
2653 /// itself, diverge: for example, fn() -> _|_.)
2654 /// Note that inspecting a type's structure *directly* may expose the fact
2655 /// that there are actually multiple representations for `ty_err`, so avoid
2656 /// that when err needs to be handled differently.
2657 fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2658 expr: &'tcx ast::Expr,
2659 expected: Expectation<'tcx>,
2660 lvalue_pref: LvaluePreference,
2664 debug!(">> typechecking: expr={} expected={}",
2665 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2667 // Checks a method call.
2668 fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2669 expr: &'tcx ast::Expr,
2670 method_name: ast::SpannedIdent,
2671 args: &'tcx [P<ast::Expr>],
2673 expected: Expectation<'tcx>,
2674 lvalue_pref: LvaluePreference) {
2675 let rcvr = &*args[0];
2676 check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
2678 // no need to check for bot/err -- callee does that
2679 let expr_t = structurally_resolved_type(fcx,
2681 fcx.expr_ty(&*rcvr));
2683 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2684 let fn_ty = match method::lookup(fcx,
2686 method_name.node.name,
2692 let method_ty = method.ty;
2693 let method_call = MethodCall::expr(expr.id);
2694 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2698 method::report_error(fcx, method_name.span, expr_t,
2699 method_name.node.name, rcvr, error);
2700 fcx.write_error(expr.id);
2705 // Call the generic checker.
2706 let ret_ty = check_method_argument_types(fcx,
2715 write_call(fcx, expr, ret_ty);
2718 // A generic function for checking the then and else in an if
2720 fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2721 cond_expr: &'tcx ast::Expr,
2722 then_blk: &'tcx ast::Block,
2723 opt_else_expr: Option<&'tcx ast::Expr>,
2726 expected: Expectation<'tcx>) {
2727 check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
2729 let expected = expected.adjust_for_branches(fcx);
2730 check_block_with_expected(fcx, then_blk, expected);
2731 let then_ty = fcx.node_ty(then_blk.id);
2733 let branches_ty = match opt_else_expr {
2734 Some(ref else_expr) => {
2735 check_expr_with_expectation(fcx, &**else_expr, expected);
2736 let else_ty = fcx.expr_ty(&**else_expr);
2737 infer::common_supertype(fcx.infcx(),
2738 infer::IfExpression(sp),
2744 infer::common_supertype(fcx.infcx(),
2745 infer::IfExpressionWithNoElse(sp),
2748 ty::mk_nil(fcx.tcx()))
2752 let cond_ty = fcx.expr_ty(cond_expr);
2753 let if_ty = if ty::type_is_error(cond_ty) {
2759 fcx.write_ty(id, if_ty);
2762 fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
2763 op_ex: &'tcx ast::Expr,
2766 trait_did: Option<ast::DefId>,
2768 rhs: Option<&'tcx P<ast::Expr>>,
2770 autoref_args: AutorefArgs) -> Ty<'tcx> where
2773 let method = match trait_did {
2774 Some(trait_did) => {
2775 // We do eager coercions to make using operators
2778 // - If the input is of type &'a T (resp. &'a mut T),
2779 // then reborrow it to &'b T (resp. &'b mut T) where
2780 // 'b <= 'a. This makes things like `x == y`, where
2781 // `x` and `y` are both region pointers, work. We
2782 // could also solve this with variance or different
2783 // traits that don't force left and right to have same
2785 let (adj_ty, adjustment) = match lhs_ty.sty {
2786 ty::ty_rptr(r_in, mt) => {
2787 let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
2788 fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in);
2789 let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt);
2790 let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None);
2791 let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) };
2792 (adjusted_ty, adjustment)
2795 (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None })
2799 debug!("adjusted_ty={} adjustment={:?}",
2800 adj_ty.repr(fcx.tcx()),
2803 method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname,
2804 trait_did, adjustment, adj_ty, None)
2808 let args = match rhs {
2809 Some(rhs) => slice::ref_slice(rhs),
2814 let method_ty = method.ty;
2815 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2816 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
2817 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2818 match check_method_argument_types(fcx,
2826 ty::FnConverging(result_type) => result_type,
2827 ty::FnDiverging => fcx.tcx().types.err
2832 // Check the args anyway
2833 // so we get all the error messages
2834 let expected_ty = fcx.tcx().types.err;
2835 check_method_argument_types(fcx,
2848 // could be either an expr_binop or an expr_assign_binop
2849 fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
2850 expr: &'tcx ast::Expr,
2852 lhs: &'tcx ast::Expr,
2853 rhs: &'tcx P<ast::Expr>,
2854 is_binop_assignment: IsBinopAssignment) {
2855 let tcx = fcx.ccx.tcx;
2857 let lvalue_pref = match is_binop_assignment {
2858 BinopAssignment => PreferMutLvalue,
2859 SimpleBinop => NoPreference
2861 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2863 // Callee does bot / err checking
2864 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2865 fcx.expr_ty(&*lhs));
2867 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) {
2868 // Shift is a special case: rhs must be uint, no matter what lhs is
2869 check_expr(fcx, &**rhs);
2870 let rhs_ty = fcx.expr_ty(&**rhs);
2871 let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty);
2872 if ty::type_is_integral(rhs_ty) {
2873 fcx.write_ty(expr.id, lhs_t);
2875 fcx.type_error_message(
2879 "right-hand-side of a shift operation must have integral type, \
2885 fcx.write_ty(expr.id, fcx.tcx().types.err);
2890 if ty::is_binopable(tcx, lhs_t, op) {
2891 let tvar = fcx.infcx().next_ty_var();
2892 demand::suptype(fcx, expr.span, tvar, lhs_t);
2893 check_expr_has_type(fcx, &**rhs, tvar);
2895 let result_t = match op.node {
2896 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2898 if ty::type_is_simd(tcx, lhs_t) {
2899 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2900 fcx.type_error_message(expr.span,
2902 format!("binary comparison \
2903 operation `{}` not \
2904 supported for floating \
2905 point SIMD vector `{}`",
2906 ast_util::binop_to_string(op.node),
2917 fcx.tcx().types.bool
2923 fcx.write_ty(expr.id, result_t);
2927 if op.node == ast::BiOr || op.node == ast::BiAnd {
2928 // This is an error; one of the operands must have the wrong
2930 fcx.write_error(expr.id);
2931 fcx.write_error(rhs.id);
2932 fcx.type_error_message(expr.span,
2934 format!("binary operation `{}` cannot be applied \
2936 ast_util::binop_to_string(op.node),
2943 // Check for overloaded operators if not an assignment.
2944 let result_t = if is_binop_assignment == SimpleBinop {
2945 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2947 fcx.type_error_message(expr.span,
2949 format!("binary assignment \
2951 cannot be applied to \
2953 ast_util::binop_to_string(op.node),
2958 check_expr(fcx, &**rhs);
2962 fcx.write_ty(expr.id, result_t);
2963 if ty::type_is_error(result_t) {
2964 fcx.write_ty(rhs.id, result_t);
2968 fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2969 ex: &'tcx ast::Expr,
2970 lhs_expr: &'tcx ast::Expr,
2971 lhs_resolved_t: Ty<'tcx>,
2973 rhs: &'tcx P<ast::Expr>) -> Ty<'tcx> {
2974 let tcx = fcx.ccx.tcx;
2975 let lang = &tcx.lang_items;
2976 let (name, trait_did) = match op.node {
2977 ast::BiAdd => ("add", lang.add_trait()),
2978 ast::BiSub => ("sub", lang.sub_trait()),
2979 ast::BiMul => ("mul", lang.mul_trait()),
2980 ast::BiDiv => ("div", lang.div_trait()),
2981 ast::BiRem => ("rem", lang.rem_trait()),
2982 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2983 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2984 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2985 ast::BiShl => ("shl", lang.shl_trait()),
2986 ast::BiShr => ("shr", lang.shr_trait()),
2987 ast::BiLt => ("lt", lang.ord_trait()),
2988 ast::BiLe => ("le", lang.ord_trait()),
2989 ast::BiGe => ("ge", lang.ord_trait()),
2990 ast::BiGt => ("gt", lang.ord_trait()),
2991 ast::BiEq => ("eq", lang.eq_trait()),
2992 ast::BiNe => ("ne", lang.eq_trait()),
2993 ast::BiAnd | ast::BiOr => {
2994 check_expr(fcx, &**rhs);
2995 return tcx.types.err;
2998 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2999 trait_did, lhs_expr, Some(rhs), || {
3000 fcx.type_error_message(ex.span, |actual| {
3001 format!("binary operation `{}` cannot be applied to type `{}`",
3002 ast_util::binop_to_string(op.node),
3004 }, lhs_resolved_t, None)
3005 }, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes })
3008 fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3011 trait_did: Option<ast::DefId>,
3012 ex: &'tcx ast::Expr,
3013 rhs_expr: &'tcx ast::Expr,
3015 op: ast::UnOp) -> Ty<'tcx> {
3016 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3017 trait_did, rhs_expr, None, || {
3018 fcx.type_error_message(ex.span, |actual| {
3019 format!("cannot apply unary operator `{}` to type `{}`",
3022 }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
3025 // Check field access expressions
3026 fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3027 expr: &'tcx ast::Expr,
3028 lvalue_pref: LvaluePreference,
3029 base: &'tcx ast::Expr,
3030 field: &ast::SpannedIdent) {
3031 let tcx = fcx.ccx.tcx;
3032 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3033 let expr_t = structurally_resolved_type(fcx, expr.span,
3035 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3036 let (_, autoderefs, field_ty) = autoderef(fcx,
3040 UnresolvedTypeAction::Error,
3044 ty::ty_struct(base_id, substs) => {
3045 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3046 let fields = ty::lookup_struct_fields(tcx, base_id);
3047 fcx.lookup_field_ty(expr.span, base_id, &fields[],
3048 field.node.name, &(*substs))
3055 fcx.write_ty(expr.id, field_ty);
3056 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3062 if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
3063 fcx.type_error_message(
3066 format!("attempted to take value of method `{}` on type \
3067 `{}`", token::get_ident(field.node), actual)
3071 tcx.sess.span_help(field.span,
3072 "maybe a `()` to call it is missing? \
3073 If not, try an anonymous function");
3075 fcx.type_error_message(
3078 format!("attempted access of field `{}` on \
3079 type `{}`, but no field with that \
3081 token::get_ident(field.node),
3085 if let Some(t) = ty::ty_to_def_id(expr_t) {
3086 suggest_field_names(t, field, tcx, vec![]);
3090 fcx.write_error(expr.id);
3093 // displays hints about the closest matches in field names
3094 fn suggest_field_names<'tcx>(id : DefId,
3095 field : &ast::SpannedIdent,
3096 tcx : &ty::ctxt<'tcx>,
3098 let ident = token::get_ident(field.node);
3099 let name = ident.get();
3100 // only find fits with at least one matching letter
3101 let mut best_dist = name.len();
3102 let fields = ty::lookup_struct_fields(tcx, id);
3103 let mut best = None;
3104 for elem in &fields {
3105 let n = elem.name.as_str();
3106 // ignore already set fields
3107 if skip.iter().any(|&x| x == n) {
3110 let dist = lev_distance(n, name);
3111 if dist < best_dist {
3116 if let Some(n) = best {
3117 tcx.sess.span_help(field.span,
3118 format!("did you mean `{}`?", n).as_slice());
3122 // Check tuple index expressions
3123 fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3124 expr: &'tcx ast::Expr,
3125 lvalue_pref: LvaluePreference,
3126 base: &'tcx ast::Expr,
3127 idx: codemap::Spanned<uint>) {
3128 let tcx = fcx.ccx.tcx;
3129 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3130 let expr_t = structurally_resolved_type(fcx, expr.span,
3132 let mut tuple_like = false;
3133 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3134 let (_, autoderefs, field_ty) = autoderef(fcx,
3138 UnresolvedTypeAction::Error,
3142 ty::ty_struct(base_id, substs) => {
3143 tuple_like = ty::is_tuple_struct(tcx, base_id);
3145 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3146 let fields = ty::lookup_struct_fields(tcx, base_id);
3147 fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
3148 idx.node, &(*substs))
3153 ty::ty_tup(ref v) => {
3155 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3162 fcx.write_ty(expr.id, field_ty);
3163 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3168 fcx.type_error_message(
3172 format!("attempted out-of-bounds tuple index `{}` on \
3177 format!("attempted tuple index `{}` on type `{}`, but the \
3178 type was not a tuple or tuple struct",
3185 fcx.write_error(expr.id);
3188 fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3189 struct_ty: Ty<'tcx>,
3191 class_id: ast::DefId,
3192 node_id: ast::NodeId,
3193 substitutions: &'tcx subst::Substs<'tcx>,
3194 field_types: &[ty::field_ty],
3195 ast_fields: &'tcx [ast::Field],
3196 check_completeness: bool,
3197 enum_id_opt: Option<ast::DefId>) {
3198 let tcx = fcx.ccx.tcx;
3200 let mut class_field_map = FnvHashMap();
3201 let mut fields_found = 0;
3202 for field in field_types {
3203 class_field_map.insert(field.name, (field.id, false));
3206 let mut error_happened = false;
3208 // Typecheck each field.
3209 for field in ast_fields {
3210 let mut expected_field_type = tcx.types.err;
3212 let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
3215 fcx.type_error_message(
3217 |actual| match enum_id_opt {
3219 let variant_type = ty::enum_variant_with_id(tcx,
3222 format!("struct variant `{}::{}` has no field named `{}`",
3223 actual, variant_type.name.as_str(),
3224 token::get_ident(field.ident.node))
3227 format!("structure `{}` has no field named `{}`",
3229 token::get_ident(field.ident.node))
3234 // prevent all specified fields from being suggested
3235 let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
3236 let actual_id = match enum_id_opt {
3237 Some(_) => class_id,
3238 None => ty::ty_to_def_id(struct_ty).unwrap()
3240 suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
3241 error_happened = true;
3243 Some((_, true)) => {
3244 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3245 "field `{}` specified more than once",
3246 token::get_ident(field.ident.node));
3247 error_happened = true;
3249 Some((field_id, false)) => {
3250 expected_field_type =
3251 ty::lookup_field_type(
3252 tcx, class_id, field_id, substitutions);
3253 expected_field_type =
3254 fcx.normalize_associated_types_in(
3255 field.span, &expected_field_type);
3256 class_field_map.insert(
3257 field.ident.node.name, (field_id, true));
3262 // Make sure to give a type to the field even if there's
3263 // an error, so we can continue typechecking
3264 check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
3268 fcx.write_error(node_id);
3271 if check_completeness && !error_happened {
3272 // Make sure the programmer specified all the fields.
3273 assert!(fields_found <= field_types.len());
3274 if fields_found < field_types.len() {
3275 let mut missing_fields = Vec::new();
3276 for class_field in field_types {
3277 let name = class_field.name;
3278 let (_, seen) = class_field_map[name];
3280 missing_fields.push(
3281 format!("`{}`", token::get_name(name).get()))
3285 span_err!(tcx.sess, span, E0063,
3286 "missing field{}: {}",
3287 if missing_fields.len() == 1 {""} else {"s"},
3288 missing_fields.connect(", "));
3292 if !error_happened {
3293 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3294 class_id, substitutions));
3298 fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3300 span: codemap::Span,
3301 class_id: ast::DefId,
3302 fields: &'tcx [ast::Field],
3303 base_expr: Option<&'tcx ast::Expr>) {
3304 let tcx = fcx.ccx.tcx;
3306 // Generate the struct type.
3308 ty: mut struct_type,
3309 substs: struct_substs
3310 } = fcx.instantiate_type(span, class_id);
3312 // Look up and check the fields.
3313 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3314 check_struct_or_variant_fields(fcx,
3319 fcx.ccx.tcx.mk_substs(struct_substs),
3322 base_expr.is_none(),
3324 if ty::type_is_error(fcx.node_ty(id)) {
3325 struct_type = tcx.types.err;
3328 // Check the base expression if necessary.
3331 Some(base_expr) => {
3332 check_expr_has_type(fcx, &*base_expr, struct_type);
3336 // Write in the resulting type.
3337 fcx.write_ty(id, struct_type);
3340 fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3342 span: codemap::Span,
3343 enum_id: ast::DefId,
3344 variant_id: ast::DefId,
3345 fields: &'tcx [ast::Field]) {
3346 let tcx = fcx.ccx.tcx;
3348 // Look up the number of type parameters and the raw type, and
3349 // determine whether the enum is region-parameterized.
3352 substs: substitutions
3353 } = fcx.instantiate_type(span, enum_id);
3355 // Look up and check the enum variant fields.
3356 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3357 check_struct_or_variant_fields(fcx,
3362 fcx.ccx.tcx.mk_substs(substitutions),
3367 fcx.write_ty(id, enum_type);
3370 fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
3372 fields: &'tcx [ast::Field],
3373 base_expr: &'tcx Option<P<ast::Expr>>) {
3374 // Make sure to still write the types
3375 // otherwise we might ICE
3376 fcx.write_error(id);
3377 for field in fields {
3378 check_expr(fcx, &*field.expr);
3381 Some(ref base) => check_expr(fcx, &**base),
3386 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
3388 let tcx = fcx.ccx.tcx;
3391 ast::ExprBox(ref opt_place, ref subexpr) => {
3392 opt_place.as_ref().map(|place|check_expr(fcx, &**place));
3393 check_expr(fcx, &**subexpr);
3395 let mut checked = false;
3396 opt_place.as_ref().map(|place| match place.node {
3397 ast::ExprPath(ref path) => {
3398 // FIXME(pcwalton): For now we hardcode the two permissible
3399 // places: the exchange heap and the managed heap.
3400 let definition = lookup_def(fcx, path.span, place.id);
3401 let def_id = definition.def_id();
3402 let referent_ty = fcx.expr_ty(&**subexpr);
3403 if tcx.lang_items.exchange_heap() == Some(def_id) {
3404 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3412 span_err!(tcx.sess, expr.span, E0066,
3413 "only the managed heap and exchange heap are currently supported");
3414 fcx.write_ty(id, tcx.types.err);
3418 ast::ExprLit(ref lit) => {
3419 let typ = check_lit(fcx, &**lit, expected);
3420 fcx.write_ty(id, typ);
3422 ast::ExprBinary(op, ref lhs, ref rhs) => {
3423 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3425 let lhs_ty = fcx.expr_ty(&**lhs);
3426 let rhs_ty = fcx.expr_ty(&**rhs);
3427 if ty::type_is_error(lhs_ty) ||
3428 ty::type_is_error(rhs_ty) {
3429 fcx.write_error(id);
3432 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3433 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3435 let lhs_t = fcx.expr_ty(&**lhs);
3436 let result_t = fcx.expr_ty(expr);
3437 demand::suptype(fcx, expr.span, result_t, lhs_t);
3439 let tcx = fcx.tcx();
3440 if !ty::expr_is_lval(tcx, &**lhs) {
3441 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3444 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3446 // Overwrite result of check_binop...this preserves existing behavior
3447 // but seems quite dubious with regard to user-defined methods
3448 // and so forth. - Niko
3449 if !ty::type_is_error(result_t) {
3450 fcx.write_nil(expr.id);
3453 ast::ExprUnary(unop, ref oprnd) => {
3454 let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
3456 ast::UnUniq => match ty.sty {
3457 ty::ty_uniq(ty) => {
3458 Expectation::rvalue_hint(ty)
3464 ast::UnNot | ast::UnNeg => {
3472 let lvalue_pref = match unop {
3473 ast::UnDeref => lvalue_pref,
3476 check_expr_with_expectation_and_lvalue_pref(
3477 fcx, &**oprnd, expected_inner, lvalue_pref);
3478 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3480 if !ty::type_is_error(oprnd_t) {
3483 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3486 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3487 oprnd_t = match ty::deref(oprnd_t, true) {
3489 None => match try_overloaded_deref(fcx, expr.span,
3490 Some(MethodCall::expr(expr.id)),
3491 Some(&**oprnd), oprnd_t, lvalue_pref) {
3494 let is_newtype = match oprnd_t.sty {
3495 ty::ty_struct(did, substs) => {
3496 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3498 && fields[0].name ==
3499 token::special_idents::unnamed_field.name
3504 // This is an obsolete struct deref
3505 span_err!(tcx.sess, expr.span, E0068,
3506 "single-field tuple-structs can \
3507 no longer be dereferenced");
3509 fcx.type_error_message(expr.span, |actual| {
3510 format!("type `{}` cannot be \
3511 dereferenced", actual)
3520 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3522 if !(ty::type_is_integral(oprnd_t) ||
3523 oprnd_t.sty == ty::ty_bool) {
3524 oprnd_t = check_user_unop(fcx, "!", "not",
3525 tcx.lang_items.not_trait(),
3526 expr, &**oprnd, oprnd_t, unop);
3530 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3532 if !(ty::type_is_integral(oprnd_t) ||
3533 ty::type_is_fp(oprnd_t)) {
3534 oprnd_t = check_user_unop(fcx, "-", "neg",
3535 tcx.lang_items.neg_trait(),
3536 expr, &**oprnd, oprnd_t, unop);
3541 fcx.write_ty(id, oprnd_t);
3543 ast::ExprAddrOf(mutbl, ref oprnd) => {
3544 let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
3546 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
3547 if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
3548 // Lvalues may legitimately have unsized types.
3549 // For example, dereferences of a fat pointer and
3550 // the last field of a struct can be unsized.
3551 ExpectHasType(mt.ty)
3553 Expectation::rvalue_hint(mt.ty)
3559 let lvalue_pref = match mutbl {
3560 ast::MutMutable => PreferMutLvalue,
3561 ast::MutImmutable => NoPreference
3563 check_expr_with_expectation_and_lvalue_pref(fcx,
3568 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3569 let oprnd_t = if ty::type_is_error(tm.ty) {
3572 // Note: at this point, we cannot say what the best lifetime
3573 // is to use for resulting pointer. We want to use the
3574 // shortest lifetime possible so as to avoid spurious borrowck
3575 // errors. Moreover, the longest lifetime will depend on the
3576 // precise details of the value whose address is being taken
3577 // (and how long it is valid), which we don't know yet until type
3578 // inference is complete.
3580 // Therefore, here we simply generate a region variable. The
3581 // region inferencer will then select the ultimate value.
3582 // Finally, borrowck is charged with guaranteeing that the
3583 // value whose address was taken can actually be made to live
3584 // as long as it needs to live.
3586 // String literals are already, implicitly converted to slices.
3587 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3588 // Empty slices live in static memory.
3589 ast::ExprVec(ref elements) if elements.len() == 0 => {
3590 // Note: we do not assign a lifetime of
3591 // static. This is because the resulting type
3592 // `&'static [T]` would require that T outlives
3594 let region = fcx.infcx().next_region_var(
3595 infer::AddrOfSlice(expr.span));
3596 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3599 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3600 ty::mk_rptr(tcx, tcx.mk_region(region), tm)
3604 fcx.write_ty(id, oprnd_t);
3606 ast::ExprPath(ref path) => {
3607 let defn = lookup_def(fcx, path.span, id);
3608 let pty = type_scheme_for_def(fcx, expr.span, defn);
3609 instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
3611 // We always require that the type provided as the value for
3612 // a type parameter outlives the moment of instantiation.
3613 constrain_path_type_parameters(fcx, expr);
3615 ast::ExprQPath(ref qpath) => {
3616 // Require explicit type params for the trait.
3617 let self_ty = fcx.to_ty(&*qpath.self_type);
3618 astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
3620 let defn = lookup_def(fcx, expr.span, id);
3621 let pty = type_scheme_for_def(fcx, expr.span, defn);
3622 let mut path = qpath.trait_ref.path.clone();
3623 path.segments.push(qpath.item_path.clone());
3624 instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
3626 // We always require that the type provided as the value for
3627 // a type parameter outlives the moment of instantiation.
3628 constrain_path_type_parameters(fcx, expr);
3630 ast::ExprInlineAsm(ref ia) => {
3631 for &(_, ref input) in &ia.inputs {
3632 check_expr(fcx, &**input);
3634 for &(_, ref out, _) in &ia.outputs {
3635 check_expr(fcx, &**out);
3639 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3640 ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3641 ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
3642 ast::ExprRet(ref expr_opt) => {
3644 ty::FnConverging(result_type) => {
3647 if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
3648 result_type, ty::mk_nil(fcx.tcx())) {
3649 span_err!(tcx.sess, expr.span, E0069,
3650 "`return;` in function returning non-nil");
3653 check_expr_coercable_to_type(fcx, &**e, result_type);
3657 ty::FnDiverging => {
3658 if let Some(ref e) = *expr_opt {
3659 check_expr(fcx, &**e);
3661 span_err!(tcx.sess, expr.span, E0166,
3662 "`return` in a function declared as diverging");
3665 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3667 ast::ExprParen(ref a) => {
3668 check_expr_with_expectation_and_lvalue_pref(fcx,
3672 fcx.write_ty(id, fcx.expr_ty(&**a));
3674 ast::ExprAssign(ref lhs, ref rhs) => {
3675 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3677 let tcx = fcx.tcx();
3678 if !ty::expr_is_lval(tcx, &**lhs) {
3679 span_err!(tcx.sess, expr.span, E0070,
3680 "illegal left-hand side expression");
3683 let lhs_ty = fcx.expr_ty(&**lhs);
3684 check_expr_coercable_to_type(fcx, &**rhs, lhs_ty);
3685 let rhs_ty = fcx.expr_ty(&**rhs);
3687 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3689 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3690 fcx.write_error(id);
3695 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3696 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
3697 id, expr.span, expected);
3699 ast::ExprIfLet(..) => {
3700 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3702 ast::ExprWhile(ref cond, ref body, _) => {
3703 check_expr_has_type(fcx, &**cond, tcx.types.bool);
3704 check_block_no_value(fcx, &**body);
3705 let cond_ty = fcx.expr_ty(&**cond);
3706 let body_ty = fcx.node_ty(body.id);
3707 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3708 fcx.write_error(id);
3714 ast::ExprWhileLet(..) => {
3715 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3717 ast::ExprForLoop(..) => {
3718 tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
3720 ast::ExprLoop(ref body, _) => {
3721 check_block_no_value(fcx, &**body);
3722 if !may_break(tcx, expr.id, &**body) {
3723 fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
3728 ast::ExprMatch(ref discrim, ref arms, match_src) => {
3729 _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
3731 ast::ExprClosure(capture, opt_kind, ref decl, ref body) => {
3732 closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected);
3734 ast::ExprBlock(ref b) => {
3735 check_block_with_expected(fcx, &**b, expected);
3736 fcx.write_ty(id, fcx.node_ty(b.id));
3738 ast::ExprCall(ref callee, ref args) => {
3739 callee::check_call(fcx, expr, &**callee, &args[], expected);
3741 ast::ExprMethodCall(ident, ref tps, ref args) => {
3742 check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
3743 let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3744 let args_err = arg_tys.fold(false,
3746 rest_err || ty::type_is_error(a)});
3748 fcx.write_error(id);
3751 ast::ExprCast(ref e, ref t) => {
3752 if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
3753 check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
3755 check_cast(fcx, expr, &**e, &**t);
3757 ast::ExprVec(ref args) => {
3758 let uty = expected.to_option(fcx).and_then(|uty| {
3760 ty::ty_vec(ty, _) => Some(ty),
3765 let typ = match uty {
3768 check_expr_coercable_to_type(fcx, &**e, uty);
3773 let t: Ty = fcx.infcx().next_ty_var();
3775 check_expr_has_type(fcx, &**e, t);
3780 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3781 fcx.write_ty(id, typ);
3783 ast::ExprRepeat(ref element, ref count_expr) => {
3784 check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
3785 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3787 let uty = match expected {
3788 ExpectHasType(uty) => {
3790 ty::ty_vec(ty, _) => Some(ty),
3797 let (element_ty, t) = match uty {
3799 check_expr_coercable_to_type(fcx, &**element, uty);
3803 let t: Ty = fcx.infcx().next_ty_var();
3804 check_expr_has_type(fcx, &**element, t);
3805 (fcx.expr_ty(&**element), t)
3810 // For [foo, ..n] where n > 1, `foo` must have
3812 fcx.require_type_meets(
3819 if ty::type_is_error(element_ty) {
3820 fcx.write_error(id);
3822 let t = ty::mk_vec(tcx, t, Some(count));
3823 fcx.write_ty(id, t);
3826 ast::ExprTup(ref elts) => {
3827 let flds = expected.only_has_type(fcx).and_then(|ty| {
3829 ty::ty_tup(ref flds) => Some(&flds[]),
3833 let mut err_field = false;
3835 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3836 let t = match flds {
3837 Some(ref fs) if i < fs.len() => {
3839 check_expr_coercable_to_type(fcx, &**e, ety);
3843 check_expr_with_expectation(fcx, &**e, NoExpectation);
3847 err_field = err_field || ty::type_is_error(t);
3851 fcx.write_error(id);
3853 let typ = ty::mk_tup(tcx, elt_ts);
3854 fcx.write_ty(id, typ);
3857 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
3858 // Resolve the path.
3859 let def = tcx.def_map.borrow().get(&id).map(|i| *i);
3860 let struct_id = match def {
3861 Some(def::DefVariant(enum_id, variant_id, true)) => {
3862 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3863 variant_id, &fields[]);
3866 Some(def::DefTrait(def_id)) => {
3867 span_err!(tcx.sess, path.span, E0159,
3868 "use of trait `{}` as a struct constructor",
3869 pprust::path_to_string(path));
3870 check_struct_fields_on_error(fcx,
3877 // Verify that this was actually a struct.
3878 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3880 ty::ty_struct(struct_did, _) => {
3881 check_struct_constructor(fcx,
3886 base_expr.as_ref().map(|e| &**e));
3889 span_err!(tcx.sess, path.span, E0071,
3890 "`{}` does not name a structure",
3891 pprust::path_to_string(path));
3892 check_struct_fields_on_error(fcx,
3902 tcx.sess.span_bug(path.span,
3903 "structure constructor wasn't resolved")
3907 // Turn the path into a type and verify that that type unifies with
3908 // the resulting structure type. This is needed to handle type
3909 // parameters correctly.
3910 let actual_structure_type = fcx.expr_ty(&*expr);
3911 if !ty::type_is_error(actual_structure_type) {
3912 let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
3913 match fcx.mk_subty(false,
3914 infer::Misc(path.span),
3915 actual_structure_type,
3916 type_and_substs.ty) {
3918 Err(type_error) => {
3919 let type_error_description =
3920 ty::type_err_to_str(tcx, &type_error);
3921 span_err!(fcx.tcx().sess, path.span, E0235,
3922 "structure constructor specifies a \
3923 structure of type `{}`, but this \
3924 structure has type `{}`: {}",
3926 .ty_to_string(type_and_substs.ty),
3929 actual_structure_type),
3930 type_error_description);
3931 ty::note_and_explain_type_err(tcx, &type_error);
3936 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
3938 ast::ExprField(ref base, ref field) => {
3939 check_field(fcx, expr, lvalue_pref, &**base, field);
3941 ast::ExprTupField(ref base, idx) => {
3942 check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
3944 ast::ExprIndex(ref base, ref idx) => {
3945 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3946 let base_t = fcx.expr_ty(&**base);
3947 if ty::type_is_error(base_t) {
3948 fcx.write_ty(id, base_t);
3950 check_expr(fcx, &**idx);
3951 let idx_t = fcx.expr_ty(&**idx);
3952 if ty::type_is_error(idx_t) {
3953 fcx.write_ty(id, idx_t);
3955 let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3958 autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
3960 MethodCall::expr(expr.id),
3970 Some((index_ty, element_ty)) => {
3971 // FIXME: we've already checked idx above, we should
3972 // probably just demand subtype or something here.
3973 check_expr_has_type(fcx, &**idx, index_ty);
3974 fcx.write_ty(id, element_ty);
3977 check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3978 fcx.type_error_message(
3981 format!("cannot index a value of type `{}`",
3986 fcx.write_ty(id, fcx.tcx().types.err);
3992 ast::ExprRange(ref start, ref end) => {
3993 let t_start = start.as_ref().map(|e| {
3994 check_expr(fcx, &**e);
3997 let t_end = end.as_ref().map(|e| {
3998 check_expr(fcx, &**e);
4002 let idx_type = match (t_start, t_end) {
4003 (Some(ty), None) | (None, Some(ty)) => {
4006 (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
4007 ty::type_is_error(t_end)) => {
4008 Some(fcx.tcx().types.err)
4010 (Some(t_start), Some(t_end)) => {
4011 Some(infer::common_supertype(fcx.infcx(),
4012 infer::RangeExpression(expr.span),
4020 // Note that we don't check the type of start/end satisfy any
4021 // bounds because right now the range structs do not have any. If we add
4022 // some bounds, then we'll need to check `t_start` against them here.
4024 let range_type = match idx_type {
4025 Some(idx_type) if ty::type_is_error(idx_type) => {
4029 // Find the did from the appropriate lang item.
4030 let did = match (start, end) {
4031 (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
4032 (&Some(_), &None) => tcx.lang_items.range_from_struct(),
4033 (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
4035 tcx.sess.span_bug(expr.span, "full range should be dealt with above")
4039 if let Some(did) = did {
4040 let polytype = ty::lookup_item_type(tcx, did);
4041 let substs = Substs::new_type(vec![idx_type], vec![]);
4042 let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
4043 fcx.add_obligations_for_parameters(
4044 traits::ObligationCause::new(expr.span,
4046 traits::ItemObligation(did)),
4049 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4051 span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
4056 // Neither start nor end => RangeFull
4057 if let Some(did) = tcx.lang_items.range_full_struct() {
4058 let substs = Substs::new_type(vec![], vec![]);
4059 ty::mk_struct(tcx, did, tcx.mk_substs(substs))
4061 span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
4067 fcx.write_ty(id, range_type);
4072 debug!("type of expr({}) {} is...", expr.id,
4073 syntax::print::pprust::expr_to_string(expr));
4074 debug!("... {}, expected is {}",
4075 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4076 expected.repr(tcx));
4081 fn constrain_path_type_parameters(fcx: &FnCtxt,
4084 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4085 fcx.add_default_region_param_bounds(&item_substs.substs, expr);
4089 impl<'tcx> Expectation<'tcx> {
4090 /// Provide an expectation for an rvalue expression given an *optional*
4091 /// hint, which is not required for type safety (the resulting type might
4092 /// be checked higher up, as is the case with `&expr` and `box expr`), but
4093 /// is useful in determining the concrete type.
4095 /// The primary use case is where the expected type is a fat pointer,
4096 /// like `&[int]`. For example, consider the following statement:
4098 /// let x: &[int] = &[1, 2, 3];
4100 /// In this case, the expected type for the `&[1, 2, 3]` expression is
4101 /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
4102 /// expectation `ExpectHasType([int])`, that would be too strong --
4103 /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
4104 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
4105 /// to the type `&[int]`. Therefore, we propagate this more limited hint,
4106 /// which still is useful, because it informs integer literals and the like.
4107 /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
4108 /// for examples of where this comes up,.
4109 fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
4111 ty::ty_vec(_, None) | ty::ty_trait(..) => {
4112 ExpectRvalueLikeUnsized(ty)
4114 _ => ExpectHasType(ty)
4118 // Resolves `expected` by a single level if it is a variable. If
4119 // there is no expected type or resolution is not possible (e.g.,
4120 // no constraints yet present), just returns `None`.
4121 fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
4126 ExpectCastableToType(t) => {
4127 ExpectCastableToType(
4128 fcx.infcx().resolve_type_vars_if_possible(&t))
4130 ExpectHasType(t) => {
4132 fcx.infcx().resolve_type_vars_if_possible(&t))
4134 ExpectRvalueLikeUnsized(t) => {
4135 ExpectRvalueLikeUnsized(
4136 fcx.infcx().resolve_type_vars_if_possible(&t))
4141 fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4142 match self.resolve(fcx) {
4143 NoExpectation => None,
4144 ExpectCastableToType(ty) |
4146 ExpectRvalueLikeUnsized(ty) => Some(ty),
4150 fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
4151 match self.resolve(fcx) {
4152 ExpectHasType(ty) => Some(ty),
4158 impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
4159 fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
4161 NoExpectation => format!("NoExpectation"),
4162 ExpectHasType(t) => format!("ExpectHasType({})",
4164 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4166 ExpectRvalueLikeUnsized(t) => format!("ExpectRvalueLikeUnsized({})",
4172 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
4174 init: &'tcx ast::Expr)
4176 let local_ty = fcx.local_ty(init.span, nid);
4177 check_expr_coercable_to_type(fcx, init, local_ty)
4180 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) {
4181 let tcx = fcx.ccx.tcx;
4183 let t = fcx.local_ty(local.span, local.id);
4184 fcx.write_ty(local.id, t);
4186 if let Some(ref init) = local.init {
4187 check_decl_initializer(fcx, local.id, &**init);
4188 let init_ty = fcx.expr_ty(&**init);
4189 if ty::type_is_error(init_ty) {
4190 fcx.write_ty(local.id, init_ty);
4194 let pcx = pat_ctxt {
4196 map: pat_id_map(&tcx.def_map, &*local.pat),
4198 _match::check_pat(&pcx, &*local.pat, t);
4199 let pat_ty = fcx.node_ty(local.pat.id);
4200 if ty::type_is_error(pat_ty) {
4201 fcx.write_ty(local.id, pat_ty);
4205 pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt) {
4207 let mut saw_bot = false;
4208 let mut saw_err = false;
4210 ast::StmtDecl(ref decl, id) => {
4213 ast::DeclLocal(ref l) => {
4214 check_decl_local(fcx, &**l);
4215 let l_t = fcx.node_ty(l.id);
4216 saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
4217 saw_err = saw_err || ty::type_is_error(l_t);
4219 ast::DeclItem(_) => {/* ignore for now */ }
4222 ast::StmtExpr(ref expr, id) => {
4224 // Check with expected type of ()
4225 check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
4226 let expr_ty = fcx.expr_ty(&**expr);
4227 saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
4228 saw_err = saw_err || ty::type_is_error(expr_ty);
4230 ast::StmtSemi(ref expr, id) => {
4232 check_expr(fcx, &**expr);
4233 let expr_ty = fcx.expr_ty(&**expr);
4234 saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
4235 saw_err |= ty::type_is_error(expr_ty);
4237 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4240 fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
4243 fcx.write_error(node_id);
4246 fcx.write_nil(node_id)
4250 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block) {
4251 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
4252 let blkty = fcx.node_ty(blk.id);
4253 if ty::type_is_error(blkty) {
4254 fcx.write_error(blk.id);
4256 let nilty = ty::mk_nil(fcx.tcx());
4257 demand::suptype(fcx, blk.span, nilty, blkty);
4261 fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4262 blk: &'tcx ast::Block,
4263 expected: Expectation<'tcx>) {
4265 let mut fcx_ps = fcx.ps.borrow_mut();
4266 let unsafety_state = fcx_ps.recurse(blk);
4267 replace(&mut *fcx_ps, unsafety_state)
4270 let mut warned = false;
4271 let mut any_diverges = false;
4272 let mut any_err = false;
4273 for s in &blk.stmts {
4274 check_stmt(fcx, &**s);
4275 let s_id = ast_util::stmt_id(&**s);
4276 let s_ty = fcx.node_ty(s_id);
4277 if any_diverges && !warned && match s.node {
4278 ast::StmtDecl(ref decl, _) => {
4280 ast::DeclLocal(_) => true,
4284 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4290 .add_lint(lint::builtin::UNREACHABLE_CODE,
4293 "unreachable statement".to_string());
4296 any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
4297 any_err = any_err || ty::type_is_error(s_ty);
4300 None => if any_err {
4301 fcx.write_error(blk.id);
4302 } else if any_diverges {
4303 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4305 fcx.write_nil(blk.id);
4308 if any_diverges && !warned {
4312 .add_lint(lint::builtin::UNREACHABLE_CODE,
4315 "unreachable expression".to_string());
4317 let ety = match expected {
4318 ExpectHasType(ety) => {
4319 check_expr_coercable_to_type(fcx, &**e, ety);
4323 check_expr_with_expectation(fcx, &**e, expected);
4329 fcx.write_error(blk.id);
4330 } else if any_diverges {
4331 fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
4333 fcx.write_ty(blk.id, ety);
4338 *fcx.ps.borrow_mut() = prev;
4341 /// Checks a constant appearing in a type. At the moment this is just the
4342 /// length expression in a fixed-length vector, but someday it might be
4343 /// extended to type-level numeric literals.
4344 fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
4345 expr: &'tcx ast::Expr,
4346 expected_type: Ty<'tcx>) {
4347 let inh = static_inherited_fields(ccx);
4348 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(expected_type), expr.id);
4349 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4352 fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4356 let inh = static_inherited_fields(ccx);
4357 let rty = ty::node_id_to_type(ccx.tcx, id);
4358 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4359 let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
4360 check_const_with_ty(&fcx, sp, e, declty);
4363 fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4367 // Gather locals in statics (because of block expressions).
4368 // This is technically unnecessary because locals in static items are forbidden,
4369 // but prevents type checking from blowing up before const checking can properly
4371 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4373 check_expr_with_hint(fcx, e, declty);
4374 demand::coerce(fcx, e.span, declty, e);
4375 vtable::select_all_fcx_obligations_or_error(fcx);
4376 regionck::regionck_expr(fcx, e);
4377 writeback::resolve_type_vars_in_expr(fcx, e);
4380 /// Checks whether a type can be represented in memory. In particular, it
4381 /// identifies types that contain themselves without indirection through a
4382 /// pointer, which would mean their size is unbounded. This is different from
4383 /// the question of whether a type can be instantiated. See the definition of
4384 /// `check_instantiable`.
4385 pub fn check_representable(tcx: &ty::ctxt,
4387 item_id: ast::NodeId,
4388 designation: &str) -> bool {
4389 let rty = ty::node_id_to_type(tcx, item_id);
4391 // Check that it is possible to represent this type. This call identifies
4392 // (1) types that contain themselves and (2) types that contain a different
4393 // recursive type. It is only necessary to throw an error on those that
4394 // contain themselves. For case 2, there must be an inner type that will be
4395 // caught by case 1.
4396 match ty::is_type_representable(tcx, sp, rty) {
4397 ty::SelfRecursive => {
4398 span_err!(tcx.sess, sp, E0072,
4399 "illegal recursive {} type; \
4400 wrap the inner value in a box to make it representable",
4404 ty::Representable | ty::ContainsRecursive => (),
4409 /// Checks whether a type can be created without an instance of itself.
4410 /// This is similar but different from the question of whether a type
4411 /// can be represented. For example, the following type:
4413 /// enum foo { None, Some(foo) }
4415 /// is instantiable but is not representable. Similarly, the type
4417 /// enum foo { Some(@foo) }
4419 /// is representable, but not instantiable.
4420 pub fn check_instantiable(tcx: &ty::ctxt,
4422 item_id: ast::NodeId)
4424 let item_ty = ty::node_id_to_type(tcx, item_id);
4425 if !ty::is_instantiable(tcx, item_ty) {
4426 span_err!(tcx.sess, sp, E0073,
4427 "this type cannot be instantiated without an \
4428 instance of itself");
4429 span_help!(tcx.sess, sp, "consider using `Option<{}>`",
4430 ppaux::ty_to_string(tcx, item_ty));
4437 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4438 let t = ty::node_id_to_type(tcx, id);
4439 if ty::type_needs_subst(t) {
4440 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4444 ty::ty_struct(did, substs) => {
4445 let fields = ty::lookup_struct_fields(tcx, did);
4446 if fields.is_empty() {
4447 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4450 let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
4451 if !fields.iter().all(
4452 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4453 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4456 if !ty::type_is_machine(e) {
4457 span_err!(tcx.sess, sp, E0077,
4458 "SIMD vector element type should be machine type");
4466 pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
4468 vs: &'tcx [P<ast::Variant>],
4471 fn disr_in_range(ccx: &CrateCtxt,
4473 disr: ty::Disr) -> bool {
4474 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4476 ast::TyU8 => disr as u8 as Disr == disr,
4477 ast::TyU16 => disr as u16 as Disr == disr,
4478 ast::TyU32 => disr as u32 as Disr == disr,
4479 ast::TyU64 => disr as u64 as Disr == disr,
4480 ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
4483 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4485 ast::TyI8 => disr as i8 as Disr == disr,
4486 ast::TyI16 => disr as i16 as Disr == disr,
4487 ast::TyI32 => disr as i32 as Disr == disr,
4488 ast::TyI64 => disr as i64 as Disr == disr,
4489 ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
4493 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4494 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4498 fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
4499 vs: &'tcx [P<ast::Variant>],
4501 hint: attr::ReprAttr)
4502 -> Vec<Rc<ty::VariantInfo<'tcx>>> {
4504 let rty = ty::node_id_to_type(ccx.tcx, id);
4505 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4506 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4507 let mut prev_disr_val: Option<ty::Disr> = None;
4511 // If the discriminant value is specified explicitly in the enum check whether the
4512 // initialization expression is valid, otherwise use the last value plus one.
4513 let mut current_disr_val = match prev_disr_val {
4514 Some(prev_disr_val) => prev_disr_val + 1,
4515 None => ty::INITIAL_DISCRIMINANT_VALUE
4518 match v.node.disr_expr {
4520 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4522 let inh = static_inherited_fields(ccx);
4523 let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
4524 let declty = match hint {
4525 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
4526 attr::ReprInt(_, attr::SignedInt(ity)) => {
4527 ty::mk_mach_int(fcx.tcx(), ity)
4529 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4530 ty::mk_mach_uint(fcx.tcx(), ity)
4533 check_const_with_ty(&fcx, e.span, &**e, declty);
4534 // check_expr (from check_const pass) doesn't guarantee
4535 // that the expression is in a form that eval_const_expr can
4536 // handle, so we may still get an internal compiler error
4538 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4539 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4540 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4542 span_err!(ccx.tcx.sess, e.span, E0079,
4543 "expected signed integer constant");
4546 span_err!(ccx.tcx.sess, e.span, E0080,
4547 "expected constant: {}", *err);
4554 // Check for duplicate discriminant values
4555 match disr_vals.iter().position(|&x| x == current_disr_val) {
4557 span_err!(ccx.tcx.sess, v.span, E0081,
4558 "discriminant value `{}` already exists", disr_vals[i]);
4559 span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].id.node),
4560 "conflicting discriminant here")
4564 // Check for unrepresentable discriminant values
4566 attr::ReprAny | attr::ReprExtern => (),
4567 attr::ReprInt(sp, ity) => {
4568 if !disr_in_range(ccx, ity, current_disr_val) {
4569 span_err!(ccx.tcx.sess, v.span, E0082,
4570 "discriminant value outside specified type");
4571 span_note!(ccx.tcx.sess, sp,
4572 "discriminant type specified here");
4575 attr::ReprPacked => {
4576 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4579 disr_vals.push(current_disr_val);
4581 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4583 prev_disr_val = Some(current_disr_val);
4585 variants.push(variant_info);
4591 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4592 [].get(0).unwrap_or(&attr::ReprAny);
4594 if hint != attr::ReprAny && vs.len() <= 1 {
4596 span_err!(ccx.tcx.sess, sp, E0083,
4597 "unsupported representation for univariant enum");
4599 span_err!(ccx.tcx.sess, sp, E0084,
4600 "unsupported representation for zero-variant enum");
4604 let variants = do_check(ccx, vs, id, hint);
4606 // cache so that ty::enum_variants won't repeat this work
4607 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4609 check_representable(ccx.tcx, sp, id, "enum");
4611 // Check that it is possible to instantiate this enum:
4613 // This *sounds* like the same that as representable, but it's
4614 // not. See def'n of `check_instantiable()` for details.
4615 check_instantiable(ccx.tcx, sp, id);
4618 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4619 lookup_def_ccx(fcx.ccx, sp, id)
4622 // Returns the type parameter count and the type for the given definition.
4623 pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4626 -> TypeScheme<'tcx> {
4628 def::DefLocal(nid) | def::DefUpvar(nid, _) => {
4629 let typ = fcx.local_ty(sp, nid);
4630 return no_params(typ);
4632 def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
4633 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4634 def::DefStruct(id) | def::DefConst(id) => {
4635 return ty::lookup_item_type(fcx.ccx.tcx, id);
4639 def::DefAssociatedTy(..) |
4640 def::DefAssociatedPath(..) |
4642 def::DefTyParam(..) => {
4643 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4645 def::DefMod(..) | def::DefForeignMod(..) => {
4646 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4648 def::DefUse(..) => {
4649 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4651 def::DefRegion(..) => {
4652 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4654 def::DefTyParamBinder(..) => {
4655 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4657 def::DefLabel(..) => {
4658 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4660 def::DefSelfTy(..) => {
4661 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4666 // Instantiates the given path, which must refer to an item with the given
4667 // number of type parameters and type.
4668 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
4670 type_scheme: TypeScheme<'tcx>,
4671 opt_self_ty: Option<Ty<'tcx>>,
4674 node_id: ast::NodeId) {
4675 debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
4676 path.repr(fcx.tcx()),
4677 def.repr(fcx.tcx()),
4679 type_scheme.repr(fcx.tcx()));
4681 // We need to extract the type parameters supplied by the user in
4682 // the path `path`. Due to the current setup, this is a bit of a
4683 // tricky-process; the problem is that resolve only tells us the
4684 // end-point of the path resolution, and not the intermediate steps.
4685 // Luckily, we can (at least for now) deduce the intermediate steps
4686 // just from the end-point.
4688 // There are basically three cases to consider:
4690 // 1. Reference to a *type*, such as a struct or enum:
4692 // mod a { struct Foo<T> { ... } }
4694 // Because we don't allow types to be declared within one
4695 // another, a path that leads to a type will always look like
4696 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4697 // that only the final segment can have type parameters, and
4698 // they are located in the TypeSpace.
4700 // *Note:* Generally speaking, references to types don't
4701 // actually pass through this function, but rather the
4702 // `ast_ty_to_ty` function in `astconv`. However, in the case
4703 // of struct patterns (and maybe literals) we do invoke
4704 // `instantiate_path` to get the general type of an instance of
4705 // a struct. (In these cases, there are actually no type
4706 // parameters permitted at present, but perhaps we will allow
4707 // them in the future.)
4709 // 1b. Reference to a enum variant or tuple-like struct:
4711 // struct foo<T>(...)
4712 // enum E<T> { foo(...) }
4714 // In these cases, the parameters are declared in the type
4717 // 2. Reference to a *fn item*:
4721 // In this case, the path will again always have the form
4722 // `a::b::foo::<T>` where only the final segment should have
4723 // type parameters. However, in this case, those parameters are
4724 // declared on a value, and hence are in the `FnSpace`.
4726 // 3. Reference to a *method*:
4728 // impl<A> SomeStruct<A> {
4732 // Here we can have a path like
4733 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4734 // may appear in two places. The penultimate segment,
4735 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4736 // final segment, `foo::<B>` contains parameters in fn space.
4738 // The first step then is to categorize the segments appropriately.
4740 assert!(path.segments.len() >= 1);
4741 let mut segment_spaces: Vec<_>;
4743 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4744 def::DefSelfTy(..) |
4745 def::DefStruct(..) |
4746 def::DefVariant(..) |
4747 def::DefTyParamBinder(..) |
4749 def::DefAssociatedTy(..) |
4750 def::DefAssociatedPath(..) |
4752 def::DefPrimTy(..) |
4753 def::DefTyParam(..) => {
4754 // Everything but the final segment should have no
4755 // parameters at all.
4756 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4757 segment_spaces.push(Some(subst::TypeSpace));
4760 // Case 2. Reference to a top-level value.
4763 def::DefStatic(..) => {
4764 segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
4765 segment_spaces.push(Some(subst::FnSpace));
4768 // Case 3. Reference to a method.
4769 def::DefStaticMethod(_, providence) |
4770 def::DefMethod(_, _, providence) => {
4771 assert!(path.segments.len() >= 2);
4774 def::FromTrait(trait_did) => {
4775 callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
4777 def::FromImpl(_) => {}
4780 segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
4781 segment_spaces.push(Some(subst::TypeSpace));
4782 segment_spaces.push(Some(subst::FnSpace));
4785 // Other cases. Various nonsense that really shouldn't show up
4786 // here. If they do, an error will have been reported
4787 // elsewhere. (I hope)
4789 def::DefForeignMod(..) |
4792 def::DefRegion(..) |
4794 def::DefUpvar(..) => {
4795 segment_spaces = repeat(None).take(path.segments.len()).collect();
4798 assert_eq!(segment_spaces.len(), path.segments.len());
4800 debug!("segment_spaces={:?}", segment_spaces);
4802 // Next, examine the definition, and determine how many type
4803 // parameters we expect from each space.
4804 let type_defs = &type_scheme.generics.types;
4805 let region_defs = &type_scheme.generics.regions;
4807 // Now that we have categorized what space the parameters for each
4808 // segment belong to, let's sort out the parameters that the user
4809 // provided (if any) into their appropriate spaces. We'll also report
4810 // errors if type parameters are provided in an inappropriate place.
4811 let mut substs = Substs::empty();
4812 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4815 report_error_if_segment_contains_type_parameters(fcx, segment);
4819 push_explicit_parameters_from_segment_to_substs(fcx,
4829 if let Some(self_ty) = opt_self_ty {
4830 // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
4831 assert_eq!(type_defs.len(subst::SelfSpace), 1);
4832 substs.types.push(subst::SelfSpace, self_ty);
4835 // Now we have to compare the types that the user *actually*
4836 // provided against the types that were *expected*. If the user
4837 // did not provide any types, then we want to substitute inference
4838 // variables. If the user provided some types, we may still need
4839 // to add defaults. If the user provided *too many* types, that's
4841 for &space in &ParamSpace::all() {
4842 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4843 assert_eq!(substs.types.len(space), type_defs.len(space));
4845 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4846 assert_eq!(substs.regions().len(space), region_defs.len(space));
4849 // The things we are substituting into the type should not contain
4850 // escaping late-bound regions, and nor should the base type scheme.
4851 assert!(!substs.has_regions_escaping_depth(0));
4852 assert!(!type_scheme.has_escaping_regions());
4854 // Add all the obligations that are required, substituting and
4855 // normalized appropriately.
4856 let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
4857 fcx.add_obligations_for_parameters(
4858 traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
4861 // Substitute the values for the type parameters into the type of
4862 // the referenced item.
4863 let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
4865 fcx.write_ty(node_id, ty_substituted);
4866 fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
4869 fn report_error_if_segment_contains_type_parameters(
4871 segment: &ast::PathSegment)
4873 for typ in &segment.parameters.types() {
4874 span_err!(fcx.tcx().sess, typ.span, E0085,
4875 "type parameters may not appear here");
4879 for lifetime in &segment.parameters.lifetimes() {
4880 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4881 "lifetime parameters may not appear here");
4886 /// Finds the parameters that the user provided and adds them to `substs`. If too many
4887 /// parameters are provided, then reports an error and clears the output vector.
4889 /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
4890 /// use inference variables. This seems less likely to lead to derived errors.
4892 /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
4893 /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
4894 /// here because we can easily use the precise span of the N+1'th parameter.
4895 fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
4896 fcx: &FnCtxt<'a, 'tcx>,
4897 space: subst::ParamSpace,
4899 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4900 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4901 segment: &ast::PathSegment,
4902 substs: &mut Substs<'tcx>)
4904 match segment.parameters {
4905 ast::AngleBracketedParameters(ref data) => {
4906 push_explicit_angle_bracketed_parameters_from_segment_to_substs(
4907 fcx, space, type_defs, region_defs, data, substs);
4910 ast::ParenthesizedParameters(ref data) => {
4911 span_err!(fcx.tcx().sess, span, E0238,
4912 "parenthesized parameters may only be used with a trait");
4913 push_explicit_parenthesized_parameters_from_segment_to_substs(
4914 fcx, space, span, type_defs, data, substs);
4919 fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
4920 fcx: &FnCtxt<'a, 'tcx>,
4921 space: subst::ParamSpace,
4922 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4923 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4924 data: &ast::AngleBracketedParameterData,
4925 substs: &mut Substs<'tcx>)
4928 let type_count = type_defs.len(space);
4929 assert_eq!(substs.types.len(space), 0);
4930 for (i, typ) in data.types.iter().enumerate() {
4931 let t = fcx.to_ty(&**typ);
4933 substs.types.push(space, t);
4934 } else if i == type_count {
4935 span_err!(fcx.tcx().sess, typ.span, E0087,
4936 "too many type parameters provided: \
4937 expected at most {} parameter(s), \
4938 found {} parameter(s)",
4939 type_count, data.types.len());
4940 substs.types.truncate(space, 0);
4946 if data.bindings.len() > 0 {
4947 span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
4948 "unexpected binding of associated item in expression path \
4949 (only allowed in type paths)");
4953 let region_count = region_defs.len(space);
4954 assert_eq!(substs.regions().len(space), 0);
4955 for (i, lifetime) in data.lifetimes.iter().enumerate() {
4956 let r = ast_region_to_region(fcx.tcx(), lifetime);
4957 if i < region_count {
4958 substs.mut_regions().push(space, r);
4959 } else if i == region_count {
4960 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4961 "too many lifetime parameters provided: \
4962 expected {} parameter(s), found {} parameter(s)",
4964 data.lifetimes.len());
4965 substs.mut_regions().truncate(space, 0);
4973 /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
4974 /// but intended for `Foo(A,B) -> C` form. This expands to
4975 /// roughly the same thing as `Foo<(A,B),C>`. One important
4976 /// difference has to do with the treatment of anonymous
4977 /// regions, which are translated into bound regions (NYI).
4978 fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
4979 fcx: &FnCtxt<'a, 'tcx>,
4980 space: subst::ParamSpace,
4982 type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
4983 data: &ast::ParenthesizedParameterData,
4984 substs: &mut Substs<'tcx>)
4986 let type_count = type_defs.len(space);
4988 span_err!(fcx.tcx().sess, span, E0167,
4989 "parenthesized form always supplies 2 type parameters, \
4990 but only {} parameter(s) were expected",
4994 let input_tys: Vec<Ty> =
4995 data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
4998 ty::mk_tup(fcx.tcx(), input_tys);
5000 if type_count >= 1 {
5001 substs.types.push(space, tuple_ty);
5004 let output_ty: Option<Ty> =
5005 data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
5008 output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
5010 if type_count >= 2 {
5011 substs.types.push(space, output_ty);
5015 fn adjust_type_parameters<'a, 'tcx>(
5016 fcx: &FnCtxt<'a, 'tcx>,
5019 defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
5020 substs: &mut Substs<'tcx>)
5022 let provided_len = substs.types.len(space);
5023 let desired = defs.get_slice(space);
5024 let required_len = desired.iter()
5025 .take_while(|d| d.default.is_none())
5028 debug!("adjust_type_parameters(space={:?}, \
5037 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5038 assert!(provided_len <= desired.len());
5040 // Nothing specified at all: supply inference variables for
5042 if provided_len == 0 {
5043 substs.types.replace(space,
5044 fcx.infcx().next_ty_vars(desired.len()));
5048 // Too few parameters specified: report an error and use Err
5050 if provided_len < required_len {
5052 if desired.len() != required_len { "at least " } else { "" };
5053 span_err!(fcx.tcx().sess, span, E0089,
5054 "too few type parameters provided: expected {}{} parameter(s) \
5055 , found {} parameter(s)",
5056 qualifier, required_len, provided_len);
5057 substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
5061 // Otherwise, add in any optional parameters that the user
5062 // omitted. The case of *too many* parameters is handled
5064 // push_explicit_parameters_from_segment_to_substs(). Note
5065 // that the *default* type are expressed in terms of all prior
5066 // parameters, so we have to substitute as we go with the
5067 // partial substitution that we have built up.
5068 for i in provided_len..desired.len() {
5069 let default = desired[i].default.unwrap();
5070 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5071 substs.types.push(space, default);
5073 assert_eq!(substs.types.len(space), desired.len());
5075 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5078 fn adjust_region_parameters(
5082 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5083 substs: &mut Substs)
5085 let provided_len = substs.mut_regions().len(space);
5086 let desired = defs.get_slice(space);
5088 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5089 assert!(provided_len <= desired.len());
5091 // If nothing was provided, just use inference variables.
5092 if provided_len == 0 {
5093 substs.mut_regions().replace(
5095 fcx.infcx().region_vars_for_defs(span, desired));
5099 // If just the right number were provided, everybody is happy.
5100 if provided_len == desired.len() {
5104 // Otherwise, too few were provided. Report an error and then
5105 // use inference variables.
5106 span_err!(fcx.tcx().sess, span, E0090,
5107 "too few lifetime parameters provided: expected {} parameter(s), \
5108 found {} parameter(s)",
5109 desired.len(), provided_len);
5111 substs.mut_regions().replace(
5113 fcx.infcx().region_vars_for_defs(span, desired));
5117 // Resolves `typ` by a single level if `typ` is a type variable. If no
5118 // resolution is possible, then an error is reported.
5119 pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5124 let mut ty = fcx.resolve_type_vars_if_possible(ty);
5127 if ty::type_is_ty_var(ty) {
5128 fcx.type_error_message(sp, |_actual| {
5129 "the type of this value must be known in this \
5130 context".to_string()
5132 demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
5133 ty = fcx.tcx().types.err;
5139 // Returns true if b contains a break that can exit from b
5140 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5141 // First: is there an unlabeled break immediately
5143 (loop_query(&*b, |e| {
5145 ast::ExprBreak(_) => true,
5149 // Second: is there a labeled break with label
5150 // <id> nested anywhere inside the loop?
5151 (block_query(b, |e| {
5153 ast::ExprBreak(Some(_)) => {
5154 match cx.def_map.borrow().get(&e.id) {
5155 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5163 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
5165 tps: &OwnedSlice<ast::TyParam>,
5167 debug!("check_bounds_are_used(n_tps={}, ty={})",
5168 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5170 // make a vector of booleans initially false, set to true when used
5171 if tps.len() == 0u { return; }
5172 let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
5174 ty::walk_ty(ty, |t| {
5176 ty::ty_param(ParamTy {idx, ..}) => {
5177 debug!("Found use of ty param num {}", idx);
5178 tps_used[idx as uint] = true;
5184 for (i, b) in tps_used.iter().enumerate() {
5186 span_err!(ccx.tcx.sess, span, E0091,
5187 "type parameter `{}` is unused",
5188 token::get_ident(tps[i].ident));
5193 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5194 fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
5195 let name = token::intern(format!("P{}", n).as_slice());
5196 ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
5200 let name = token::get_ident(it.ident);
5201 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5202 let split : Vec<&str> = name.get().split('_').collect();
5203 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5205 //We only care about the operation here
5206 let (n_tps, inputs, output) = match split[1] {
5207 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5211 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5213 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5216 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5217 "min" | "umax" | "umin" => {
5218 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5222 (0, Vec::new(), ty::mk_nil(tcx))
5225 span_err!(tcx.sess, it.span, E0092,
5226 "unrecognized atomic operation function: `{}`", op);
5230 (n_tps, inputs, ty::FnConverging(output))
5231 } else if name.get() == "abort" || name.get() == "unreachable" {
5232 (0, Vec::new(), ty::FnDiverging)
5234 let (n_tps, inputs, output) = match name.get() {
5235 "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
5237 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
5238 "init" => (1u, Vec::new(), param(ccx, 0)),
5239 "uninit" => (1u, Vec::new(), param(ccx, 0)),
5240 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
5241 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5242 "move_val_init" => {
5245 ty::mk_mut_rptr(tcx,
5246 tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
5253 "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
5254 "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
5257 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5259 Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[]); }
5261 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5263 mutbl: ast::MutImmutable
5265 (1u, Vec::new(), td_ptr)
5267 "type_id" => (1u, Vec::new(), ccx.tcx.types.u64),
5271 ty::mk_ptr(tcx, ty::mt {
5273 mutbl: ast::MutImmutable
5277 ty::mk_ptr(tcx, ty::mt {
5279 mutbl: ast::MutImmutable
5282 "copy_memory" | "copy_nonoverlapping_memory" |
5283 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5286 ty::mk_ptr(tcx, ty::mt {
5288 mutbl: ast::MutMutable
5290 ty::mk_ptr(tcx, ty::mt {
5292 mutbl: ast::MutImmutable
5298 "set_memory" | "volatile_set_memory" => {
5301 ty::mk_ptr(tcx, ty::mt {
5303 mutbl: ast::MutMutable
5310 "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5311 "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5314 vec!( tcx.types.f32, tcx.types.i32 ),
5319 vec!( tcx.types.f64, tcx.types.i32 ),
5322 "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5323 "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5324 "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5325 "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5328 vec!( tcx.types.f32, tcx.types.f32 ),
5333 vec!( tcx.types.f64, tcx.types.f64 ),
5336 "expf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5337 "expf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5338 "exp2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5339 "exp2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5340 "logf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5341 "logf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5342 "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5343 "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5344 "log2f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5345 "log2f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5348 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
5353 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
5356 "fabsf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5357 "fabsf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5358 "copysignf32" => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
5359 "copysignf64" => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
5360 "floorf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5361 "floorf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5362 "ceilf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5363 "ceilf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5364 "truncf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5365 "truncf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5366 "rintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5367 "rintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5368 "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5369 "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5370 "roundf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
5371 "roundf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
5372 "ctpop8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5373 "ctpop16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5374 "ctpop32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5375 "ctpop64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5376 "ctlz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5377 "ctlz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5378 "ctlz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5379 "ctlz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5380 "cttz8" => (0, vec!( tcx.types.u8 ), tcx.types.u8),
5381 "cttz16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5382 "cttz32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5383 "cttz64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5384 "bswap16" => (0, vec!( tcx.types.u16 ), tcx.types.u16),
5385 "bswap32" => (0, vec!( tcx.types.u32 ), tcx.types.u32),
5386 "bswap64" => (0, vec!( tcx.types.u64 ), tcx.types.u64),
5389 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5391 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
5393 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5394 (0, vec!(tcx.types.i8, tcx.types.i8),
5395 ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
5397 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5398 (0, vec!(tcx.types.i16, tcx.types.i16),
5399 ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
5401 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5402 (0, vec!(tcx.types.i32, tcx.types.i32),
5403 ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
5405 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5406 (0, vec!(tcx.types.i64, tcx.types.i64),
5407 ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
5409 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5410 (0, vec!(tcx.types.u8, tcx.types.u8),
5411 ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
5413 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5414 (0, vec!(tcx.types.u16, tcx.types.u16),
5415 ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
5417 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5418 (0, vec!(tcx.types.u32, tcx.types.u32),
5419 ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
5421 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5422 (0, vec!(tcx.types.u64, tcx.types.u64),
5423 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
5425 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
5427 "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
5430 span_err!(tcx.sess, it.span, E0093,
5431 "unrecognized intrinsic function: `{}`", *other);
5435 (n_tps, inputs, ty::FnConverging(output))
5437 let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
5438 unsafety: ast::Unsafety::Unsafe,
5439 abi: abi::RustIntrinsic,
5440 sig: ty::Binder(FnSig {
5446 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5447 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5448 if i_n_tps != n_tps {
5449 span_err!(tcx.sess, it.span, E0094,
5450 "intrinsic has wrong number of type \
5451 parameters: found {}, expected {}",
5454 require_same_types(tcx,
5461 format!("intrinsic has wrong type: expected `{}`",
5462 ppaux::ty_to_string(ccx.tcx, fty))