1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Within the check phase of type check, we check each item one at a time
16 (bodies of function expressions are checked as part of the containing
17 function). Inference is used to supply types wherever they are
20 By far the most complex case is checking the body of a function. This
21 can be broken down into several distinct phases:
23 - gather: creates type variables to represent the type of each local
24 variable and pattern binding.
26 - main: the main pass does the lion's share of the work: it
27 determines the types of all expressions, resolves
28 methods, checks for most invalid conditions, and so forth. In
29 some cases, where a type is unknown, it may create a type or region
30 variable and use that as the type of an expression.
32 In the process of checking, various constraints will be placed on
33 these type variables through the subtyping relationships requested
34 through the `demand` module. The `typeck::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
80 use middle::const_eval;
83 use middle::lang_items::IteratorItem;
84 use middle::mem_categorization::McResult;
85 use middle::mem_categorization;
86 use middle::pat_util::pat_id_map;
89 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
91 use middle::ty::{FnSig, VariantInfo};
92 use middle::ty::{Polytype};
93 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
95 use middle::ty_fold::TypeFolder;
96 use middle::typeck::astconv::AstConv;
97 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
98 use middle::typeck::astconv;
99 use middle::typeck::check::_match::pat_ctxt;
100 use middle::typeck::check::method::{AutoderefReceiver};
101 use middle::typeck::check::method::{AutoderefReceiverFlag};
102 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
103 use middle::typeck::check::method::{DontAutoderefReceiver};
104 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
105 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
106 use middle::typeck::CrateCtxt;
107 use middle::typeck::infer::{resolve_type, force_tvar};
108 use middle::typeck::infer;
109 use middle::typeck::rscope::RegionScope;
110 use middle::typeck::{lookup_def_ccx};
111 use middle::typeck::no_params;
112 use middle::typeck::{require_same_types};
113 use middle::typeck::{MethodCall, MethodMap, ObjectCastMap};
114 use middle::typeck::{TypeAndSubsts};
116 use middle::lang_items::TypeIdLangItem;
118 use util::common::{block_query, indenter, loop_query};
120 use util::ppaux::{UserString, Repr};
121 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
123 use std::cell::{Cell, RefCell};
124 use std::collections::HashMap;
125 use std::mem::replace;
129 use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
132 use syntax::ast_util::{local_def, PostExpansionMethod};
133 use syntax::ast_util;
135 use syntax::codemap::Span;
137 use syntax::owned_slice::OwnedSlice;
138 use syntax::parse::token;
139 use syntax::print::pprust;
142 use syntax::visit::Visitor;
146 pub mod vtable2; // New trait code
154 /// Fields that are part of a `FnCtxt` which are inherited by
155 /// closures defined within the function. For example:
158 /// bar(proc() { ... })
161 /// Here, the function `foo()` and the closure passed to
162 /// `bar()` will each have their own `FnCtxt`, but they will
163 /// share the inherited fields.
164 pub struct Inherited<'a, 'tcx: 'a> {
165 infcx: infer::InferCtxt<'a, 'tcx>,
166 locals: RefCell<NodeMap<ty::t>>,
167 param_env: ty::ParameterEnvironment,
170 node_types: RefCell<NodeMap<ty::t>>,
171 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
172 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
173 method_map: MethodMap,
174 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
175 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
176 object_cast_map: ObjectCastMap,
178 // A mapping from each fn's id to its signature, with all bound
179 // regions replaced with free ones. Unlike the other tables, this
180 // one is never copied into the tcx: it is only used by regionck.
181 fn_sig_map: RefCell<NodeMap<Vec<ty::t>>>,
183 // A set of constraints that regionck must validate. Each
184 // constraint has the form `T:'a`, meaning "some type `T` must
185 // outlive the lifetime 'a". These constraints derive from
186 // instantiated type parameters. So if you had a struct defined
189 // struct Foo<T:'static> { ... }
191 // then in some expression `let x = Foo { ... }` it will
192 // instantiate the type parameter `T` with a fresh type `$0`. At
193 // the same time, it will record a region obligation of
194 // `$0:'static`. This will get checked later by regionck. (We
195 // can't generally check these things right away because we have
196 // to wait until types are resolved.)
198 // These are stored in a map keyed to the id of the innermost
199 // enclosing fn body / static initializer expression. This is
200 // because the location where the obligation was incurred can be
201 // relevant with respect to which sublifetime assumptions are in
202 // place. The reason that we store under the fn-id, and not
203 // something more fine-grained, is so that it is easier for
204 // regionck to be sure that it has found *all* the region
205 // obligations (otherwise, it's easy to fail to walk to a
206 // particular node-id).
207 region_obligations: RefCell<NodeMap<Vec<RegionObligation>>>,
209 // Tracks trait obligations incurred during this function body.
210 fulfillment_cx: RefCell<traits::FulfillmentContext>,
213 struct RegionObligation {
214 sub_region: ty::Region,
216 origin: infer::SubregionOrigin,
219 /// When type-checking an expression, we propagate downward
220 /// whatever type hint we are able in the form of an `Expectation`.
222 /// We know nothing about what type this expression should have.
225 /// This expression should have the type given (or some subtype)
226 ExpectHasType(ty::t),
228 /// This expression will be cast to the `ty::t`
229 ExpectCastableToType(ty::t),
233 pub struct FnStyleState {
234 pub def: ast::NodeId,
235 pub fn_style: ast::FnStyle,
240 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
241 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
244 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
245 match self.fn_style {
246 // If this unsafe, then if the outer function was already marked as
247 // unsafe we shouldn't attribute the unsafe'ness to the block. This
248 // way the block can be warned about instead of ignoring this
249 // extraneous block (functions are never warned about).
250 ast::UnsafeFn if self.from_fn => *self,
253 let (fn_style, def) = match blk.rules {
254 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
255 ast::DefaultBlock => (fn_style, self.def),
257 FnStyleState{ def: def,
265 /// Whether `check_binop` is part of an assignment or not.
266 /// Used to know whether we allow user overloads and to print
267 /// better messages on error.
268 #[deriving(PartialEq)]
269 enum IsBinopAssignment{
275 pub struct FnCtxt<'a, 'tcx: 'a> {
276 body_id: ast::NodeId,
278 // This flag is set to true if, during the writeback phase, we encounter
279 // a type error in this function.
280 writeback_errors: Cell<bool>,
282 // Number of errors that had been reported when we started
283 // checking this function. On exit, if we find that *more* errors
284 // have been reported, we will skip regionck and other work that
285 // expects the types within the function to be consistent.
286 err_count_on_creation: uint,
290 ps: RefCell<FnStyleState>,
292 inh: &'a Inherited<'a, 'tcx>,
294 ccx: &'a CrateCtxt<'a, 'tcx>,
297 impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
298 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
301 fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
302 self.ccx.tcx.node_ty(id)
304 fn node_method_ty(&self, method_call: typeck::MethodCall)
306 self.ccx.tcx.node_method_ty(method_call)
308 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
309 self.ccx.tcx.adjustments()
311 fn is_method_call(&self, id: ast::NodeId) -> bool {
312 self.ccx.tcx.is_method_call(id)
314 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
315 self.ccx.tcx.temporary_scope(rvalue_id)
317 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
318 self.ccx.tcx.upvar_borrow(upvar_id)
320 fn capture_mode(&self, closure_expr_id: ast::NodeId)
321 -> freevars::CaptureMode {
322 self.ccx.tcx.capture_mode(closure_expr_id)
324 fn unboxed_closures<'a>(&'a self)
325 -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
326 &self.inh.unboxed_closures
330 impl<'a, 'tcx> Inherited<'a, 'tcx> {
331 fn new(tcx: &'a ty::ctxt<'tcx>,
332 param_env: ty::ParameterEnvironment)
333 -> Inherited<'a, 'tcx> {
335 infcx: infer::new_infer_ctxt(tcx),
336 locals: RefCell::new(NodeMap::new()),
337 param_env: param_env,
338 node_types: RefCell::new(NodeMap::new()),
339 item_substs: RefCell::new(NodeMap::new()),
340 adjustments: RefCell::new(NodeMap::new()),
341 method_map: RefCell::new(FnvHashMap::new()),
342 object_cast_map: RefCell::new(NodeMap::new()),
343 upvar_borrow_map: RefCell::new(HashMap::new()),
344 unboxed_closures: RefCell::new(DefIdMap::new()),
345 fn_sig_map: RefCell::new(NodeMap::new()),
346 region_obligations: RefCell::new(NodeMap::new()),
347 fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
352 // Used by check_const and check_enum_variants
353 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
354 inh: &'a Inherited<'a, 'tcx>,
356 body_id: ast::NodeId)
357 -> FnCtxt<'a, 'tcx> {
360 writeback_errors: Cell::new(false),
361 err_count_on_creation: ccx.tcx.sess.err_count(),
363 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
369 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
370 -> Inherited<'a, 'tcx> {
371 // It's kind of a kludge to manufacture a fake function context
372 // and statement context, but we might as well do write the code only once
373 let param_env = ty::ParameterEnvironment {
374 free_substs: subst::Substs::empty(),
375 bounds: subst::VecPerParamSpace::empty(),
376 implicit_region_bound: ty::ReStatic,
377 caller_obligations: subst::VecPerParamSpace::empty(),
379 Inherited::new(ccx.tcx, param_env)
382 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
384 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
385 fn visit_item(&mut self, i: &ast::Item) {
386 check_item(self.ccx, i);
387 visit::walk_item(self, i);
391 struct CheckItemSizedTypesVisitor<'a, 'tcx: 'a> {
392 ccx: &'a CrateCtxt<'a, 'tcx>
395 impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemSizedTypesVisitor<'a, 'tcx> {
396 fn visit_item(&mut self, i: &ast::Item) {
397 check_item_sized(self.ccx, i);
398 visit::walk_item(self, i);
402 pub fn check_item_types(ccx: &CrateCtxt) {
403 let krate = ccx.tcx.map.krate();
404 let mut visit = wf::CheckTypeWellFormedVisitor::new(ccx);
405 visit::walk_crate(&mut visit, krate);
407 // If types are not well-formed, it leads to all manner of errors
408 // downstream, so stop reporting errors at this point.
409 ccx.tcx.sess.abort_if_errors();
411 let mut visit = CheckItemTypesVisitor { ccx: ccx };
412 visit::walk_crate(&mut visit, krate);
414 ccx.tcx.sess.abort_if_errors();
416 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
417 visit::walk_crate(&mut visit, krate);
420 fn check_bare_fn(ccx: &CrateCtxt,
425 param_env: ty::ParameterEnvironment) {
426 // Compute the fty from point of view of inside fn
427 // (replace any type-scheme with a type)
428 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
430 match ty::get(fty).sty {
431 ty::ty_bare_fn(ref fn_ty) => {
432 let inh = Inherited::new(ccx.tcx, param_env);
433 let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
434 decl, id, body, &inh);
436 vtable2::select_all_fcx_obligations_or_error(&fcx);
437 regionck::regionck_fn(&fcx, id, body);
438 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
439 vtable2::check_builtin_bound_obligations(&fcx); // must happen after writeback
441 _ => ccx.tcx.sess.impossible_case(body.span,
442 "check_bare_fn: function type expected")
446 struct GatherLocalsVisitor<'a, 'tcx: 'a> {
447 fcx: &'a FnCtxt<'a, 'tcx>
450 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
451 fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<ty::t>) -> ty::t {
454 // infer the variable's type
455 let var_id = self.fcx.infcx().next_ty_var_id();
456 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
457 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
461 // take type that the user specified
462 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
469 impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
470 // Add explicitly-declared locals.
471 fn visit_local(&mut self, local: &ast::Local) {
472 let o_ty = match local.ty.node {
473 ast::TyInfer => None,
474 _ => Some(self.fcx.to_ty(&*local.ty))
476 self.assign(local.span, local.id, o_ty);
477 debug!("Local variable {} is assigned type {}",
478 self.fcx.pat_to_string(&*local.pat),
479 self.fcx.infcx().ty_to_string(
480 self.fcx.inh.locals.borrow().get_copy(&local.id)));
481 visit::walk_local(self, local);
484 // Add pattern bindings.
485 fn visit_pat(&mut self, p: &ast::Pat) {
487 ast::PatIdent(_, ref path1, _)
488 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
489 let var_ty = self.assign(p.span, p.id, None);
491 self.fcx.require_type_is_sized(var_ty, p.span,
492 traits::VariableType(p.id));
494 debug!("Pattern binding {} is assigned to {} with type {}",
495 token::get_ident(path1.node),
496 self.fcx.infcx().ty_to_string(
497 self.fcx.inh.locals.borrow().get_copy(&p.id)),
498 var_ty.repr(self.fcx.tcx()));
502 visit::walk_pat(self, p);
505 fn visit_block(&mut self, b: &ast::Block) {
506 // non-obvious: the `blk` variable maps to region lb, so
507 // we have to keep this up-to-date. This
508 // is... unfortunate. It'd be nice to not need this.
509 visit::walk_block(self, b);
512 // Since an expr occurs as part of the type fixed size arrays we
513 // need to record the type for that node
514 fn visit_ty(&mut self, t: &ast::Ty) {
516 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
517 self.visit_ty(&**ty);
518 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
520 _ => visit::walk_ty(self, t)
524 // Don't descend into fns and items
525 fn visit_fn(&mut self, _: visit::FnKind<'v>, _: &'v ast::FnDecl,
526 _: &'v ast::Block, _: Span, _: ast::NodeId) { }
527 fn visit_item(&mut self, _: &ast::Item) { }
531 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
532 fn_style: ast::FnStyle,
533 fn_style_id: ast::NodeId,
538 inherited: &'a Inherited<'a, 'tcx>)
539 -> FnCtxt<'a, 'tcx> {
541 * Helper used by check_bare_fn and check_expr_fn. Does the
542 * grungy work of checking a function body and returns the
543 * function context used for that purpose, since in the case of a
544 * fn item there is still a bit more to do.
547 * - inherited: other fields inherited from the enclosing fn (if any)
551 let err_count_on_creation = tcx.sess.err_count();
553 // First, we have to replace any bound regions in the fn type with free ones.
554 // The free region references will be bound the node_id of the body block.
555 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
556 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
559 let arg_tys = fn_sig.inputs.as_slice();
560 let ret_ty = fn_sig.output;
562 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
567 // Create the function context. This is either derived from scratch or,
568 // in the case of function expressions, based on the outer context.
571 writeback_errors: Cell::new(false),
572 err_count_on_creation: err_count_on_creation,
574 ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)),
579 // Remember return type so that regionck can access it later.
580 let fn_sig_tys: Vec<ty::t> =
582 .chain([ret_ty].iter())
585 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
587 fn_sig_tys.repr(tcx));
590 .insert(fn_id, fn_sig_tys);
593 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
595 // Add formal parameters.
596 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
597 // Create type variables for each argument.
598 pat_util::pat_bindings(
601 |_bm, pat_id, sp, _path| {
602 let var_ty = visit.assign(sp, pat_id, None);
603 fcx.require_type_is_sized(var_ty, sp,
604 traits::VariableType(pat_id));
607 // Check the pattern.
610 map: pat_id_map(&tcx.def_map, &*input.pat),
612 _match::check_pat(&pcx, &*input.pat, *arg_ty);
615 visit.visit_block(body);
618 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
620 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
621 fcx.write_ty(input.id, *arg);
627 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
628 assert!(field.id.krate == ast::LOCAL_CRATE);
629 let item = match tcx.map.find(struct_id.node) {
630 Some(ast_map::NodeItem(item)) => item,
631 None => fail!("node not in ast map: {}", struct_id.node),
632 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
636 ast::ItemStruct(ref struct_def, _) => {
637 match struct_def.fields.iter().find(|f| match f.node.kind {
638 ast::NamedField(ident, _) => ident.name == field.name,
644 .bug(format!("Could not find field {}",
645 token::get_name(field.name)).as_slice())
649 _ => tcx.sess.bug("Field found outside of a struct?"),
653 // Check struct fields are uniquely named wrt parents.
654 fn check_for_field_shadowing(tcx: &ty::ctxt,
656 let struct_fields = tcx.struct_fields.borrow();
657 let fields = struct_fields.get(&id);
659 let superstructs = tcx.superstructs.borrow();
660 let super_struct = superstructs.get(&id);
661 match *super_struct {
663 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
664 for f in fields.iter() {
665 match super_fields.iter().find(|sf| f.name == sf.name) {
666 Some(prev_field) => {
667 span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
668 "field `{}` hides field declared in super-struct",
669 token::get_name(f.name));
670 span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
671 "previously declared here");
681 fn check_fields_sized(tcx: &ty::ctxt,
682 struct_def: &ast::StructDef) {
683 let len = struct_def.fields.len();
687 for f in struct_def.fields.slice_to(len - 1).iter() {
688 let t = ty::node_id_to_type(tcx, f.node.id);
689 if !ty::type_is_sized(tcx, t) {
691 ast::NamedField(ident, _) => {
692 span_err!(tcx.sess, f.span, E0042,
693 "type `{}` is dynamically sized. \
694 dynamically sized types may only \
695 appear as the type of the final \
697 token::get_ident(ident));
699 ast::UnnamedField(_) => {
700 span_err!(tcx.sess, f.span, E0043,
701 "dynamically sized type in field");
708 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
711 check_representable(tcx, span, id, "struct");
712 check_instantiable(tcx, span, id);
714 // Check there are no overlapping fields in super-structs
715 check_for_field_shadowing(tcx, local_def(id));
717 if ty::lookup_simd(tcx, local_def(id)) {
718 check_simd(tcx, span, id);
722 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
723 debug!("check_item(it.id={}, it.ident={})",
725 ty::item_path_str(ccx.tcx, local_def(it.id)));
726 let _indenter = indenter();
729 ast::ItemEnum(ref enum_definition, _) => {
730 check_enum_variants_sized(ccx,
731 enum_definition.variants.as_slice());
733 ast::ItemStruct(..) => {
734 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
740 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
741 debug!("check_item(it.id={}, it.ident={})",
743 ty::item_path_str(ccx.tcx, local_def(it.id)));
744 let _indenter = indenter();
747 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
748 ast::ItemEnum(ref enum_definition, _) => {
749 check_enum_variants(ccx,
751 enum_definition.variants.as_slice(),
754 ast::ItemFn(ref decl, _, _, _, ref body) => {
755 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
756 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
757 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
759 ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
760 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
762 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
763 for impl_item in impl_items.iter() {
765 ast::MethodImplItem(ref m) => {
766 check_method_body(ccx, &impl_pty.generics, &**m);
768 ast::TypeImplItem(_) => {
769 // Nothing to do here.
774 match *opt_trait_ref {
775 Some(ref ast_trait_ref) => {
777 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
778 check_impl_items_against_trait(ccx,
782 impl_items.as_slice());
788 ast::ItemTrait(_, _, _, ref trait_methods) => {
789 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
790 for trait_method in trait_methods.iter() {
791 match *trait_method {
792 RequiredMethod(..) => {
793 // Nothing to do, since required methods don't have
796 ProvidedMethod(ref m) => {
797 check_method_body(ccx, &trait_def.generics, &**m);
799 TypeTraitItem(_) => {
805 ast::ItemStruct(..) => {
806 check_struct(ccx, it.id, it.span);
808 ast::ItemTy(ref t, ref generics) => {
809 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
810 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
812 ast::ItemForeignMod(ref m) => {
813 if m.abi == abi::RustIntrinsic {
814 for item in m.items.iter() {
815 check_intrinsic_type(ccx, &**item);
818 for item in m.items.iter() {
819 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
820 if !pty.generics.types.is_empty() {
821 span_err!(ccx.tcx.sess, item.span, E0044,
822 "foreign items may not have type parameters");
826 ast::ForeignItemFn(ref fn_decl, _) => {
827 if fn_decl.variadic && m.abi != abi::C {
828 span_err!(ccx.tcx.sess, item.span, E0045,
829 "variadic function must have C calling convention");
837 _ => {/* nothing to do */ }
841 fn check_method_body(ccx: &CrateCtxt,
842 item_generics: &ty::Generics,
843 method: &ast::Method) {
845 * Type checks a method body.
848 * - `item_generics`: generics defined on the impl/trait that contains
850 * - `self_bound`: bound for the `Self` type parameter, if any
851 * - `method`: the method definition
854 debug!("check_method_body(item_generics={}, method.id={})",
855 item_generics.repr(ccx.tcx),
857 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
859 let fty = ty::node_id_to_type(ccx.tcx, method.id);
862 &*method.pe_fn_decl(),
869 fn check_impl_items_against_trait(ccx: &CrateCtxt,
871 ast_trait_ref: &ast::TraitRef,
872 impl_trait_ref: &ty::TraitRef,
873 impl_items: &[ast::ImplItem]) {
874 // Locate trait methods
876 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
878 // Check existing impl methods to see if they are both present in trait
879 // and compatible with trait signature
880 for impl_item in impl_items.iter() {
882 ast::MethodImplItem(ref impl_method) => {
883 let impl_method_def_id = local_def(impl_method.id);
884 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
887 // If this is an impl of a trait method, find the
888 // corresponding method definition in the trait.
889 let opt_trait_method_ty =
892 ti.ident().name == impl_item_ty.ident()
895 match opt_trait_method_ty {
896 Some(trait_method_ty) => {
897 match (trait_method_ty, &impl_item_ty) {
898 (&ty::MethodTraitItem(ref trait_method_ty),
899 &ty::MethodTraitItem(ref impl_method_ty)) => {
900 compare_impl_method(ccx.tcx,
903 impl_method.pe_body().id,
905 &impl_trait_ref.substs);
908 // This is span_bug as it should have already been
909 // caught in resolve.
911 .span_bug(impl_method.span,
912 format!("item `{}` is of a \
913 different kind from \
916 impl_item_ty.ident()),
917 pprust::path_to_string(
918 &ast_trait_ref.path))
924 // This is span_bug as it should have already been
925 // caught in resolve.
929 "method `{}` is not a member of trait `{}`",
930 token::get_ident(impl_item_ty.ident()),
931 pprust::path_to_string(
932 &ast_trait_ref.path)).as_slice());
936 ast::TypeImplItem(ref typedef) => {
937 let typedef_def_id = local_def(typedef.id);
938 let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
941 // If this is an impl of an associated type, find the
942 // corresponding type definition in the trait.
943 let opt_associated_type =
946 ti.ident().name == typedef_ty.ident().name
948 match opt_associated_type {
949 Some(associated_type) => {
950 match (associated_type, &typedef_ty) {
951 (&ty::TypeTraitItem(_),
952 &ty::TypeTraitItem(_)) => {}
954 // This is `span_bug` as it should have
955 // already been caught in resolve.
957 .span_bug(typedef.span,
958 format!("item `{}` is of a \
959 different kind from \
963 pprust::path_to_string(
964 &ast_trait_ref.path))
970 // This is `span_bug` as it should have already been
971 // caught in resolve.
975 "associated type `{}` is not a member of \
977 token::get_ident(typedef_ty.ident()),
978 pprust::path_to_string(
979 &ast_trait_ref.path)).as_slice());
986 // Check for missing items from trait
987 let provided_methods = ty::provided_trait_methods(tcx,
988 impl_trait_ref.def_id);
989 let mut missing_methods = Vec::new();
990 for trait_item in trait_items.iter() {
992 ty::MethodTraitItem(ref trait_method) => {
994 impl_items.iter().any(|ii| {
996 ast::MethodImplItem(ref m) => {
997 m.pe_ident().name == trait_method.ident.name
999 ast::TypeImplItem(_) => false,
1003 provided_methods.iter().any(
1004 |m| m.ident.name == trait_method.ident.name);
1005 if !is_implemented && !is_provided {
1006 missing_methods.push(
1008 token::get_ident(trait_method.ident)));
1011 ty::TypeTraitItem(ref associated_type) => {
1012 let is_implemented = impl_items.iter().any(|ii| {
1014 ast::TypeImplItem(ref typedef) => {
1015 typedef.ident.name == associated_type.ident.name
1017 ast::MethodImplItem(_) => false,
1020 if !is_implemented {
1021 missing_methods.push(
1023 token::get_ident(associated_type.ident)));
1029 if !missing_methods.is_empty() {
1030 span_err!(tcx.sess, impl_span, E0046,
1031 "not all trait items implemented, missing: {}",
1032 missing_methods.connect(", "));
1037 * Checks that a method from an impl conforms to the signature of
1038 * the same method as declared in the trait.
1042 * - impl_generics: the generics declared on the impl itself (not the method!)
1043 * - impl_m: type of the method we are checking
1044 * - impl_m_span: span to use for reporting errors
1045 * - impl_m_body_id: id of the method body
1046 * - trait_m: the method in the trait
1047 * - trait_to_impl_substs: the substitutions used on the type of the trait
1049 fn compare_impl_method(tcx: &ty::ctxt,
1050 impl_m: &ty::Method,
1052 impl_m_body_id: ast::NodeId,
1053 trait_m: &ty::Method,
1054 trait_to_impl_substs: &subst::Substs) {
1055 debug!("compare_impl_method(trait_to_impl_substs={})",
1056 trait_to_impl_substs.repr(tcx));
1057 let infcx = infer::new_infer_ctxt(tcx);
1059 // Try to give more informative error messages about self typing
1060 // mismatches. Note that any mismatch will also be detected
1061 // below, where we construct a canonical function type that
1062 // includes the self parameter as a normal parameter. It's just
1063 // that the error messages you get out of this code are a bit more
1064 // inscrutable, particularly for cases where one method has no
1066 match (&trait_m.explicit_self, &impl_m.explicit_self) {
1067 (&ty::StaticExplicitSelfCategory,
1068 &ty::StaticExplicitSelfCategory) => {}
1069 (&ty::StaticExplicitSelfCategory, _) => {
1072 format!("method `{}` has a `{}` declaration in the impl, \
1073 but not in the trait",
1074 token::get_ident(trait_m.ident),
1075 ppaux::explicit_self_category_to_str(
1076 &impl_m.explicit_self)).as_slice());
1079 (_, &ty::StaticExplicitSelfCategory) => {
1082 format!("method `{}` has a `{}` declaration in the trait, \
1083 but not in the impl",
1084 token::get_ident(trait_m.ident),
1085 ppaux::explicit_self_category_to_str(
1086 &trait_m.explicit_self)).as_slice());
1090 // Let the type checker catch other errors below
1094 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
1095 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
1096 if num_impl_m_type_params != num_trait_m_type_params {
1097 span_err!(tcx.sess, impl_m_span, E0049,
1098 "method `{}` has {} type parameter{} \
1099 but its trait declaration has {} type parameter{}",
1100 token::get_ident(trait_m.ident),
1101 num_impl_m_type_params,
1102 if num_impl_m_type_params == 1 {""} else {"s"},
1103 num_trait_m_type_params,
1104 if num_trait_m_type_params == 1 {""} else {"s"});
1108 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
1109 span_err!(tcx.sess, impl_m_span, E0050,
1110 "method `{}` has {} parameter{} \
1111 but the declaration in trait `{}` has {}",
1112 token::get_ident(trait_m.ident),
1113 impl_m.fty.sig.inputs.len(),
1114 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
1115 ty::item_path_str(tcx, trait_m.def_id),
1116 trait_m.fty.sig.inputs.len());
1120 // This code is best explained by example. Consider a trait:
1123 // fn method<'a,M>(t: T, m: &'a M) -> Self;
1128 // impl<'i, U> Trait<&'i U> for Foo {
1129 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
1132 // We wish to decide if those two method types are compatible.
1134 // We start out with trait_to_impl_substs, that maps the trait type
1135 // parameters to impl type parameters:
1137 // trait_to_impl_substs = {T => &'i U, Self => Foo}
1139 // We create a mapping `dummy_substs` that maps from the impl type
1140 // parameters to fresh types and regions. For type parameters,
1141 // this is the identity transform, but we could as well use any
1142 // skolemized types. For regions, we convert from bound to free
1143 // regions (Note: but only early-bound regions, i.e., those
1144 // declared on the impl or used in type parameter bounds).
1146 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1148 // Now we can apply skol_substs to the type of the impl method
1149 // to yield a new function type in terms of our fresh, skolemized
1152 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1154 // We now want to extract and substitute the type of the *trait*
1155 // method and compare it. To do so, we must create a compound
1156 // substitution by combining trait_to_impl_substs and
1157 // impl_to_skol_substs, and also adding a mapping for the method
1158 // type parameters. We extend the mapping to also include
1159 // the method parameters.
1161 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1163 // Applying this to the trait method type yields:
1165 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1167 // This type is also the same but the name of the bound region ('a
1168 // vs 'b). However, the normal subtyping rules on fn types handle
1169 // this kind of equivalency just fine.
1171 // Create mapping from impl to skolemized.
1173 impl_m.generics.types.map(
1174 |d| ty::mk_param_from_def(tcx, d));
1176 impl_m.generics.regions.map(
1177 |l| ty::free_region_from_def(impl_m_body_id, l));
1178 let impl_to_skol_substs =
1179 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1181 // Create mapping from trait to skolemized.
1182 let trait_to_skol_substs =
1183 trait_to_impl_substs
1184 .subst(tcx, &impl_to_skol_substs)
1185 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
1186 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
1188 // Check region bounds.
1189 if !check_region_bounds_on_impl_method(tcx,
1194 &trait_to_skol_substs,
1195 &impl_to_skol_substs) {
1200 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
1201 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
1202 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1203 // Check that the impl does not require any builtin-bounds
1204 // that the trait does not guarantee:
1206 impl_param_def.bounds.builtin_bounds -
1207 trait_param_def.bounds.builtin_bounds;
1208 if !extra_bounds.is_empty() {
1209 span_err!(tcx.sess, impl_m_span, E0051,
1210 "in method `{}`, type parameter {} requires `{}`, \
1211 which is not required by the corresponding type parameter \
1212 in the trait declaration",
1213 token::get_ident(trait_m.ident),
1215 extra_bounds.user_string(tcx));
1219 // Check that the trait bounds of the trait imply the bounds of its
1222 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1223 // traits, but I doubt that'll be wanted often, so meh.
1224 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1225 debug!("compare_impl_method(): impl-trait-bound subst");
1226 let impl_trait_bound =
1227 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1230 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1231 debug!("compare_impl_method(): trait-bound subst");
1233 trait_bound.subst(tcx, &trait_to_skol_substs);
1234 let infcx = infer::new_infer_ctxt(tcx);
1235 match infer::mk_sub_trait_refs(&infcx,
1237 infer::Misc(impl_m_span),
1239 impl_trait_bound.clone()) {
1249 span_err!(tcx.sess, impl_m_span, E0052,
1250 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1251 required by the corresponding type parameter in the trait declaration",
1252 token::get_ident(trait_m.ident),
1254 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1259 // Compute skolemized form of impl and trait method tys.
1260 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1261 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1262 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1263 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1265 // Check the impl method type IM is a subtype of the trait method
1266 // type TM. To see why this makes sense, think of a vtable. The
1267 // expected type of the function pointers in the vtable is the
1268 // type TM of the trait method. The actual type will be the type
1269 // IM of the impl method. Because we know that IM <: TM, that
1270 // means that anywhere a TM is expected, a IM will do instead. In
1271 // other words, anyone expecting to call a method with the type
1272 // from the trait, can safely call a method with the type from the
1274 debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
1276 trait_fty.repr(tcx));
1277 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1278 impl_fty, trait_fty) {
1281 span_err!(tcx.sess, impl_m_span, E0053,
1282 "method `{}` has an incompatible type for trait: {}",
1283 token::get_ident(trait_m.ident),
1284 ty::type_err_to_str(tcx, terr));
1285 ty::note_and_explain_type_err(tcx, terr);
1289 // Finally, resolve all regions. This catches wily misuses of lifetime
1291 infcx.resolve_regions_and_report_errors();
1293 fn check_region_bounds_on_impl_method(tcx: &ty::ctxt,
1295 impl_m: &ty::Method,
1296 trait_generics: &ty::Generics,
1297 impl_generics: &ty::Generics,
1298 trait_to_skol_substs: &Substs,
1299 impl_to_skol_substs: &Substs)
1304 Check that region bounds on impl method are the same as those
1305 on the trait. In principle, it could be ok for there to be
1306 fewer region bounds on the impl method, but this leads to an
1307 annoying corner case that is painful to handle (described
1308 below), so for now we can just forbid it.
1311 `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1315 fn method2<'b:'a>();
1318 impl<'a> Foo<'a> for ... {
1319 fn method1<'b:'a>() { .. case 1, definitely bad .. }
1320 fn method2<'b>() { .. case 2, could be ok .. }
1323 The "definitely bad" case is case #1. Here, the impl adds an
1324 extra constraint not present in the trait.
1326 The "maybe bad" case is case #2. Here, the impl adds an extra
1327 constraint not present in the trait. We could in principle
1328 allow this, but it interacts in a complex way with early/late
1329 bound resolution of lifetimes. Basically the presence or
1330 absence of a lifetime bound affects whether the lifetime is
1331 early/late bound, and right now the code breaks if the trait
1332 has an early bound lifetime parameter and the method does not.
1336 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1337 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1339 debug!("check_region_bounds_on_impl_method: \
1342 trait_generics.repr(tcx),
1343 impl_generics.repr(tcx));
1345 // Must have same number of early-bound lifetime parameters.
1346 // Unfortunately, if the user screws up the bounds, then this
1347 // will change classification between early and late. E.g.,
1348 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1349 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1350 // in trait but 0 in the impl. But if we report "expected 2
1351 // but found 0" it's confusing, because it looks like there
1352 // are zero. Since I don't quite know how to phrase things at
1353 // the moment, give a kind of vague error message.
1354 if trait_params.len() != impl_params.len() {
1357 format!("lifetime parameters or bounds on method `{}` do \
1358 not match the trait declaration",
1359 token::get_ident(impl_m.ident)).as_slice());
1363 // Each parameter `'a:'b+'c+'d` in trait should have the same
1364 // set of bounds in the impl, after subst.
1365 for (trait_param, impl_param) in
1366 trait_params.iter().zip(
1370 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1372 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1374 debug!("check_region_bounds_on_impl_method: \
1379 trait_param.repr(tcx),
1380 impl_param.repr(tcx),
1381 trait_bounds.repr(tcx),
1382 impl_bounds.repr(tcx));
1384 // Collect the set of bounds present in trait but not in
1386 let missing: Vec<ty::Region> =
1388 .filter(|&b| !impl_bounds.contains(b))
1392 // Collect set present in impl but not in trait.
1393 let extra: Vec<ty::Region> =
1395 .filter(|&b| !trait_bounds.contains(b))
1399 debug!("missing={} extra={}",
1400 missing.repr(tcx), extra.repr(tcx));
1402 let err = if missing.len() != 0 || extra.len() != 0 {
1406 "the lifetime parameter `{}` declared in the impl \
1407 has a distinct set of bounds \
1408 from its counterpart `{}` \
1409 declared in the trait",
1410 impl_param.name.user_string(tcx),
1411 trait_param.name.user_string(tcx)).as_slice());
1417 if missing.len() != 0 {
1420 format!("the impl is missing the following bounds: `{}`",
1421 missing.user_string(tcx)).as_slice());
1424 if extra.len() != 0 {
1427 format!("the impl has the following extra bounds: `{}`",
1428 extra.user_string(tcx)).as_slice());
1440 fn check_cast(fcx: &FnCtxt,
1441 cast_expr: &ast::Expr,
1444 let id = cast_expr.id;
1445 let span = cast_expr.span;
1447 // Find the type of `e`. Supply hints based on the type we are casting to,
1449 let t_1 = fcx.to_ty(t);
1450 let t_1 = structurally_resolved_type(fcx, span, t_1);
1452 if ty::type_is_scalar(t_1) {
1453 // Supply the type as a hint so as to influence integer
1454 // literals and other things that might care.
1455 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1))
1460 let t_e = fcx.expr_ty(e);
1462 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1463 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1465 if ty::type_is_error(t_e) {
1466 fcx.write_error(id);
1470 if ty::type_is_bot(t_e) {
1475 if ty::type_is_trait(t_1) {
1476 // This will be looked up later on.
1477 vtable2::check_object_cast(fcx, cast_expr, e, t_1);
1478 fcx.write_ty(id, t_1);
1482 let t_1 = structurally_resolved_type(fcx, span, t_1);
1483 let t_e = structurally_resolved_type(fcx, span, t_e);
1485 if ty::type_is_nil(t_e) {
1486 fcx.type_error_message(span, |actual| {
1487 format!("cast from nil: `{}` as `{}`",
1489 fcx.infcx().ty_to_string(t_1))
1491 } else if ty::type_is_nil(t_1) {
1492 fcx.type_error_message(span, |actual| {
1493 format!("cast to nil: `{}` as `{}`",
1495 fcx.infcx().ty_to_string(t_1))
1499 let t_1_is_scalar = ty::type_is_scalar(t_1);
1500 let t_1_is_char = ty::type_is_char(t_1);
1501 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1502 let t_1_is_float = ty::type_is_floating_point(t_1);
1504 // casts to scalars other than `char` and `bare fn` are trivial
1505 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1506 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1508 fcx.type_error_message(span, |actual| {
1509 format!("illegal cast; cast through an \
1510 integer first: `{}` as `{}`",
1512 fcx.infcx().ty_to_string(t_1))
1515 // casts from C-like enums are allowed
1516 } else if t_1_is_char {
1517 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1518 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1519 fcx.type_error_message(span, |actual| {
1520 format!("only `u8` can be cast as \
1521 `char`, not `{}`", actual)
1524 } else if ty::get(t_1).sty == ty::ty_bool {
1525 span_err!(fcx.tcx().sess, span, E0054,
1526 "cannot cast as `bool`, compare with zero instead");
1527 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1528 fn types_compatible(fcx: &FnCtxt, sp: Span,
1529 t1: ty::t, t2: ty::t) -> bool {
1530 match ty::get(t1).sty {
1531 ty::ty_vec(_, Some(_)) => {}
1534 if ty::type_needs_infer(t2) {
1535 // This prevents this special case from going off when casting
1536 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1541 let el = ty::sequence_element_type(fcx.tcx(), t1);
1542 infer::mk_eqty(fcx.infcx(),
1549 // Due to the limitations of LLVM global constants,
1550 // region pointers end up pointing at copies of
1551 // vector elements instead of the original values.
1552 // To allow unsafe pointers to work correctly, we
1553 // need to special-case obtaining an unsafe pointer
1554 // from a region pointer to a vector.
1556 /* this cast is only allowed from &[T, ..n] to *T or
1558 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1559 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1560 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1561 if types_compatible(fcx, e.span, mt1, mt2) => {
1562 /* this case is allowed */
1565 demand::coerce(fcx, e.span, t_1, &*e);
1568 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1570 If more type combinations should be supported than are
1571 supported here, then file an enhancement issue and
1572 record the issue number in this comment.
1574 fcx.type_error_message(span, |actual| {
1575 format!("non-scalar cast: `{}` as `{}`",
1577 fcx.infcx().ty_to_string(t_1))
1579 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1580 fcx.type_error_message(span, |actual| {
1581 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1584 fcx.infcx().ty_to_string(t_1))
1588 fcx.write_ty(id, t_1);
1591 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1592 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1594 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1595 ty::lookup_item_type(self.tcx(), id)
1598 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1599 ty::lookup_trait_def(self.tcx(), id)
1602 fn ty_infer(&self, _span: Span) -> ty::t {
1603 self.infcx().next_ty_var()
1606 fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
1611 fn associated_type_binding(&self,
1617 self.tcx().sess.span_err(span, "unsupported associated type binding");
1622 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1623 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1625 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
1629 pub fn err_count_since_creation(&self) -> uint {
1630 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1634 impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
1635 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1636 Some(self.next_region_var(infer::MiscVariable(span)))
1639 fn anon_regions(&self, span: Span, count: uint)
1640 -> Result<Vec<ty::Region> , ()> {
1641 Ok(Vec::from_fn(count, |_| {
1642 self.next_region_var(infer::MiscVariable(span))
1647 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1648 pub fn tag(&self) -> String {
1649 format!("{}", self as *const FnCtxt)
1652 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1653 match self.inh.locals.borrow().find(&nid) {
1656 self.tcx().sess.span_bug(
1658 format!("no type for local variable {:?}",
1665 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1666 debug!("write_ty({}, {}) in fcx {}",
1667 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1668 self.inh.node_types.borrow_mut().insert(node_id, ty);
1671 pub fn write_object_cast(&self,
1673 trait_ref: Rc<ty::TraitRef>) {
1674 debug!("write_object_cast key={} trait_ref={}",
1675 key, trait_ref.repr(self.tcx()));
1676 self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
1679 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1680 if !substs.substs.is_noop() {
1681 debug!("write_substs({}, {}) in fcx {}",
1683 substs.repr(self.tcx()),
1686 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1690 pub fn write_ty_substs(&self,
1691 node_id: ast::NodeId,
1693 substs: ty::ItemSubsts) {
1694 let ty = ty.subst(self.tcx(), &substs.substs);
1695 self.write_ty(node_id, ty);
1696 self.write_substs(node_id, substs);
1699 pub fn write_autoderef_adjustment(&self,
1700 node_id: ast::NodeId,
1703 if derefs == 0 { return; }
1704 self.write_adjustment(
1707 ty::AutoDerefRef(ty::AutoDerefRef {
1713 pub fn write_adjustment(&self,
1714 node_id: ast::NodeId,
1716 adj: ty::AutoAdjustment) {
1717 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1719 // Careful: adjustments can imply trait obligations if we are
1720 // casting from a concrete type to an object type. I think
1721 // it'd probably be nicer to move the logic that creates the
1722 // obligation into the code that creates the adjustment, but
1723 // that's a bit awkward, so instead we go digging and pull the
1724 // obligation out here.
1725 self.register_adjustment_obligations(span, &adj);
1726 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1729 fn register_adjustment_obligations(&self,
1731 adj: &ty::AutoAdjustment) {
1733 ty::AutoAddEnv(..) => { }
1734 ty::AutoDerefRef(ref d_r) => {
1737 self.register_autoref_obligations(span, a_r);
1745 fn register_autoref_obligations(&self,
1747 autoref: &ty::AutoRef) {
1749 ty::AutoUnsize(ref unsize) => {
1750 self.register_unsize_obligations(span, unsize);
1752 ty::AutoPtr(_, _, None) |
1753 ty::AutoUnsafe(_, None) => {
1755 ty::AutoPtr(_, _, Some(ref a_r)) |
1756 ty::AutoUnsafe(_, Some(ref a_r)) => {
1757 self.register_autoref_obligations(span, &**a_r)
1759 ty::AutoUnsizeUniq(ref unsize) => {
1760 self.register_unsize_obligations(span, unsize);
1765 fn register_unsize_obligations(&self,
1767 unsize: &ty::UnsizeKind) {
1768 debug!("register_unsize_obligations: unsize={:?}", unsize);
1771 ty::UnsizeLength(..) => {}
1772 ty::UnsizeStruct(ref u, _) => {
1773 self.register_unsize_obligations(span, &**u)
1775 ty::UnsizeVtable(ref ty_trait, self_ty) => {
1776 vtable2::register_object_cast_obligations(self,
1784 pub fn instantiate_item_type(&self,
1790 * Returns the type of `def_id` with all generics replaced by
1791 * by fresh type/region variables. Also returns the
1792 * substitution from the type parameters on `def_id` to the
1793 * fresh variables. Registers any trait obligations specified
1794 * on `def_id` at the same time.
1798 ty::lookup_item_type(self.tcx(), def_id);
1800 self.infcx().fresh_substs_for_generics(
1802 &polytype.generics);
1803 self.add_obligations_for_parameters(
1804 traits::ObligationCause::new(
1806 traits::ItemObligation(def_id)),
1808 &polytype.generics);
1810 polytype.ty.subst(self.tcx(), &substs);
1818 pub fn write_nil(&self, node_id: ast::NodeId) {
1819 self.write_ty(node_id, ty::mk_nil());
1821 pub fn write_bot(&self, node_id: ast::NodeId) {
1822 self.write_ty(node_id, ty::mk_bot());
1824 pub fn write_error(&self, node_id: ast::NodeId) {
1825 self.write_ty(node_id, ty::mk_err());
1828 pub fn require_type_meets(&self,
1831 code: traits::ObligationCauseCode,
1832 bound: ty::BuiltinBound)
1834 self.register_obligation(
1835 traits::obligation_for_builtin_bound(
1837 traits::ObligationCause::new(span, code),
1842 pub fn require_type_is_sized(&self,
1845 code: traits::ObligationCauseCode)
1847 self.require_type_meets(ty, span, code, ty::BoundSized);
1850 pub fn require_expr_have_sized_type(&self,
1852 code: traits::ObligationCauseCode)
1854 self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
1857 pub fn register_obligation(&self,
1858 obligation: traits::Obligation)
1860 debug!("register_obligation({})",
1861 obligation.repr(self.tcx()));
1863 self.inh.fulfillment_cx
1865 .register_obligation(self.tcx(), obligation);
1868 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1869 let t = ast_ty_to_ty(self, self.infcx(), ast_t);
1871 let mut bounds_checker = wf::BoundsChecker::new(self,
1875 bounds_checker.check_ty(t);
1880 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1881 pat.repr(self.tcx())
1884 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1885 match self.inh.node_types.borrow().find(&ex.id) {
1888 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1889 self.tag()).as_slice());
1894 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1895 match self.inh.node_types.borrow().find(&id) {
1898 self.tcx().sess.bug(
1899 format!("no type for node {}: {} in fcx {}",
1900 id, self.tcx().map.node_to_string(id),
1901 self.tag()).as_slice());
1906 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1907 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1908 Some(method) => method.substs.clone(),
1910 self.tcx().sess.bug(
1911 format!("no method entry for node {}: {} in fcx {}",
1912 id, self.tcx().map.node_to_string(id),
1913 self.tag()).as_slice());
1918 pub fn opt_node_ty_substs(&self,
1920 f: |&ty::ItemSubsts|) {
1921 match self.inh.item_substs.borrow().find(&id) {
1927 pub fn mk_subty(&self,
1928 a_is_expected: bool,
1929 origin: infer::TypeOrigin,
1932 -> Result<(), ty::type_err> {
1933 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1936 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1937 -> Result<(), ty::type_err> {
1938 infer::can_mk_subty(self.infcx(), sub, sup)
1941 pub fn can_mk_eqty(&self, sub: ty::t, sup: ty::t)
1942 -> Result<(), ty::type_err> {
1943 infer::can_mk_eqty(self.infcx(), sub, sup)
1946 pub fn mk_assignty(&self,
1950 -> Result<(), ty::type_err> {
1951 match infer::mk_coercety(self.infcx(),
1953 infer::ExprAssignable(expr.span),
1957 Err(ref e) => Err((*e)),
1958 Ok(Some(adjustment)) => {
1959 self.write_adjustment(expr.id, expr.span, adjustment);
1965 pub fn mk_eqty(&self,
1966 a_is_expected: bool,
1967 origin: infer::TypeOrigin,
1970 -> Result<(), ty::type_err> {
1971 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1974 pub fn mk_subr(&self,
1975 origin: infer::SubregionOrigin,
1978 infer::mk_subr(self.infcx(), origin, sub, sup)
1981 pub fn type_error_message(&self,
1983 mk_msg: |String| -> String,
1985 err: Option<&ty::type_err>) {
1986 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1989 pub fn report_mismatched_return_types(&self,
1993 err: &ty::type_err) {
1995 if ty::type_is_error(e) || ty::type_is_error(a) {
1998 self.infcx().report_mismatched_types(sp, e, a, err)
2001 pub fn report_mismatched_types(&self,
2005 err: &ty::type_err) {
2006 self.infcx().report_mismatched_types(sp, e, a, err)
2009 pub fn register_region_obligation(&self,
2010 origin: infer::SubregionOrigin,
2015 * Registers an obligation for checking later, during
2016 * regionck, that the type `ty` must outlive the region `r`.
2019 let mut region_obligations = self.inh.region_obligations.borrow_mut();
2020 let v = region_obligations.find_or_insert_with(self.body_id,
2022 v.push(RegionObligation { sub_region: r,
2027 pub fn add_obligations_for_parameters(&self,
2028 cause: traits::ObligationCause,
2030 generics: &ty::Generics)
2033 * Given a set of generic parameter definitions (`generics`)
2034 * and the values provided for each of them (`substs`),
2035 * creates and registers suitable region obligations.
2037 * For example, if there is a function:
2039 * fn foo<'a,T:'a>(...)
2045 * Then we will create a fresh region variable `'$0` and a
2046 * fresh type variable `$1` for `'a` and `T`. This routine
2047 * will add a region obligation `$1:'$0` and register it
2051 debug!("add_obligations_for_parameters(substs={}, generics={})",
2052 substs.repr(self.tcx()),
2053 generics.repr(self.tcx()));
2055 self.add_trait_obligations_for_generics(cause, substs, generics);
2056 self.add_region_obligations_for_generics(cause, substs, generics);
2059 fn add_trait_obligations_for_generics(&self,
2060 cause: traits::ObligationCause,
2062 generics: &ty::Generics) {
2064 traits::obligations_for_generics(self.tcx(),
2068 obligations.map_move(|o| self.register_obligation(o));
2071 fn add_region_obligations_for_generics(&self,
2072 cause: traits::ObligationCause,
2074 generics: &ty::Generics)
2076 assert_eq!(generics.types.iter().len(),
2077 substs.types.iter().len());
2078 for (type_def, &type_param) in
2079 generics.types.iter().zip(
2080 substs.types.iter())
2082 let param_ty = ty::ParamTy { space: type_def.space,
2083 idx: type_def.index,
2084 def_id: type_def.def_id };
2085 let bounds = type_def.bounds.subst(self.tcx(), substs);
2086 self.add_region_obligations_for_type_parameter(
2087 cause.span, param_ty, &bounds, type_param);
2090 assert_eq!(generics.regions.iter().len(),
2091 substs.regions().iter().len());
2092 for (region_def, ®ion_param) in
2093 generics.regions.iter().zip(
2094 substs.regions().iter())
2096 let bounds = region_def.bounds.subst(self.tcx(), substs);
2097 self.add_region_obligations_for_region_parameter(
2098 cause.span, bounds.as_slice(), region_param);
2102 fn add_region_obligations_for_type_parameter(&self,
2104 param_ty: ty::ParamTy,
2105 param_bound: &ty::ParamBounds,
2108 // For each declared region bound `T:r`, `T` must outlive `r`.
2110 ty::required_region_bounds(
2112 param_bound.region_bounds.as_slice(),
2113 param_bound.builtin_bounds,
2114 param_bound.trait_bounds.as_slice());
2115 for &r in region_bounds.iter() {
2116 let origin = infer::RelateParamBound(span, param_ty, ty);
2117 self.register_region_obligation(origin, ty, r);
2121 fn add_region_obligations_for_region_parameter(&self,
2123 region_bounds: &[ty::Region],
2124 region_param: ty::Region)
2126 for &b in region_bounds.iter() {
2127 // For each bound `region:b`, `b <= region` must hold
2128 // (i.e., `region` must outlive `b`).
2129 let origin = infer::RelateRegionParamBound(span);
2130 self.mk_subr(origin, b, region_param);
2135 pub enum LvaluePreference {
2140 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
2141 expr_id: Option<ast::NodeId>,
2142 mut lvalue_pref: LvaluePreference,
2143 should_stop: |ty::t, uint| -> Option<T>)
2144 -> (ty::t, uint, Option<T>) {
2146 * Executes an autoderef loop for the type `t`. At each step, invokes
2147 * `should_stop` to decide whether to terminate the loop. Returns
2148 * the final type and number of derefs that it performed.
2150 * Note: this method does not modify the adjustments table. The caller is
2151 * responsible for inserting an AutoAdjustment record into the `fcx`
2152 * using one of the suitable methods.
2155 let mut t = base_ty;
2156 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
2157 let resolved_t = structurally_resolved_type(fcx, sp, t);
2159 if ty::type_is_bot(resolved_t) {
2160 return (resolved_t, autoderefs, None);
2163 match should_stop(resolved_t, autoderefs) {
2164 Some(x) => return (resolved_t, autoderefs, Some(x)),
2168 // Otherwise, deref if type is derefable:
2169 let mt = match ty::deref(resolved_t, false) {
2170 Some(mt) => Some(mt),
2172 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
2173 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
2179 if mt.mutbl == ast::MutImmutable {
2180 lvalue_pref = NoPreference;
2183 None => return (resolved_t, autoderefs, None)
2187 // We've reached the recursion limit, error gracefully.
2188 span_err!(fcx.tcx().sess, sp, E0055,
2189 "reached the recursion limit while auto-dereferencing {}",
2190 base_ty.repr(fcx.tcx()));
2191 (ty::mk_err(), 0, None)
2194 /// Attempts to resolve a call expression as an overloaded call.
2195 fn try_overloaded_call(fcx: &FnCtxt,
2196 call_expression: &ast::Expr,
2199 args: &[P<ast::Expr>])
2201 // Bail out if the callee is a bare function or a closure. We check those
2203 match *structure_of(fcx, callee.span, callee_type) {
2204 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
2208 // Try `FnOnce`, then `FnMut`, then `Fn`.
2209 for &(maybe_function_trait, method_name) in [
2210 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
2211 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
2212 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
2214 let function_trait = match maybe_function_trait {
2216 Some(function_trait) => function_trait,
2218 let method_callee = match method::lookup_in_trait(
2220 call_expression.span,
2226 DontAutoderefReceiver,
2227 IgnoreStaticMethods) {
2229 Some(method_callee) => method_callee,
2231 let method_call = MethodCall::expr(call_expression.id);
2232 let output_type = check_method_argument_types(fcx,
2233 call_expression.span,
2239 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2240 write_call(fcx, call_expression, output_type);
2242 if !fcx.tcx().sess.features.borrow().overloaded_calls {
2243 span_err!(fcx.tcx().sess, call_expression.span, E0056,
2244 "overloaded calls are experimental");
2245 span_note!(fcx.tcx().sess, call_expression.span,
2246 "add `#![feature(overloaded_calls)]` to \
2247 the crate attributes to enable");
2256 fn try_overloaded_deref(fcx: &FnCtxt,
2258 method_call: Option<MethodCall>,
2259 base_expr: Option<&ast::Expr>,
2261 lvalue_pref: LvaluePreference)
2263 // Try DerefMut first, if preferred.
2264 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2265 (PreferMutLvalue, Some(trait_did)) => {
2266 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2267 token::intern("deref_mut"), trait_did,
2268 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2273 // Otherwise, fall back to Deref.
2274 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2275 (None, Some(trait_did)) => {
2276 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2277 token::intern("deref"), trait_did,
2278 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2280 (method, _) => method
2285 let ref_ty = ty::ty_fn_ret(method.ty);
2287 Some(method_call) => {
2288 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2292 ty::deref(ref_ty, true)
2298 fn try_overloaded_index(fcx: &FnCtxt,
2299 method_call: Option<MethodCall>,
2301 base_expr: &ast::Expr,
2303 index_expr: &P<ast::Expr>,
2304 lvalue_pref: LvaluePreference)
2306 // Try `IndexMut` first, if preferred.
2307 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2308 (PreferMutLvalue, Some(trait_did)) => {
2309 method::lookup_in_trait(fcx,
2312 token::intern("index_mut"),
2316 DontAutoderefReceiver,
2317 IgnoreStaticMethods)
2322 // Otherwise, fall back to `Index`.
2323 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2324 (None, Some(trait_did)) => {
2325 method::lookup_in_trait(fcx,
2328 token::intern("index"),
2332 DontAutoderefReceiver,
2333 IgnoreStaticMethods)
2335 (method, _) => method,
2338 // Regardless of whether the lookup succeeds, check the method arguments
2339 // so that we have *some* type for each argument.
2340 let method_type = match method {
2341 Some(ref method) => method.ty,
2342 None => ty::mk_err()
2344 check_method_argument_types(fcx,
2348 slice::ref_slice(index_expr),
2350 DontTupleArguments);
2354 let ref_ty = ty::ty_fn_ret(method.ty);
2356 Some(method_call) => {
2357 fcx.inh.method_map.borrow_mut().insert(method_call,
2362 ty::deref(ref_ty, true)
2368 /// Given the head of a `for` expression, looks up the `next` method in the
2369 /// `Iterator` trait. Fails if the expression does not implement `next`.
2371 /// The return type of this function represents the concrete element type
2372 /// `A` in the type `Iterator<A>` that the method returns.
2373 fn lookup_method_for_for_loop(fcx: &FnCtxt,
2374 iterator_expr: &ast::Expr,
2375 loop_id: ast::NodeId)
2377 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2378 Ok(trait_did) => trait_did,
2379 Err(ref err_string) => {
2380 fcx.tcx().sess.span_err(iterator_expr.span,
2381 err_string.as_slice());
2386 let expr_type = fcx.expr_ty(&*iterator_expr);
2387 let method = method::lookup_in_trait(fcx,
2389 Some(&*iterator_expr),
2390 token::intern("next"),
2394 DontAutoderefReceiver,
2395 IgnoreStaticMethods);
2397 // Regardless of whether the lookup succeeds, check the method arguments
2398 // so that we have *some* type for each argument.
2399 let method_type = match method {
2400 Some(ref method) => method.ty,
2402 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
2404 if !ty::type_is_error(true_expr_type) {
2405 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2406 fcx.tcx().sess.span_err(iterator_expr.span,
2407 format!("`for` loop expression has type `{}` which does \
2408 not implement the `Iterator` trait",
2409 ty_string).as_slice());
2414 let return_type = check_method_argument_types(fcx,
2420 DontTupleArguments);
2424 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2427 // We expect the return type to be `Option` or something like it.
2428 // Grab the first parameter of its type substitution.
2429 let return_type = structurally_resolved_type(fcx,
2432 match ty::get(return_type).sty {
2433 ty::ty_enum(_, ref substs)
2434 if !substs.types.is_empty_in(subst::TypeSpace) => {
2435 *substs.types.get(subst::TypeSpace, 0)
2438 fcx.tcx().sess.span_err(iterator_expr.span,
2439 "`next` method of the `Iterator` \
2440 trait has an unexpected type");
2445 None => ty::mk_err()
2449 fn check_method_argument_types(fcx: &FnCtxt,
2451 method_fn_ty: ty::t,
2452 callee_expr: &ast::Expr,
2453 args_no_rcvr: &[P<ast::Expr>],
2454 deref_args: DerefArgs,
2455 tuple_arguments: TupleArgumentsFlag)
2457 if ty::type_is_error(method_fn_ty) {
2458 let err_inputs = err_args(args_no_rcvr.len());
2459 check_argument_types(fcx,
2461 err_inputs.as_slice(),
2469 match ty::get(method_fn_ty).sty {
2470 ty::ty_bare_fn(ref fty) => {
2471 // HACK(eddyb) ignore self in the definition (see above).
2472 check_argument_types(fcx,
2474 fty.sig.inputs.slice_from(1),
2483 fcx.tcx().sess.span_bug(callee_expr.span,
2484 "method without bare fn type");
2490 fn check_argument_types(fcx: &FnCtxt,
2492 fn_inputs: &[ty::t],
2493 _callee_expr: &ast::Expr,
2494 args: &[P<ast::Expr>],
2495 deref_args: DerefArgs,
2497 tuple_arguments: TupleArgumentsFlag) {
2500 * Generic function that factors out common logic from
2501 * function calls, method calls and overloaded operators.
2504 let tcx = fcx.ccx.tcx;
2506 // Grab the argument types, supplying fresh type variables
2507 // if the wrong number of arguments were supplied
2508 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2514 let expected_arg_count = fn_inputs.len();
2515 let formal_tys = if tuple_arguments == TupleArguments {
2516 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2517 match ty::get(tuple_type).sty {
2518 ty::ty_tup(ref arg_types) => {
2519 if arg_types.len() != args.len() {
2520 span_err!(tcx.sess, sp, E0057,
2521 "this function takes {} parameter{} but {} parameter{} supplied",
2523 if arg_types.len() == 1 {""} else {"s"},
2525 if args.len() == 1 {" was"} else {"s were"});
2526 err_args(args.len())
2528 (*arg_types).clone()
2532 if args.len() != 0 {
2533 span_err!(tcx.sess, sp, E0058,
2534 "this function takes 0 parameters but {} parameter{} supplied",
2536 if args.len() == 1 {" was"} else {"s were"});
2541 span_err!(tcx.sess, sp, E0059,
2542 "cannot use call notation; the first type parameter \
2543 for the function trait is neither a tuple nor unit");
2544 err_args(supplied_arg_count)
2547 } else if expected_arg_count == supplied_arg_count {
2548 fn_inputs.iter().map(|a| *a).collect()
2549 } else if variadic {
2550 if supplied_arg_count >= expected_arg_count {
2551 fn_inputs.iter().map(|a| *a).collect()
2553 span_err!(tcx.sess, sp, E0060,
2554 "this function takes at least {} parameter{} \
2555 but {} parameter{} supplied",
2557 if expected_arg_count == 1 {""} else {"s"},
2559 if supplied_arg_count == 1 {" was"} else {"s were"});
2560 err_args(supplied_arg_count)
2563 span_err!(tcx.sess, sp, E0061,
2564 "this function takes {} parameter{} but {} parameter{} supplied",
2566 if expected_arg_count == 1 {""} else {"s"},
2568 if supplied_arg_count == 1 {" was"} else {"s were"});
2569 err_args(supplied_arg_count)
2572 debug!("check_argument_types: formal_tys={:?}",
2573 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2575 // Check the arguments.
2576 // We do this in a pretty awful way: first we typecheck any arguments
2577 // that are not anonymous functions, then we typecheck the anonymous
2578 // functions. This is so that we have more information about the types
2579 // of arguments when we typecheck the functions. This isn't really the
2580 // right way to do this.
2581 let xs = [false, true];
2582 for check_blocks in xs.iter() {
2583 let check_blocks = *check_blocks;
2584 debug!("check_blocks={}", check_blocks);
2586 // More awful hacks: before we check the blocks, try to do
2587 // an "opportunistic" vtable resolution of any trait
2588 // bounds on the call.
2590 vtable2::select_fcx_obligations_where_possible(fcx);
2593 // For variadic functions, we don't have a declared type for all of
2594 // the arguments hence we only do our usual type checking with
2595 // the arguments who's types we do know.
2596 let t = if variadic {
2598 } else if tuple_arguments == TupleArguments {
2603 for (i, arg) in args.iter().take(t).enumerate() {
2604 let is_block = match arg.node {
2605 ast::ExprFnBlock(..) |
2607 ast::ExprUnboxedFn(..) => true,
2611 if is_block == check_blocks {
2612 debug!("checking the argument");
2613 let mut formal_ty = *formal_tys.get(i);
2617 match ty::get(formal_ty).sty {
2618 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2621 // So we hit this case when one implements the
2622 // operator traits but leaves an argument as
2623 // just T instead of &T. We'll catch it in the
2624 // mismatch impl/trait method phase no need to
2627 formal_ty = ty::mk_err();
2634 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
2639 // We also need to make sure we at least write the ty of the other
2640 // arguments which we skipped above.
2642 for arg in args.iter().skip(expected_arg_count) {
2643 check_expr(fcx, &**arg);
2645 // There are a few types which get autopromoted when passed via varargs
2646 // in C but we just error out instead and require explicit casts.
2647 let arg_ty = structurally_resolved_type(fcx, arg.span,
2648 fcx.expr_ty(&**arg));
2649 match ty::get(arg_ty).sty {
2650 ty::ty_float(ast::TyF32) => {
2651 fcx.type_error_message(arg.span,
2653 format!("can't pass an {} to variadic \
2654 function, cast to c_double", t)
2657 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2658 fcx.type_error_message(arg.span, |t| {
2659 format!("can't pass {} to variadic \
2660 function, cast to c_int",
2664 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2665 fcx.type_error_message(arg.span, |t| {
2666 format!("can't pass {} to variadic \
2667 function, cast to c_uint",
2677 fn err_args(len: uint) -> Vec<ty::t> {
2678 Vec::from_fn(len, |_| ty::mk_err())
2681 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
2682 fcx.write_ty(call_expr.id, output);
2685 // AST fragment checking
2686 fn check_lit(fcx: &FnCtxt,
2688 expected: Expectation)
2691 let tcx = fcx.ccx.tcx;
2694 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2695 ast::LitBinary(..) => {
2696 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2698 ast::LitByte(_) => ty::mk_u8(),
2699 ast::LitChar(_) => ty::mk_char(),
2700 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2701 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2702 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2703 let opt_ty = expected.map_to_option(fcx, |sty| {
2705 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2706 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2707 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2708 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2709 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2713 opt_ty.unwrap_or_else(
2714 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2716 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2717 ast::LitFloatUnsuffixed(_) => {
2718 let opt_ty = expected.map_to_option(fcx, |sty| {
2720 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2724 opt_ty.unwrap_or_else(
2725 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2727 ast::LitNil => ty::mk_nil(),
2728 ast::LitBool(_) => ty::mk_bool()
2732 pub fn valid_range_bounds(ccx: &CrateCtxt,
2736 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2737 Some(val) => Some(val <= 0),
2742 pub fn check_expr_has_type(fcx: &FnCtxt,
2745 check_expr_with_unifier(
2746 fcx, expr, ExpectHasType(expected), NoPreference,
2747 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2750 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2753 check_expr_with_unifier(
2754 fcx, expr, ExpectHasType(expected), NoPreference,
2755 || demand::coerce(fcx, expr.span, expected, expr));
2758 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2759 check_expr_with_unifier(
2760 fcx, expr, ExpectHasType(expected), NoPreference,
2764 fn check_expr_with_expectation(fcx: &FnCtxt,
2766 expected: Expectation) {
2767 check_expr_with_unifier(
2768 fcx, expr, expected, NoPreference,
2772 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2774 expected: Expectation,
2775 lvalue_pref: LvaluePreference)
2777 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2780 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2781 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2784 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2785 lvalue_pref: LvaluePreference) {
2786 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2789 // determine the `self` type, using fresh variables for all variables
2790 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2791 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2793 pub fn impl_self_ty(fcx: &FnCtxt,
2794 span: Span, // (potential) receiver for this impl
2797 let tcx = fcx.tcx();
2799 let ity = ty::lookup_item_type(tcx, did);
2800 let (n_tps, rps, raw_ty) =
2801 (ity.generics.types.len(subst::TypeSpace),
2802 ity.generics.regions.get_slice(subst::TypeSpace),
2805 let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
2806 let tps = fcx.inh.infcx.next_ty_vars(n_tps);
2807 let substs = subst::Substs::new_type(tps, rps);
2808 let substd_ty = raw_ty.subst(tcx, &substs);
2810 TypeAndSubsts { substs: substs, ty: substd_ty }
2813 // Only for fields! Returns <none> for methods>
2814 // Indifferent to privacy flags
2815 pub fn lookup_field_ty(tcx: &ty::ctxt,
2816 class_id: ast::DefId,
2817 items: &[ty::field_ty],
2818 fieldname: ast::Name,
2819 substs: &subst::Substs) -> Option<ty::t> {
2821 let o_field = items.iter().find(|f| f.name == fieldname);
2822 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2825 pub fn lookup_tup_field_ty(tcx: &ty::ctxt,
2826 class_id: ast::DefId,
2827 items: &[ty::field_ty],
2829 substs: &subst::Substs) -> Option<ty::t> {
2831 let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
2832 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2835 // Controls whether the arguments are automatically referenced. This is useful
2836 // for overloaded binary and unary operators.
2837 pub enum DerefArgs {
2842 /// Controls whether the arguments are tupled. This is used for the call
2845 /// Tupling means that all call-side arguments are packed into a tuple and
2846 /// passed as a single parameter. For example, if tupling is enabled, this
2849 /// fn f(x: (int, int))
2851 /// Can be called as:
2858 #[deriving(Clone, Eq, PartialEq)]
2859 enum TupleArgumentsFlag {
2865 /// If an expression has any sub-expressions that result in a type error,
2866 /// inspecting that expression's type with `ty::type_is_error` will return
2867 /// true. Likewise, if an expression is known to diverge, inspecting its
2868 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2869 /// strict, _|_ can appear in the type of an expression that does not,
2870 /// itself, diverge: for example, fn() -> _|_.)
2871 /// Note that inspecting a type's structure *directly* may expose the fact
2872 /// that there are actually multiple representations for both `ty_err` and
2873 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2874 fn check_expr_with_unifier(fcx: &FnCtxt,
2876 expected: Expectation,
2877 lvalue_pref: LvaluePreference,
2880 debug!(">> typechecking: expr={} expected={}",
2881 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2883 // A generic function for doing all of the checking for call expressions
2884 fn check_call(fcx: &FnCtxt,
2885 call_expr: &ast::Expr,
2887 args: &[P<ast::Expr>]) {
2888 // Store the type of `f` as the type of the callee
2889 let fn_ty = fcx.expr_ty(f);
2891 // Extract the function signature from `in_fty`.
2892 let fn_sty = structure_of(fcx, f.span, fn_ty);
2894 // This is the "default" function signature, used in case of error.
2895 // In that case, we check each argument against "error" in order to
2896 // set up all the node type bindings.
2897 let error_fn_sig = FnSig {
2898 binder_id: ast::CRATE_NODE_ID,
2899 inputs: err_args(args.len()),
2900 output: ty::mk_err(),
2904 let fn_sig = match *fn_sty {
2905 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2906 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2908 fcx.type_error_message(call_expr.span, |actual| {
2909 format!("expected function, found `{}`", actual)
2915 // Replace any bound regions that appear in the function
2916 // signature with region variables
2917 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2918 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2921 // Call the generic checker.
2922 check_argument_types(fcx,
2924 fn_sig.inputs.as_slice(),
2929 DontTupleArguments);
2931 write_call(fcx, call_expr, fn_sig.output);
2934 // Checks a method call.
2935 fn check_method_call(fcx: &FnCtxt,
2937 method_name: ast::SpannedIdent,
2938 args: &[P<ast::Expr>],
2939 tps: &[P<ast::Ty>]) {
2940 let rcvr = &*args[0];
2941 // We can't know if we need &mut self before we look up the method,
2942 // so treat the receiver as mutable just in case - only explicit
2943 // overloaded dereferences care about the distinction.
2944 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2946 // no need to check for bot/err -- callee does that
2947 let expr_t = structurally_resolved_type(fcx,
2949 fcx.expr_ty(&*rcvr));
2951 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2952 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2953 method_name.node.name,
2954 expr_t, tps.as_slice(),
2956 CheckTraitsAndInherentMethods,
2957 AutoderefReceiver, IgnoreStaticMethods) {
2959 let method_ty = method.ty;
2960 let method_call = MethodCall::expr(expr.id);
2961 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2965 debug!("(checking method call) failing expr is {}", expr.id);
2967 fcx.type_error_message(method_name.span,
2969 format!("type `{}` does not implement any \
2970 method in scope named `{}`",
2972 token::get_ident(method_name.node))
2977 // Add error type for the result
2978 fcx.write_error(expr.id);
2980 // Check for potential static matches (missing self parameters)
2984 method_name.node.name,
2988 CheckTraitsAndInherentMethods,
2989 DontAutoderefReceiver,
2990 ReportStaticMethods);
2996 // Call the generic checker.
2997 let ret_ty = check_method_argument_types(fcx,
3003 DontTupleArguments);
3005 write_call(fcx, expr, ret_ty);
3008 // A generic function for checking the then and else in an if
3010 fn check_then_else(fcx: &FnCtxt,
3011 cond_expr: &ast::Expr,
3012 then_blk: &ast::Block,
3013 opt_else_expr: Option<&ast::Expr>,
3016 expected: Expectation) {
3017 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
3019 let branches_ty = match opt_else_expr {
3020 Some(ref else_expr) => {
3021 // Disregard "castable to" expectations because they
3022 // can lead us astray. Consider for example `if cond
3023 // {22} else {c} as u8` -- if we propagate the
3024 // "castable to u8" constraint to 22, it will pick the
3025 // type 22u8, which is overly constrained (c might not
3026 // be a u8). In effect, the problem is that the
3027 // "castable to" expectation is not the tightest thing
3028 // we can say, so we want to drop it in this case.
3029 // The tightest thing we can say is "must unify with
3030 // else branch". Note that in the case of a "has type"
3031 // constraint, this limitation does not hold.
3033 // If the expected type is just a type variable, then don't use
3034 // an expected type. Otherwise, we might write parts of the type
3035 // when checking the 'then' block which are incompatible with the
3037 let expected = match expected.only_has_type() {
3038 ExpectHasType(ety) => {
3039 match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) {
3040 Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
3046 check_block_with_expected(fcx, then_blk, expected);
3047 let then_ty = fcx.node_ty(then_blk.id);
3048 check_expr_with_expectation(fcx, &**else_expr, expected);
3049 let else_ty = fcx.expr_ty(&**else_expr);
3050 infer::common_supertype(fcx.infcx(),
3051 infer::IfExpression(sp),
3057 check_block_no_value(fcx, then_blk);
3062 let cond_ty = fcx.expr_ty(cond_expr);
3063 let if_ty = if ty::type_is_error(cond_ty) {
3065 } else if ty::type_is_bot(cond_ty) {
3071 fcx.write_ty(id, if_ty);
3074 fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
3078 trait_did: Option<ast::DefId>,
3080 rhs: Option<&P<ast::Expr>>,
3081 autoderef_receiver: AutoderefReceiverFlag,
3082 unbound_method: ||) -> ty::t {
3083 let method = match trait_did {
3084 Some(trait_did) => {
3085 method::lookup_in_trait(fcx, op_ex.span, Some(lhs), opname,
3086 trait_did, lhs_ty, &[], autoderef_receiver,
3087 IgnoreStaticMethods)
3091 let args = match rhs {
3092 Some(rhs) => slice::ref_slice(rhs),
3094 // Work around the lack of coercion.
3095 let empty: &[_] = &[];
3101 let method_ty = method.ty;
3102 // HACK(eddyb) Fully qualified path to work around a resolve bug.
3103 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
3104 fcx.inh.method_map.borrow_mut().insert(method_call, method);
3105 check_method_argument_types(fcx,
3115 // Check the args anyway
3116 // so we get all the error messages
3117 let expected_ty = ty::mk_err();
3118 check_method_argument_types(fcx,
3124 DontTupleArguments);
3130 // could be either an expr_binop or an expr_assign_binop
3131 fn check_binop(fcx: &FnCtxt,
3136 is_binop_assignment: IsBinopAssignment) {
3137 let tcx = fcx.ccx.tcx;
3139 let lvalue_pref = match is_binop_assignment {
3140 BinopAssignment => PreferMutLvalue,
3141 SimpleBinop => NoPreference
3143 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
3145 // Callee does bot / err checking
3146 let lhs_t = structurally_resolved_type(fcx, lhs.span,
3147 fcx.expr_ty(&*lhs));
3149 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
3150 // Shift is a special case: rhs must be uint, no matter what lhs is
3151 check_expr_has_type(fcx, &**rhs, ty::mk_uint());
3152 fcx.write_ty(expr.id, lhs_t);
3156 if ty::is_binopable(tcx, lhs_t, op) {
3157 let tvar = fcx.infcx().next_ty_var();
3158 demand::suptype(fcx, expr.span, tvar, lhs_t);
3159 check_expr_has_type(fcx, &**rhs, tvar);
3161 let result_t = match op {
3162 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
3164 if ty::type_is_simd(tcx, lhs_t) {
3165 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
3166 fcx.type_error_message(expr.span,
3168 format!("binary comparison \
3169 operation `{}` not \
3170 supported for floating \
3171 point SIMD vector `{}`",
3172 ast_util::binop_to_string(op),
3189 fcx.write_ty(expr.id, result_t);
3193 if op == ast::BiOr || op == ast::BiAnd {
3194 // This is an error; one of the operands must have the wrong
3196 fcx.write_error(expr.id);
3197 fcx.write_error(rhs.id);
3198 fcx.type_error_message(expr.span,
3200 format!("binary operation `{}` cannot be applied \
3202 ast_util::binop_to_string(op),
3209 // Check for overloaded operators if not an assignment.
3210 let result_t = if is_binop_assignment == SimpleBinop {
3211 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
3213 fcx.type_error_message(expr.span,
3215 format!("binary assignment \
3217 cannot be applied to \
3219 ast_util::binop_to_string(op),
3224 check_expr(fcx, &**rhs);
3228 fcx.write_ty(expr.id, result_t);
3229 if ty::type_is_error(result_t) {
3230 fcx.write_ty(rhs.id, result_t);
3234 fn check_user_binop(fcx: &FnCtxt,
3236 lhs_expr: &ast::Expr,
3237 lhs_resolved_t: ty::t,
3239 rhs: &P<ast::Expr>) -> ty::t {
3240 let tcx = fcx.ccx.tcx;
3241 let lang = &tcx.lang_items;
3242 let (name, trait_did) = match op {
3243 ast::BiAdd => ("add", lang.add_trait()),
3244 ast::BiSub => ("sub", lang.sub_trait()),
3245 ast::BiMul => ("mul", lang.mul_trait()),
3246 ast::BiDiv => ("div", lang.div_trait()),
3247 ast::BiRem => ("rem", lang.rem_trait()),
3248 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3249 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3250 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3251 ast::BiShl => ("shl", lang.shl_trait()),
3252 ast::BiShr => ("shr", lang.shr_trait()),
3253 ast::BiLt => ("lt", lang.ord_trait()),
3254 ast::BiLe => ("le", lang.ord_trait()),
3255 ast::BiGe => ("ge", lang.ord_trait()),
3256 ast::BiGt => ("gt", lang.ord_trait()),
3257 ast::BiEq => ("eq", lang.eq_trait()),
3258 ast::BiNe => ("ne", lang.eq_trait()),
3259 ast::BiAnd | ast::BiOr => {
3260 check_expr(fcx, &**rhs);
3261 return ty::mk_err();
3264 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3265 trait_did, lhs_expr, Some(rhs), DontAutoderefReceiver, || {
3266 fcx.type_error_message(ex.span, |actual| {
3267 format!("binary operation `{}` cannot be applied to type `{}`",
3268 ast_util::binop_to_string(op),
3270 }, lhs_resolved_t, None)
3274 fn check_user_unop(fcx: &FnCtxt,
3277 trait_did: Option<ast::DefId>,
3279 rhs_expr: &ast::Expr,
3280 rhs_t: ty::t) -> ty::t {
3281 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3282 trait_did, rhs_expr, None, DontAutoderefReceiver, || {
3283 fcx.type_error_message(ex.span, |actual| {
3284 format!("cannot apply unary operator `{}` to type `{}`",
3290 fn check_unboxed_closure(fcx: &FnCtxt,
3292 kind: ast::UnboxedClosureKind,
3294 body: &ast::Block) {
3295 let mut fn_ty = astconv::ty_of_closure(
3301 // The `RegionTraitStore` and region_existential_bounds
3302 // are lies, but we ignore them so it doesn't matter.
3304 // FIXME(pcwalton): Refactor this API.
3305 ty::region_existential_bound(ty::ReStatic),
3306 ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
3312 let region = match fcx.infcx().anon_regions(expr.span, 1) {
3314 fcx.ccx.tcx.sess.span_bug(expr.span,
3315 "can't make anon regions here?!")
3317 Ok(regions) => *regions.get(0),
3319 let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
3322 fcx.write_ty(expr.id, closure_type);
3333 // Tuple up the arguments and insert the resulting function type into
3334 // the `unboxed_closures` table.
3335 fn_ty.sig.inputs = if fn_ty.sig.inputs.len() == 0 {
3338 vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)]
3341 let kind = match kind {
3342 ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
3343 ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
3344 ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
3347 let unboxed_closure = ty::UnboxedClosure {
3348 closure_type: fn_ty,
3355 .insert(local_def(expr.id), unboxed_closure);
3358 fn check_expr_fn(fcx: &FnCtxt,
3360 store: ty::TraitStore,
3363 expected: Expectation) {
3364 let tcx = fcx.ccx.tcx;
3366 // Find the expected input/output types (if any). Substitute
3367 // fresh bound regions for any bound regions we find in the
3368 // expected types so as to avoid capture.
3369 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
3372 expected_bounds) = {
3373 match expected_sty {
3374 Some(ty::ty_closure(ref cenv)) => {
3376 replace_late_bound_regions_in_fn_sig(
3378 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
3379 let onceness = match (&store, &cenv.store) {
3380 // As the closure type and onceness go, only three
3381 // combinations are legit:
3385 // If the actual and expected closure type disagree with
3386 // each other, set expected onceness to be always Once or
3387 // Many according to the actual type. Otherwise, it will
3388 // yield either an illegal "many proc" or a less known
3389 // "once closure" in the error message.
3390 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
3391 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
3393 (&ty::UniqTraitStore, _) => ast::Once,
3394 (&ty::RegionTraitStore(..), _) => ast::Many,
3396 (Some(sig), onceness, cenv.bounds)
3399 // Not an error! Means we're inferring the closure type
3400 let (bounds, onceness) = match expr.node {
3401 ast::ExprProc(..) => {
3402 let mut bounds = ty::region_existential_bound(ty::ReStatic);
3403 bounds.builtin_bounds.add(ty::BoundSend); // FIXME
3407 let region = fcx.infcx().next_region_var(
3408 infer::AddrOfRegion(expr.span));
3409 (ty::region_existential_bound(region), ast::Many)
3412 (None, onceness, bounds)
3417 // construct the function type
3418 let fn_ty = astconv::ty_of_closure(fcx,
3427 let fty_sig = fn_ty.sig.clone();
3428 let fty = ty::mk_closure(tcx, fn_ty);
3429 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
3431 fcx.write_ty(expr.id, fty);
3433 // If the closure is a stack closure and hasn't had some non-standard
3434 // style inferred for it, then check it under its parent's style.
3435 // Otherwise, use its own
3436 let (inherited_style, inherited_style_id) = match store {
3437 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
3438 fcx.ps.borrow().def),
3439 ty::UniqTraitStore => (ast::NormalFn, expr.id)
3453 // Check field access expressions
3454 fn check_field(fcx: &FnCtxt,
3456 lvalue_pref: LvaluePreference,
3458 field: &ast::SpannedIdent,
3459 tys: &[P<ast::Ty>]) {
3460 let tcx = fcx.ccx.tcx;
3461 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3462 let expr_t = structurally_resolved_type(fcx, expr.span,
3464 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3465 let (_, autoderefs, field_ty) =
3466 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3467 match ty::get(base_t).sty {
3468 ty::ty_struct(base_id, ref substs) => {
3469 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3470 let fields = ty::lookup_struct_fields(tcx, base_id);
3471 lookup_field_ty(tcx, base_id, fields.as_slice(),
3472 field.node.name, &(*substs))
3479 fcx.write_ty(expr.id, field_ty);
3480 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3486 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
3487 match method::lookup(fcx,
3494 CheckTraitsAndInherentMethods,
3496 IgnoreStaticMethods) {
3498 fcx.type_error_message(
3501 format!("attempted to take value of method `{}` on type \
3502 `{}`", token::get_ident(field.node), actual)
3506 tcx.sess.span_note(field.span,
3507 "maybe a missing `()` to call it? If not, try an anonymous function.");
3511 fcx.type_error_message(
3514 format!("attempted access of field `{}` on \
3515 type `{}`, but no field with that \
3517 token::get_ident(field.node),
3524 fcx.write_error(expr.id);
3527 // Check tuple index expressions
3528 fn check_tup_field(fcx: &FnCtxt,
3530 lvalue_pref: LvaluePreference,
3532 idx: codemap::Spanned<uint>,
3533 _tys: &[P<ast::Ty>]) {
3534 let tcx = fcx.ccx.tcx;
3535 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3536 let expr_t = structurally_resolved_type(fcx, expr.span,
3538 let mut tuple_like = false;
3539 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3540 let (_, autoderefs, field_ty) =
3541 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3542 match ty::get(base_t).sty {
3543 ty::ty_struct(base_id, ref substs) => {
3544 tuple_like = ty::is_tuple_struct(tcx, base_id);
3546 debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
3547 let fields = ty::lookup_struct_fields(tcx, base_id);
3548 lookup_tup_field_ty(tcx, base_id, fields.as_slice(),
3549 idx.node, &(*substs))
3554 ty::ty_tup(ref v) => {
3556 if idx.node < v.len() { Some(v[idx.node]) } else { None }
3563 fcx.write_ty(expr.id, field_ty);
3564 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
3569 fcx.type_error_message(
3573 format!("attempted out-of-bounds tuple index `{}` on \
3578 format!("attempted tuple index `{}` on type `{}`, but the \
3579 type was not a tuple or tuple struct",
3586 fcx.write_error(expr.id);
3589 fn check_struct_or_variant_fields(fcx: &FnCtxt,
3592 class_id: ast::DefId,
3593 node_id: ast::NodeId,
3594 substitutions: subst::Substs,
3595 field_types: &[ty::field_ty],
3596 ast_fields: &[ast::Field],
3597 check_completeness: bool) {
3598 let tcx = fcx.ccx.tcx;
3600 let mut class_field_map = HashMap::new();
3601 let mut fields_found = 0;
3602 for field in field_types.iter() {
3603 class_field_map.insert(field.name, (field.id, false));
3606 let mut error_happened = false;
3608 // Typecheck each field.
3609 for field in ast_fields.iter() {
3610 let mut expected_field_type = ty::mk_err();
3612 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
3615 fcx.type_error_message(
3618 format!("structure `{}` has no field named `{}`",
3619 actual, token::get_ident(field.ident.node))
3623 error_happened = true;
3625 Some((_, true)) => {
3626 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3627 "field `{}` specified more than once",
3628 token::get_ident(field.ident.node));
3629 error_happened = true;
3631 Some((field_id, false)) => {
3632 expected_field_type =
3633 ty::lookup_field_type(
3634 tcx, class_id, field_id, &substitutions);
3635 class_field_map.insert(
3636 field.ident.node.name, (field_id, true));
3640 // Make sure to give a type to the field even if there's
3641 // an error, so we can continue typechecking
3642 check_expr_coercable_to_type(
3645 expected_field_type);
3649 fcx.write_error(node_id);
3652 if check_completeness && !error_happened {
3653 // Make sure the programmer specified all the fields.
3654 assert!(fields_found <= field_types.len());
3655 if fields_found < field_types.len() {
3656 let mut missing_fields = Vec::new();
3657 for class_field in field_types.iter() {
3658 let name = class_field.name;
3659 let (_, seen) = *class_field_map.get(&name);
3661 missing_fields.push(
3662 format!("`{}`", token::get_name(name).get()))
3666 span_err!(tcx.sess, span, E0063,
3667 "missing field{}: {}",
3668 if missing_fields.len() == 1 {""} else {"s"},
3669 missing_fields.connect(", "));
3673 if !error_happened {
3674 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3675 class_id, substitutions));
3679 fn check_struct_constructor(fcx: &FnCtxt,
3681 span: codemap::Span,
3682 class_id: ast::DefId,
3683 fields: &[ast::Field],
3684 base_expr: Option<&ast::Expr>) {
3685 let tcx = fcx.ccx.tcx;
3687 // Generate the struct type.
3689 ty: mut struct_type,
3690 substs: struct_substs
3691 } = fcx.instantiate_item_type(span, class_id);
3693 // Look up and check the fields.
3694 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3695 check_struct_or_variant_fields(fcx,
3701 class_fields.as_slice(),
3703 base_expr.is_none());
3704 if ty::type_is_error(fcx.node_ty(id)) {
3705 struct_type = ty::mk_err();
3708 // Check the base expression if necessary.
3711 Some(base_expr) => {
3712 check_expr_has_type(fcx, &*base_expr, struct_type);
3713 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
3714 struct_type = ty::mk_bot();
3719 // Write in the resulting type.
3720 fcx.write_ty(id, struct_type);
3723 fn check_struct_enum_variant(fcx: &FnCtxt,
3725 span: codemap::Span,
3726 enum_id: ast::DefId,
3727 variant_id: ast::DefId,
3728 fields: &[ast::Field]) {
3729 let tcx = fcx.ccx.tcx;
3731 // Look up the number of type parameters and the raw type, and
3732 // determine whether the enum is region-parameterized.
3735 substs: substitutions
3736 } = fcx.instantiate_item_type(span, enum_id);
3738 // Look up and check the enum variant fields.
3739 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3740 check_struct_or_variant_fields(fcx,
3746 variant_fields.as_slice(),
3749 fcx.write_ty(id, enum_type);
3752 fn check_struct_fields_on_error(fcx: &FnCtxt,
3754 fields: &[ast::Field],
3755 base_expr: &Option<P<ast::Expr>>) {
3756 // Make sure to still write the types
3757 // otherwise we might ICE
3758 fcx.write_error(id);
3759 for field in fields.iter() {
3760 check_expr(fcx, &*field.expr);
3763 Some(ref base) => check_expr(fcx, &**base),
3768 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
3770 let tcx = fcx.ccx.tcx;
3773 ast::ExprBox(ref place, ref subexpr) => {
3774 check_expr(fcx, &**place);
3775 check_expr(fcx, &**subexpr);
3777 let mut checked = false;
3779 ast::ExprPath(ref path) => {
3780 // FIXME(pcwalton): For now we hardcode the two permissible
3781 // places: the exchange heap and the managed heap.
3782 let definition = lookup_def(fcx, path.span, place.id);
3783 let def_id = definition.def_id();
3784 let referent_ty = fcx.expr_ty(&**subexpr);
3785 if tcx.lang_items.exchange_heap() == Some(def_id) {
3786 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3788 } else if tcx.lang_items.managed_heap() == Some(def_id) {
3789 fcx.register_region_obligation(infer::Managed(expr.span),
3792 fcx.write_ty(id, ty::mk_box(tcx, referent_ty));
3800 span_err!(tcx.sess, expr.span, E0066,
3801 "only the managed heap and exchange heap are currently supported");
3802 fcx.write_ty(id, ty::mk_err());
3806 ast::ExprLit(ref lit) => {
3807 let typ = check_lit(fcx, &**lit, expected);
3808 fcx.write_ty(id, typ);
3810 ast::ExprBinary(op, ref lhs, ref rhs) => {
3811 check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
3813 let lhs_ty = fcx.expr_ty(&**lhs);
3814 let rhs_ty = fcx.expr_ty(&**rhs);
3815 if ty::type_is_error(lhs_ty) ||
3816 ty::type_is_error(rhs_ty) {
3817 fcx.write_error(id);
3819 else if ty::type_is_bot(lhs_ty) ||
3820 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3824 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3825 check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
3827 let lhs_t = fcx.expr_ty(&**lhs);
3828 let result_t = fcx.expr_ty(expr);
3829 demand::suptype(fcx, expr.span, result_t, lhs_t);
3831 let tcx = fcx.tcx();
3832 if !ty::expr_is_lval(tcx, &**lhs) {
3833 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3836 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
3838 // Overwrite result of check_binop...this preserves existing behavior
3839 // but seems quite dubious with regard to user-defined methods
3840 // and so forth. - Niko
3841 if !ty::type_is_error(result_t)
3842 && !ty::type_is_bot(result_t) {
3843 fcx.write_nil(expr.id);
3846 ast::ExprUnary(unop, ref oprnd) => {
3847 let expected_inner = expected.map(fcx, |sty| {
3849 ast::UnBox | ast::UnUniq => match *sty {
3850 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3857 ast::UnNot | ast::UnNeg => {
3865 let lvalue_pref = match unop {
3866 ast::UnDeref => lvalue_pref,
3869 check_expr_with_expectation_and_lvalue_pref(
3870 fcx, &**oprnd, expected_inner, lvalue_pref);
3871 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3873 if !ty::type_is_error(oprnd_t) {
3876 if !ty::type_is_bot(oprnd_t) {
3877 oprnd_t = ty::mk_box(tcx, oprnd_t)
3881 if !ty::type_is_bot(oprnd_t) {
3882 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3886 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3887 oprnd_t = match ty::deref(oprnd_t, true) {
3889 None => match try_overloaded_deref(fcx, expr.span,
3890 Some(MethodCall::expr(expr.id)),
3891 Some(&**oprnd), oprnd_t, lvalue_pref) {
3894 let is_newtype = match ty::get(oprnd_t).sty {
3895 ty::ty_struct(did, ref substs) => {
3896 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3898 && fields.get(0).ident ==
3899 token::special_idents::unnamed_field
3904 // This is an obsolete struct deref
3905 span_err!(tcx.sess, expr.span, E0068,
3906 "single-field tuple-structs can \
3907 no longer be dereferenced");
3909 fcx.type_error_message(expr.span, |actual| {
3910 format!("type `{}` cannot be \
3911 dereferenced", actual)
3920 if !ty::type_is_bot(oprnd_t) {
3921 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3923 if !(ty::type_is_integral(oprnd_t) ||
3924 ty::get(oprnd_t).sty == ty::ty_bool) {
3925 oprnd_t = check_user_unop(fcx, "!", "not",
3926 tcx.lang_items.not_trait(),
3927 expr, &**oprnd, oprnd_t);
3932 if !ty::type_is_bot(oprnd_t) {
3933 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3935 if !(ty::type_is_integral(oprnd_t) ||
3936 ty::type_is_fp(oprnd_t)) {
3937 oprnd_t = check_user_unop(fcx, "-", "neg",
3938 tcx.lang_items.neg_trait(),
3939 expr, &**oprnd, oprnd_t);
3945 fcx.write_ty(id, oprnd_t);
3947 ast::ExprAddrOf(mutbl, ref oprnd) => {
3948 let expected = expected.only_has_type();
3949 let hint = expected.map(fcx, |sty| {
3950 match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3951 _ => NoExpectation }
3953 let lvalue_pref = match mutbl {
3954 ast::MutMutable => PreferMutLvalue,
3955 ast::MutImmutable => NoPreference
3957 check_expr_with_expectation_and_lvalue_pref(fcx,
3962 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3963 let oprnd_t = if ty::type_is_error(tm.ty) {
3965 } else if ty::type_is_bot(tm.ty) {
3969 // Note: at this point, we cannot say what the best lifetime
3970 // is to use for resulting pointer. We want to use the
3971 // shortest lifetime possible so as to avoid spurious borrowck
3972 // errors. Moreover, the longest lifetime will depend on the
3973 // precise details of the value whose address is being taken
3974 // (and how long it is valid), which we don't know yet until type
3975 // inference is complete.
3977 // Therefore, here we simply generate a region variable. The
3978 // region inferencer will then select the ultimate value.
3979 // Finally, borrowck is charged with guaranteeing that the
3980 // value whose address was taken can actually be made to live
3981 // as long as it needs to live.
3983 // String literals are already, implicitly converted to slices.
3984 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3985 // Empty slices live in static memory.
3986 ast::ExprVec(ref elements) if elements.len() == 0 => {
3987 // Note: we do not assign a lifetime of
3988 // static. This is because the resulting type
3989 // `&'static [T]` would require that T outlives
3991 let region = fcx.infcx().next_region_var(
3992 infer::AddrOfSlice(expr.span));
3993 ty::mk_rptr(tcx, region, tm)
3996 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3997 ty::mk_rptr(tcx, region, tm)
4001 fcx.write_ty(id, oprnd_t);
4003 ast::ExprPath(ref pth) => {
4004 let defn = lookup_def(fcx, pth.span, id);
4005 let pty = polytype_for_def(fcx, expr.span, defn);
4006 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
4008 // We always require that the type provided as the value for
4009 // a type parameter outlives the moment of instantiation.
4010 constrain_path_type_parameters(fcx, expr);
4012 ast::ExprInlineAsm(ref ia) => {
4013 for &(_, ref input) in ia.inputs.iter() {
4014 check_expr(fcx, &**input);
4016 for &(_, ref out, _) in ia.outputs.iter() {
4017 check_expr(fcx, &**out);
4021 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
4022 ast::ExprBreak(_) => { fcx.write_bot(id); }
4023 ast::ExprAgain(_) => { fcx.write_bot(id); }
4024 ast::ExprRet(ref expr_opt) => {
4025 let ret_ty = fcx.ret_ty;
4027 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
4028 ret_ty, ty::mk_nil()) {
4029 Ok(_) => { /* fall through */ }
4031 span_err!(tcx.sess, expr.span, E0069,
4032 "`return;` in function returning non-nil");
4036 check_expr_coercable_to_type(fcx, &**e, ret_ty);
4041 ast::ExprParen(ref a) => {
4042 check_expr_with_expectation_and_lvalue_pref(fcx,
4046 fcx.write_ty(id, fcx.expr_ty(&**a));
4048 ast::ExprAssign(ref lhs, ref rhs) => {
4049 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
4051 let tcx = fcx.tcx();
4052 if !ty::expr_is_lval(tcx, &**lhs) {
4053 span_err!(tcx.sess, expr.span, E0070,
4054 "illegal left-hand side expression");
4057 let lhs_ty = fcx.expr_ty(&**lhs);
4058 check_expr_has_type(fcx, &**rhs, lhs_ty);
4059 let rhs_ty = fcx.expr_ty(&**rhs);
4061 fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
4063 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
4064 fcx.write_error(id);
4065 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
4071 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
4072 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
4073 id, expr.span, expected);
4075 ast::ExprWhile(ref cond, ref body, _) => {
4076 check_expr_has_type(fcx, &**cond, ty::mk_bool());
4077 check_block_no_value(fcx, &**body);
4078 let cond_ty = fcx.expr_ty(&**cond);
4079 let body_ty = fcx.node_ty(body.id);
4080 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
4081 fcx.write_error(id);
4083 else if ty::type_is_bot(cond_ty) {
4090 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
4091 check_expr(fcx, &**head);
4092 let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
4093 vtable2::select_fcx_obligations_where_possible(fcx);
4095 let pcx = pat_ctxt {
4097 map: pat_id_map(&tcx.def_map, &**pat),
4099 _match::check_pat(&pcx, &**pat, typ);
4101 check_block_no_value(fcx, &**block);
4104 ast::ExprLoop(ref body, _) => {
4105 check_block_no_value(fcx, &**body);
4106 if !may_break(tcx, expr.id, &**body) {
4112 ast::ExprMatch(ref discrim, ref arms) => {
4113 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
4115 ast::ExprFnBlock(_, ref decl, ref body) => {
4116 let region = astconv::opt_ast_region_to_region(fcx,
4122 ty::RegionTraitStore(region, ast::MutMutable),
4127 ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
4128 check_unboxed_closure(fcx,
4134 ast::ExprProc(ref decl, ref body) => {
4142 ast::ExprBlock(ref b) => {
4143 check_block_with_expected(fcx, &**b, expected);
4144 fcx.write_ty(id, fcx.node_ty(b.id));
4146 ast::ExprCall(ref f, ref args) => {
4147 // Index expressions need to be handled separately, to inform them
4148 // that they appear in call position.
4149 check_expr(fcx, &**f);
4150 let f_ty = fcx.expr_ty(&**f);
4152 if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
4153 check_call(fcx, expr, &**f, args.as_slice());
4154 let (args_bot, args_err) = args.iter().fold((false, false),
4155 |(rest_bot, rest_err), a| {
4156 // is this not working?
4157 let a_ty = fcx.expr_ty(&**a);
4158 (rest_bot || ty::type_is_bot(a_ty),
4159 rest_err || ty::type_is_error(a_ty))});
4160 if ty::type_is_error(f_ty) || args_err {
4161 fcx.write_error(id);
4163 else if ty::type_is_bot(f_ty) || args_bot {
4168 ast::ExprMethodCall(ident, ref tps, ref args) => {
4169 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
4170 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
4171 let (args_bot, args_err) = arg_tys.fold((false, false),
4172 |(rest_bot, rest_err), a| {
4173 (rest_bot || ty::type_is_bot(a),
4174 rest_err || ty::type_is_error(a))});
4176 fcx.write_error(id);
4177 } else if args_bot {
4181 ast::ExprCast(ref e, ref t) => {
4183 ast::TyFixedLengthVec(_, ref count_expr) => {
4184 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
4188 check_cast(fcx, expr, &**e, &**t);
4190 ast::ExprVec(ref args) => {
4191 let uty = match expected {
4192 ExpectHasType(uty) => {
4193 match ty::get(uty).sty {
4194 ty::ty_vec(ty, _) => Some(ty),
4201 let typ = match uty {
4203 for e in args.iter() {
4204 check_expr_coercable_to_type(fcx, &**e, uty);
4209 let t: ty::t = fcx.infcx().next_ty_var();
4210 for e in args.iter() {
4211 check_expr_has_type(fcx, &**e, t);
4216 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
4217 fcx.write_ty(id, typ);
4219 ast::ExprRepeat(ref element, ref count_expr) => {
4220 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
4221 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
4223 let uty = match expected {
4224 ExpectHasType(uty) => {
4225 match ty::get(uty).sty {
4226 ty::ty_vec(ty, _) => Some(ty),
4233 let (element_ty, t) = match uty {
4235 check_expr_coercable_to_type(fcx, &**element, uty);
4239 let t: ty::t = fcx.infcx().next_ty_var();
4240 check_expr_has_type(fcx, &**element, t);
4241 (fcx.expr_ty(&**element), t)
4246 // For [foo, ..n] where n > 1, `foo` must have
4248 fcx.require_type_meets(
4255 if ty::type_is_error(element_ty) {
4256 fcx.write_error(id);
4257 } else if ty::type_is_bot(element_ty) {
4260 let t = ty::mk_vec(tcx, t, Some(count));
4261 fcx.write_ty(id, t);
4264 ast::ExprTup(ref elts) => {
4265 let expected = expected.only_has_type();
4266 let flds = expected.map_to_option(fcx, |sty| {
4268 ty::ty_tup(ref flds) => Some((*flds).clone()),
4272 let mut bot_field = false;
4273 let mut err_field = false;
4275 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
4276 let t = match flds {
4277 Some(ref fs) if i < fs.len() => {
4278 let ety = *fs.get(i);
4279 check_expr_coercable_to_type(fcx, &**e, ety);
4283 check_expr_with_expectation(fcx, &**e, NoExpectation);
4287 err_field = err_field || ty::type_is_error(t);
4288 bot_field = bot_field || ty::type_is_bot(t);
4293 } else if err_field {
4294 fcx.write_error(id);
4296 let typ = ty::mk_tup(tcx, elt_ts);
4297 fcx.write_ty(id, typ);
4300 ast::ExprStruct(ref path, ref fields, ref base_expr) => {
4301 // Resolve the path.
4302 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
4303 let struct_id = match def {
4304 Some(def::DefVariant(enum_id, variant_id, _)) => {
4305 check_struct_enum_variant(fcx, id, expr.span, enum_id,
4306 variant_id, fields.as_slice());
4309 Some(def::DefTrait(def_id)) => {
4310 span_err!(tcx.sess, path.span, E0159,
4311 "use of trait `{}` as a struct constructor",
4312 pprust::path_to_string(path));
4313 check_struct_fields_on_error(fcx,
4320 // Verify that this was actually a struct.
4321 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4322 match ty::get(typ.ty).sty {
4323 ty::ty_struct(struct_did, _) => {
4324 check_struct_constructor(fcx,
4329 base_expr.as_ref().map(|e| &**e));
4332 span_err!(tcx.sess, path.span, E0071,
4333 "`{}` does not name a structure",
4334 pprust::path_to_string(path));
4335 check_struct_fields_on_error(fcx,
4345 tcx.sess.span_bug(path.span,
4346 "structure constructor wasn't resolved")
4350 // Turn the path into a type and verify that that type unifies with
4351 // the resulting structure type. This is needed to handle type
4352 // parameters correctly.
4353 let actual_structure_type = fcx.expr_ty(&*expr);
4354 if !ty::type_is_error(actual_structure_type) {
4355 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4359 match fcx.mk_subty(false,
4360 infer::Misc(path.span),
4361 actual_structure_type,
4362 type_and_substs.ty) {
4364 Err(type_error) => {
4365 let type_error_description =
4366 ty::type_err_to_str(tcx, &type_error);
4369 .span_err(path.span,
4370 format!("structure constructor specifies a \
4371 structure of type `{}`, but this \
4372 structure has type `{}`: {}",
4374 .ty_to_string(type_and_substs.ty),
4377 actual_structure_type),
4378 type_error_description).as_slice());
4379 ty::note_and_explain_type_err(tcx, &type_error);
4384 fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
4386 ast::ExprField(ref base, ref field, ref tys) => {
4387 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
4389 ast::ExprTupField(ref base, idx, ref tys) => {
4390 check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
4392 ast::ExprIndex(ref base, ref idx) => {
4393 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4394 check_expr(fcx, &**idx);
4395 let raw_base_t = fcx.expr_ty(&**base);
4396 let idx_t = fcx.expr_ty(&**idx);
4397 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
4398 fcx.write_ty(id, raw_base_t);
4399 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
4400 fcx.write_ty(id, idx_t);
4402 let (_, autoderefs, field_ty) =
4403 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
4404 lvalue_pref, |base_t, _| ty::index(base_t));
4407 check_expr_has_type(fcx, &**idx, ty::mk_uint());
4408 fcx.write_ty(id, ty);
4409 fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
4412 // This is an overloaded method.
4413 let base_t = structurally_resolved_type(fcx,
4416 let method_call = MethodCall::expr(expr.id);
4417 match try_overloaded_index(fcx,
4424 Some(mt) => fcx.write_ty(id, mt.ty),
4426 fcx.type_error_message(expr.span,
4436 fcx.write_ty(id, ty::mk_err())
4445 debug!("type of expr({}) {} is...", expr.id,
4446 syntax::print::pprust::expr_to_string(expr));
4447 debug!("... {}, expected is {}",
4448 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4449 expected.repr(tcx));
4454 fn constrain_path_type_parameters(fcx: &FnCtxt,
4457 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4458 for &ty in item_substs.substs.types.iter() {
4459 let default_bound = ty::ReScope(expr.id);
4460 let origin = infer::RelateDefaultParamBound(expr.span, ty);
4461 fcx.register_region_obligation(origin, ty, default_bound);
4467 fn only_has_type(self) -> Expectation {
4469 NoExpectation | ExpectCastableToType(..) => NoExpectation,
4470 ExpectHasType(t) => ExpectHasType(t)
4474 // Resolves `expected` by a single level if it is a variable. If
4475 // there is no expected type or resolution is not possible (e.g.,
4476 // no constraints yet present), just returns `None`.
4477 fn resolve(self, fcx: &FnCtxt) -> Expectation {
4482 ExpectCastableToType(t) => {
4483 ExpectCastableToType(
4484 fcx.infcx().resolve_type_vars_if_possible(t))
4486 ExpectHasType(t) => {
4488 fcx.infcx().resolve_type_vars_if_possible(t))
4493 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
4494 match self.resolve(fcx) {
4495 NoExpectation => NoExpectation,
4496 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4500 fn map_to_option<O>(self,
4502 unpack: |&ty::sty| -> Option<O>)
4505 match self.resolve(fcx) {
4506 NoExpectation => None,
4507 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4512 impl Repr for Expectation {
4513 fn repr(&self, tcx: &ty::ctxt) -> String {
4515 NoExpectation => format!("NoExpectation"),
4516 ExpectHasType(t) => format!("ExpectHasType({})",
4518 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4524 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
4525 if !type_is_uint(fcx, sp, t) {
4526 fcx.type_error_message(sp, |actual| {
4527 format!("mismatched types: expected `uint` type, found `{}`",
4533 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
4534 if !type_is_integral(fcx, sp, t) {
4535 fcx.type_error_message(sp, |actual| {
4536 format!("mismatched types: expected integral type, found `{}`",
4542 pub fn check_decl_initializer(fcx: &FnCtxt,
4546 let local_ty = fcx.local_ty(init.span, nid);
4547 check_expr_coercable_to_type(fcx, init, local_ty)
4550 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4551 let tcx = fcx.ccx.tcx;
4553 let t = fcx.local_ty(local.span, local.id);
4554 fcx.write_ty(local.id, t);
4558 check_decl_initializer(fcx, local.id, &**init);
4559 let init_ty = fcx.expr_ty(&**init);
4560 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
4561 fcx.write_ty(local.id, init_ty);
4567 let pcx = pat_ctxt {
4569 map: pat_id_map(&tcx.def_map, &*local.pat),
4571 _match::check_pat(&pcx, &*local.pat, t);
4572 let pat_ty = fcx.node_ty(local.pat.id);
4573 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
4574 fcx.write_ty(local.id, pat_ty);
4578 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4580 let mut saw_bot = false;
4581 let mut saw_err = false;
4583 ast::StmtDecl(ref decl, id) => {
4586 ast::DeclLocal(ref l) => {
4587 check_decl_local(fcx, &**l);
4588 let l_t = fcx.node_ty(l.id);
4589 saw_bot = saw_bot || ty::type_is_bot(l_t);
4590 saw_err = saw_err || ty::type_is_error(l_t);
4592 ast::DeclItem(_) => {/* ignore for now */ }
4595 ast::StmtExpr(ref expr, id) => {
4597 // Check with expected type of ()
4598 check_expr_has_type(fcx, &**expr, ty::mk_nil());
4599 let expr_ty = fcx.expr_ty(&**expr);
4600 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
4601 saw_err = saw_err || ty::type_is_error(expr_ty);
4603 ast::StmtSemi(ref expr, id) => {
4605 check_expr(fcx, &**expr);
4606 let expr_ty = fcx.expr_ty(&**expr);
4607 saw_bot |= ty::type_is_bot(expr_ty);
4608 saw_err |= ty::type_is_error(expr_ty);
4610 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4613 fcx.write_bot(node_id);
4616 fcx.write_error(node_id);
4619 fcx.write_nil(node_id)
4623 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4624 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
4625 let blkty = fcx.node_ty(blk.id);
4626 if ty::type_is_error(blkty) {
4627 fcx.write_error(blk.id);
4629 else if ty::type_is_bot(blkty) {
4630 fcx.write_bot(blk.id);
4633 let nilty = ty::mk_nil();
4634 demand::suptype(fcx, blk.span, nilty, blkty);
4638 fn check_block_with_expected(fcx: &FnCtxt,
4640 expected: Expectation) {
4642 let mut fcx_ps = fcx.ps.borrow_mut();
4643 let fn_style_state = fcx_ps.recurse(blk);
4644 replace(&mut *fcx_ps, fn_style_state)
4647 let mut warned = false;
4648 let mut last_was_bot = false;
4649 let mut any_bot = false;
4650 let mut any_err = false;
4651 for s in blk.stmts.iter() {
4652 check_stmt(fcx, &**s);
4653 let s_id = ast_util::stmt_id(&**s);
4654 let s_ty = fcx.node_ty(s_id);
4655 if last_was_bot && !warned && match s.node {
4656 ast::StmtDecl(ref decl, _) => {
4658 ast::DeclLocal(_) => true,
4662 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4668 .add_lint(lint::builtin::UNREACHABLE_CODE,
4671 "unreachable statement".to_string());
4674 if ty::type_is_bot(s_ty) {
4675 last_was_bot = true;
4677 any_bot = any_bot || ty::type_is_bot(s_ty);
4678 any_err = any_err || ty::type_is_error(s_ty);
4681 None => if any_err {
4682 fcx.write_error(blk.id);
4684 fcx.write_bot(blk.id);
4686 fcx.write_nil(blk.id);
4689 if any_bot && !warned {
4693 .add_lint(lint::builtin::UNREACHABLE_CODE,
4696 "unreachable expression".to_string());
4698 let ety = match expected {
4699 ExpectHasType(ety) => {
4700 check_expr_coercable_to_type(fcx, &**e, ety);
4704 check_expr_with_expectation(fcx, &**e, expected);
4709 fcx.write_ty(blk.id, ety);
4711 fcx.write_error(blk.id);
4713 fcx.write_bot(blk.id);
4718 *fcx.ps.borrow_mut() = prev;
4721 /// Checks a constant appearing in a type. At the moment this is just the
4722 /// length expression in a fixed-length vector, but someday it might be
4723 /// extended to type-level numeric literals.
4724 pub fn check_const_in_type(tcx: &ty::ctxt,
4726 expected_type: ty::t) {
4727 // Synthesize a crate context. The trait map is not needed here (though I
4728 // imagine it will be if we have associated statics --pcwalton), so we
4730 let ccx = CrateCtxt {
4731 trait_map: NodeMap::new(),
4734 let inh = static_inherited_fields(&ccx);
4735 let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
4736 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4739 pub fn check_const(ccx: &CrateCtxt,
4743 let inh = static_inherited_fields(ccx);
4744 let rty = ty::node_id_to_type(ccx.tcx, id);
4745 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4746 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
4747 check_const_with_ty(&fcx, sp, e, declty);
4750 pub fn check_const_with_ty(fcx: &FnCtxt,
4754 // Gather locals in statics (because of block expressions).
4755 // This is technically unnecessary because locals in static items are forbidden,
4756 // but prevents type checking from blowing up before const checking can properly
4758 GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
4760 check_expr_with_hint(fcx, e, declty);
4761 demand::coerce(fcx, e.span, declty, e);
4762 vtable2::select_all_fcx_obligations_or_error(fcx);
4763 regionck::regionck_expr(fcx, e);
4764 writeback::resolve_type_vars_in_expr(fcx, e);
4765 vtable2::check_builtin_bound_obligations(fcx);
4768 /// Checks whether a type can be represented in memory. In particular, it
4769 /// identifies types that contain themselves without indirection through a
4770 /// pointer, which would mean their size is unbounded. This is different from
4771 /// the question of whether a type can be instantiated. See the definition of
4772 /// `check_instantiable`.
4773 pub fn check_representable(tcx: &ty::ctxt,
4775 item_id: ast::NodeId,
4776 designation: &str) -> bool {
4777 let rty = ty::node_id_to_type(tcx, item_id);
4779 // Check that it is possible to represent this type. This call identifies
4780 // (1) types that contain themselves and (2) types that contain a different
4781 // recursive type. It is only necessary to throw an error on those that
4782 // contain themselves. For case 2, there must be an inner type that will be
4783 // caught by case 1.
4784 match ty::is_type_representable(tcx, sp, rty) {
4785 ty::SelfRecursive => {
4786 span_err!(tcx.sess, sp, E0072,
4787 "illegal recursive {} type; \
4788 wrap the inner value in a box to make it representable",
4792 ty::Representable | ty::ContainsRecursive => (),
4797 /// Checks whether a type can be created without an instance of itself.
4798 /// This is similar but different from the question of whether a type
4799 /// can be represented. For example, the following type:
4801 /// enum foo { None, Some(foo) }
4803 /// is instantiable but is not representable. Similarly, the type
4805 /// enum foo { Some(@foo) }
4807 /// is representable, but not instantiable.
4808 pub fn check_instantiable(tcx: &ty::ctxt,
4810 item_id: ast::NodeId)
4812 let item_ty = ty::node_id_to_type(tcx, item_id);
4813 if !ty::is_instantiable(tcx, item_ty) {
4814 span_err!(tcx.sess, sp, E0073,
4815 "this type cannot be instantiated without an \
4816 instance of itself; consider using `Option<{}>`",
4817 ppaux::ty_to_string(tcx, item_ty));
4824 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4825 let t = ty::node_id_to_type(tcx, id);
4826 if ty::type_needs_subst(t) {
4827 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4830 match ty::get(t).sty {
4831 ty::ty_struct(did, ref substs) => {
4832 let fields = ty::lookup_struct_fields(tcx, did);
4833 if fields.is_empty() {
4834 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4837 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
4838 if !fields.iter().all(
4839 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4840 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4843 if !ty::type_is_machine(e) {
4844 span_err!(tcx.sess, sp, E0077,
4845 "SIMD vector element type should be machine type");
4854 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4855 vs: &[P<ast::Variant>]) {
4856 for v in vs.iter() {
4858 ast::TupleVariantKind(ref args) if args.len() > 0 => {
4859 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4860 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4861 let len = arg_tys.len();
4865 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4866 // Allow the last field in an enum to be unsized.
4867 // We want to do this so that we can support smart pointers.
4868 // A struct value with an unsized final field is itself
4869 // unsized and we must track this in the type system.
4870 if !ty::type_is_sized(ccx.tcx, *t) {
4871 span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4872 "type `{}` is dynamically sized. dynamically sized types may only \
4873 appear as the final type in a variant",
4874 ppaux::ty_to_string(ccx.tcx, *t));
4878 ast::StructVariantKind(ref struct_def) => {
4879 check_fields_sized(ccx.tcx, &**struct_def)
4886 pub fn check_enum_variants(ccx: &CrateCtxt,
4888 vs: &[P<ast::Variant>],
4891 fn disr_in_range(ccx: &CrateCtxt,
4893 disr: ty::Disr) -> bool {
4894 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4896 ast::TyU8 => disr as u8 as Disr == disr,
4897 ast::TyU16 => disr as u16 as Disr == disr,
4898 ast::TyU32 => disr as u32 as Disr == disr,
4899 ast::TyU64 => disr as u64 as Disr == disr,
4900 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4903 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4905 ast::TyI8 => disr as i8 as Disr == disr,
4906 ast::TyI16 => disr as i16 as Disr == disr,
4907 ast::TyI32 => disr as i32 as Disr == disr,
4908 ast::TyI64 => disr as i64 as Disr == disr,
4909 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4913 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4914 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4918 fn do_check(ccx: &CrateCtxt,
4919 vs: &[P<ast::Variant>],
4921 hint: attr::ReprAttr)
4922 -> Vec<Rc<ty::VariantInfo>> {
4924 let rty = ty::node_id_to_type(ccx.tcx, id);
4925 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4926 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4927 let mut prev_disr_val: Option<ty::Disr> = None;
4929 for v in vs.iter() {
4931 // If the discriminant value is specified explicitly in the enum check whether the
4932 // initialization expression is valid, otherwise use the last value plus one.
4933 let mut current_disr_val = match prev_disr_val {
4934 Some(prev_disr_val) => prev_disr_val + 1,
4935 None => ty::INITIAL_DISCRIMINANT_VALUE
4938 match v.node.disr_expr {
4940 debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
4942 let inh = static_inherited_fields(ccx);
4943 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4944 let declty = match hint {
4945 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4946 attr::ReprInt(_, attr::SignedInt(ity)) => {
4947 ty::mk_mach_int(ity)
4949 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4950 ty::mk_mach_uint(ity)
4953 check_const_with_ty(&fcx, e.span, &**e, declty);
4954 // check_expr (from check_const pass) doesn't guarantee
4955 // that the expression is in a form that eval_const_expr can
4956 // handle, so we may still get an internal compiler error
4958 match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
4959 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4960 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4962 span_err!(ccx.tcx.sess, e.span, E0079,
4963 "expected signed integer constant");
4966 span_err!(ccx.tcx.sess, e.span, E0080,
4967 "expected constant: {}", *err);
4974 // Check for duplicate discriminant values
4975 if disr_vals.contains(¤t_disr_val) {
4976 span_err!(ccx.tcx.sess, v.span, E0081,
4977 "discriminant value already exists");
4979 // Check for unrepresentable discriminant values
4981 attr::ReprAny | attr::ReprExtern => (),
4982 attr::ReprInt(sp, ity) => {
4983 if !disr_in_range(ccx, ity, current_disr_val) {
4984 span_err!(ccx.tcx.sess, v.span, E0082,
4985 "discriminant value outside specified type");
4986 span_note!(ccx.tcx.sess, sp,
4987 "discriminant type specified here");
4990 attr::ReprPacked => {
4991 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4994 disr_vals.push(current_disr_val);
4996 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
4998 prev_disr_val = Some(current_disr_val);
5000 variants.push(variant_info);
5006 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
5007 .as_slice().get(0).unwrap_or(&attr::ReprAny);
5009 if hint != attr::ReprAny && vs.len() <= 1 {
5011 span_err!(ccx.tcx.sess, sp, E0083,
5012 "unsupported representation for univariant enum");
5014 span_err!(ccx.tcx.sess, sp, E0084,
5015 "unsupported representation for zero-variant enum");
5019 let variants = do_check(ccx, vs, id, hint);
5021 // cache so that ty::enum_variants won't repeat this work
5022 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
5024 check_representable(ccx.tcx, sp, id, "enum");
5026 // Check that it is possible to instantiate this enum:
5028 // This *sounds* like the same that as representable, but it's
5029 // not. See def'n of `check_instantiable()` for details.
5030 check_instantiable(ccx.tcx, sp, id);
5033 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
5034 lookup_def_ccx(fcx.ccx, sp, id)
5037 // Returns the type parameter count and the type for the given definition.
5038 pub fn polytype_for_def(fcx: &FnCtxt,
5043 def::DefArg(nid, _) | def::DefLocal(nid, _) |
5044 def::DefBinding(nid, _) => {
5045 let typ = fcx.local_ty(sp, nid);
5046 return no_params(typ);
5048 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
5049 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
5050 def::DefStruct(id) => {
5051 return ty::lookup_item_type(fcx.ccx.tcx, id);
5053 def::DefUpvar(_, inner, _, _) => {
5054 return polytype_for_def(fcx, sp, *inner);
5058 def::DefAssociatedTy(..) |
5060 def::DefTyParam(..)=> {
5061 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
5063 def::DefMod(..) | def::DefForeignMod(..) => {
5064 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
5066 def::DefUse(..) => {
5067 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
5069 def::DefRegion(..) => {
5070 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
5072 def::DefTyParamBinder(..) => {
5073 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
5075 def::DefLabel(..) => {
5076 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
5078 def::DefSelfTy(..) => {
5079 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
5081 def::DefMethod(..) => {
5082 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found method");
5087 // Instantiates the given path, which must refer to an item with the given
5088 // number of type parameters and type.
5089 pub fn instantiate_path(fcx: &FnCtxt,
5094 node_id: ast::NodeId) {
5095 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
5096 path.repr(fcx.tcx()),
5097 def.repr(fcx.tcx()),
5099 polytype.repr(fcx.tcx()));
5101 // We need to extract the type parameters supplied by the user in
5102 // the path `path`. Due to the current setup, this is a bit of a
5103 // tricky-process; the problem is that resolve only tells us the
5104 // end-point of the path resolution, and not the intermediate steps.
5105 // Luckily, we can (at least for now) deduce the intermediate steps
5106 // just from the end-point.
5108 // There are basically three cases to consider:
5110 // 1. Reference to a *type*, such as a struct or enum:
5112 // mod a { struct Foo<T> { ... } }
5114 // Because we don't allow types to be declared within one
5115 // another, a path that leads to a type will always look like
5116 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
5117 // that only the final segment can have type parameters, and
5118 // they are located in the TypeSpace.
5120 // *Note:* Generally speaking, references to types don't
5121 // actually pass through this function, but rather the
5122 // `ast_ty_to_ty` function in `astconv`. However, in the case
5123 // of struct patterns (and maybe literals) we do invoke
5124 // `instantiate_path` to get the general type of an instance of
5125 // a struct. (In these cases, there are actually no type
5126 // parameters permitted at present, but perhaps we will allow
5127 // them in the future.)
5129 // 1b. Reference to a enum variant or tuple-like struct:
5131 // struct foo<T>(...)
5132 // enum E<T> { foo(...) }
5134 // In these cases, the parameters are declared in the type
5137 // 2. Reference to a *fn item*:
5141 // In this case, the path will again always have the form
5142 // `a::b::foo::<T>` where only the final segment should have
5143 // type parameters. However, in this case, those parameters are
5144 // declared on a value, and hence are in the `FnSpace`.
5146 // 3. Reference to a *method*:
5148 // impl<A> SomeStruct<A> {
5152 // Here we can have a path like
5153 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
5154 // may appear in two places. The penultimate segment,
5155 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5156 // final segment, `foo::<B>` contains parameters in fn space.
5158 // The first step then is to categorize the segments appropriately.
5160 assert!(path.segments.len() >= 1);
5161 let mut segment_spaces;
5163 // Case 1 and 1b. Reference to a *type* or *enum variant*.
5164 def::DefSelfTy(..) |
5165 def::DefStruct(..) |
5166 def::DefVariant(..) |
5167 def::DefTyParamBinder(..) |
5169 def::DefAssociatedTy(..) |
5171 def::DefPrimTy(..) |
5172 def::DefTyParam(..) => {
5173 // Everything but the final segment should have no
5174 // parameters at all.
5175 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5176 segment_spaces.push(Some(subst::TypeSpace));
5179 // Case 2. Reference to a top-level value.
5181 def::DefStatic(..) => {
5182 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
5183 segment_spaces.push(Some(subst::FnSpace));
5186 // Case 3. Reference to a method.
5187 def::DefStaticMethod(..) => {
5188 assert!(path.segments.len() >= 2);
5189 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
5190 segment_spaces.push(Some(subst::TypeSpace));
5191 segment_spaces.push(Some(subst::FnSpace));
5194 // Other cases. Various nonsense that really shouldn't show up
5195 // here. If they do, an error will have been reported
5196 // elsewhere. (I hope)
5198 def::DefForeignMod(..) |
5201 def::DefMethod(..) |
5202 def::DefBinding(..) |
5204 def::DefRegion(..) |
5206 def::DefUpvar(..) => {
5207 segment_spaces = Vec::from_elem(path.segments.len(), None);
5210 assert_eq!(segment_spaces.len(), path.segments.len());
5212 debug!("segment_spaces={}", segment_spaces);
5214 // Next, examine the definition, and determine how many type
5215 // parameters we expect from each space.
5216 let type_defs = &polytype.generics.types;
5217 let region_defs = &polytype.generics.regions;
5219 // Now that we have categorized what space the parameters for each
5220 // segment belong to, let's sort out the parameters that the user
5221 // provided (if any) into their appropriate spaces. We'll also report
5222 // errors if type parameters are provided in an inappropriate place.
5223 let mut substs = Substs::empty();
5224 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
5227 report_error_if_segment_contains_type_parameters(fcx, segment);
5231 push_explicit_parameters_from_segment_to_substs(fcx,
5241 // Now we have to compare the types that the user *actually*
5242 // provided against the types that were *expected*. If the user
5243 // did not provide any types, then we want to substitute inference
5244 // variables. If the user provided some types, we may still need
5245 // to add defaults. If the user provided *too many* types, that's
5247 for &space in ParamSpace::all().iter() {
5248 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
5249 assert_eq!(substs.types.len(space), type_defs.len(space));
5251 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
5252 assert_eq!(substs.regions().len(space), region_defs.len(space));
5255 fcx.add_obligations_for_parameters(
5256 traits::ObligationCause::new(span,
5257 traits::ItemObligation(def.def_id())),
5259 &polytype.generics);
5261 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
5265 fn report_error_if_segment_contains_type_parameters(
5267 segment: &ast::PathSegment)
5269 for typ in segment.types.iter() {
5270 span_err!(fcx.tcx().sess, typ.span, E0085,
5271 "type parameters may not appear here");
5275 for lifetime in segment.lifetimes.iter() {
5276 span_err!(fcx.tcx().sess, lifetime.span, E0086,
5277 "lifetime parameters may not appear here");
5282 fn push_explicit_parameters_from_segment_to_substs(
5284 space: subst::ParamSpace,
5285 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
5286 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
5287 segment: &ast::PathSegment,
5288 substs: &mut Substs)
5291 * Finds the parameters that the user provided and adds them
5292 * to `substs`. If too many parameters are provided, then
5293 * reports an error and clears the output vector.
5295 * We clear the output vector because that will cause the
5296 * `adjust_XXX_parameters()` later to use inference
5297 * variables. This seems less likely to lead to derived
5300 * Note that we *do not* check for *too few* parameters here.
5301 * Due to the presence of defaults etc that is more
5302 * complicated. I wanted however to do the reporting of *too
5303 * many* parameters here because we can easily use the precise
5304 * span of the N+1'th parameter.
5308 let type_count = type_defs.len(space);
5309 assert_eq!(substs.types.len(space), 0);
5310 for (i, typ) in segment.types.iter().enumerate() {
5311 let t = fcx.to_ty(&**typ);
5313 substs.types.push(space, t);
5314 } else if i == type_count {
5315 span_err!(fcx.tcx().sess, typ.span, E0087,
5316 "too many type parameters provided: \
5317 expected at most {} parameter(s), \
5318 found {} parameter(s)",
5319 type_count, segment.types.len());
5320 substs.types.truncate(space, 0);
5326 let region_count = region_defs.len(space);
5327 assert_eq!(substs.regions().len(space), 0);
5328 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
5329 let r = ast_region_to_region(fcx.tcx(), lifetime);
5330 if i < region_count {
5331 substs.mut_regions().push(space, r);
5332 } else if i == region_count {
5333 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5334 "too many lifetime parameters provided: \
5335 expected {} parameter(s), found {} parameter(s)",
5337 segment.lifetimes.len());
5338 substs.mut_regions().truncate(space, 0);
5344 fn adjust_type_parameters(
5348 defs: &VecPerParamSpace<ty::TypeParameterDef>,
5349 substs: &mut Substs)
5351 let provided_len = substs.types.len(space);
5352 let desired = defs.get_slice(space);
5353 let required_len = desired.iter()
5354 .take_while(|d| d.default.is_none())
5357 debug!("adjust_type_parameters(space={}, \
5366 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5367 assert!(provided_len <= desired.len());
5369 // Nothing specified at all: supply inference variables for
5371 if provided_len == 0 {
5372 substs.types.replace(space,
5373 fcx.infcx().next_ty_vars(desired.len()));
5377 // Too few parameters specified: report an error and use Err
5379 if provided_len < required_len {
5381 if desired.len() != required_len { "at least " } else { "" };
5382 span_err!(fcx.tcx().sess, span, E0089,
5383 "too few type parameters provided: expected {}{} parameter(s) \
5384 , found {} parameter(s)",
5385 qualifier, required_len, provided_len);
5386 substs.types.replace(space,
5387 Vec::from_elem(desired.len(), ty::mk_err()));
5391 // Otherwise, add in any optional parameters that the user
5392 // omitted. The case of *too many* parameters is handled
5394 // push_explicit_parameters_from_segment_to_substs(). Note
5395 // that the *default* type are expressed in terms of all prior
5396 // parameters, so we have to substitute as we go with the
5397 // partial substitution that we have built up.
5398 for i in range(provided_len, desired.len()) {
5399 let default = desired[i].default.unwrap();
5400 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5401 substs.types.push(space, default);
5403 assert_eq!(substs.types.len(space), desired.len());
5405 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5408 fn adjust_region_parameters(
5412 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5413 substs: &mut Substs)
5415 let provided_len = substs.mut_regions().len(space);
5416 let desired = defs.get_slice(space);
5418 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5419 assert!(provided_len <= desired.len());
5421 // If nothing was provided, just use inference variables.
5422 if provided_len == 0 {
5423 substs.mut_regions().replace(
5425 fcx.infcx().region_vars_for_defs(span, desired));
5429 // If just the right number were provided, everybody is happy.
5430 if provided_len == desired.len() {
5434 // Otherwise, too few were provided. Report an error and then
5435 // use inference variables.
5436 span_err!(fcx.tcx().sess, span, E0090,
5437 "too few lifetime parameters provided: expected {} parameter(s), \
5438 found {} parameter(s)",
5439 desired.len(), provided_len);
5441 substs.mut_regions().replace(
5443 fcx.infcx().region_vars_for_defs(span, desired));
5447 // Resolves `typ` by a single level if `typ` is a type variable. If no
5448 // resolution is possible, then an error is reported.
5449 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
5450 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
5451 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
5453 fcx.type_error_message(sp, |_actual| {
5454 "the type of this value must be known in this \
5455 context".to_string()
5457 demand::suptype(fcx, sp, ty::mk_err(), tp);
5463 // Returns the one-level-deep structure of the given type.
5464 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
5466 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
5469 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5470 let typ_s = structurally_resolved_type(fcx, sp, typ);
5471 return ty::type_is_integral(typ_s);
5474 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5475 let typ_s = structurally_resolved_type(fcx, sp, typ);
5476 return ty::type_is_uint(typ_s);
5479 pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5480 let typ_s = structurally_resolved_type(fcx, sp, typ);
5481 return ty::type_is_scalar(typ_s);
5484 pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5485 let typ_s = structurally_resolved_type(fcx, sp, typ);
5486 return ty::type_is_char(typ_s);
5489 pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5490 let typ_s = structurally_resolved_type(fcx, sp, typ);
5491 return ty::type_is_bare_fn(typ_s);
5494 pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5495 let typ_s = structurally_resolved_type(fcx, sp, typ);
5496 return ty::type_is_floating_point(typ_s);
5499 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5500 let typ_s = structurally_resolved_type(fcx, sp, typ);
5501 return ty::type_is_unsafe_ptr(typ_s);
5504 pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5505 let typ_s = structurally_resolved_type(fcx, sp, typ);
5506 return ty::type_is_region_ptr(typ_s);
5509 pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5510 let typ_s = structurally_resolved_type(fcx, sp, typ);
5511 return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
5514 // Returns true if b contains a break that can exit from b
5515 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
5516 // First: is there an unlabeled break immediately
5518 (loop_query(&*b, |e| {
5520 ast::ExprBreak(_) => true,
5524 // Second: is there a labeled break with label
5525 // <id> nested anywhere inside the loop?
5526 (block_query(b, |e| {
5528 ast::ExprBreak(Some(_)) => {
5529 match cx.def_map.borrow().find(&e.id) {
5530 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5538 pub fn check_bounds_are_used(ccx: &CrateCtxt,
5540 tps: &OwnedSlice<ast::TyParam>,
5542 debug!("check_bounds_are_used(n_tps={}, ty={})",
5543 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5545 // make a vector of booleans initially false, set to true when used
5546 if tps.len() == 0u { return; }
5547 let mut tps_used = Vec::from_elem(tps.len(), false);
5549 ty::walk_ty(ty, |t| {
5550 match ty::get(t).sty {
5551 ty::ty_param(ParamTy {idx, ..}) => {
5552 debug!("Found use of ty param num {}", idx);
5553 *tps_used.get_mut(idx) = true;
5559 for (i, b) in tps_used.iter().enumerate() {
5561 span_err!(ccx.tcx.sess, span, E0091,
5562 "type parameter `{}` is unused",
5563 token::get_ident(tps.get(i).ident));
5568 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5569 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
5570 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5574 let name = token::get_ident(it.ident);
5575 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5576 let split : Vec<&str> = name.get().split('_').collect();
5577 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5579 //We only care about the operation here
5580 match *split.get(1) {
5581 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5585 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5587 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5590 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5591 "min" | "umax" | "umin" => {
5592 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5596 (0, Vec::new(), ty::mk_nil())
5599 span_err!(tcx.sess, it.span, E0092,
5600 "unrecognized atomic operation function: `{}`", op);
5607 "abort" => (0, Vec::new(), ty::mk_bot()),
5608 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
5610 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5611 "init" => (1u, Vec::new(), param(ccx, 0u)),
5612 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5613 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
5614 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5615 "move_val_init" => {
5618 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
5623 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5624 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5627 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5629 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5631 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5633 mutbl: ast::MutImmutable
5635 (1u, Vec::new(), td_ptr)
5638 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5642 ty::mk_struct(ccx.tcx, did,
5643 subst::Substs::empty())),
5645 tcx.sess.span_fatal(it.span, msg.as_slice());
5650 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5652 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5654 let region0 = ty::ReLateBound(it.id, ty::BrAnon(0));
5655 let region1 = ty::ReLateBound(it.id, ty::BrAnon(1));
5656 let visitor_object_ty =
5657 match ty::visitor_object_ty(tcx, region0, region1) {
5658 Ok((_, vot)) => vot,
5659 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5662 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5664 mutbl: ast::MutImmutable
5666 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
5671 ty::mk_ptr(tcx, ty::mt {
5673 mutbl: ast::MutImmutable
5677 ty::mk_ptr(tcx, ty::mt {
5679 mutbl: ast::MutImmutable
5682 "copy_memory" | "copy_nonoverlapping_memory" |
5683 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5686 ty::mk_ptr(tcx, ty::mt {
5688 mutbl: ast::MutMutable
5690 ty::mk_ptr(tcx, ty::mt {
5692 mutbl: ast::MutImmutable
5698 "set_memory" | "volatile_set_memory" => {
5701 ty::mk_ptr(tcx, ty::mt {
5703 mutbl: ast::MutMutable
5710 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5711 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5714 vec!( ty::mk_f32(), ty::mk_i32() ),
5719 vec!( ty::mk_f64(), ty::mk_i32() ),
5722 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5723 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5724 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5725 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5728 vec!( ty::mk_f32(), ty::mk_f32() ),
5733 vec!( ty::mk_f64(), ty::mk_f64() ),
5736 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5737 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5738 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5739 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5740 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5741 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5742 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5743 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5744 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5745 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5748 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5753 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5756 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5757 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5758 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5759 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5760 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5761 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5762 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5763 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5764 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5765 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5766 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5767 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5768 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5769 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5770 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5771 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5772 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5773 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5774 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5775 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5776 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5777 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5778 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5779 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5780 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5781 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5782 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5783 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5784 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5785 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5786 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5789 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5791 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
5793 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5794 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5795 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5797 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5798 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5799 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5801 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5802 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5803 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5805 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5806 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5807 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5809 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5810 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5811 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5813 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5814 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5815 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5817 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5818 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5819 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5821 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5822 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5823 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5825 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5828 span_err!(tcx.sess, it.span, E0093,
5829 "unrecognized intrinsic function: `{}`", *other);
5834 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5835 fn_style: ast::UnsafeFn,
5836 abi: abi::RustIntrinsic,
5844 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5845 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5846 if i_n_tps != n_tps {
5847 span_err!(tcx.sess, it.span, E0094,
5848 "intrinsic has wrong number of type \
5849 parameters: found {}, expected {}",
5852 require_same_types(tcx,
5859 format!("intrinsic has wrong type: expected `{}`",
5860 ppaux::ty_to_string(ccx.tcx, fty))
5865 impl Repr for RegionObligation {
5866 fn repr(&self, tcx: &ty::ctxt) -> String {
5867 format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5868 self.sub_region.repr(tcx),
5869 self.sup_type.repr(tcx),
5870 self.origin.repr(tcx))