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};
90 use middle::ty::{FnSig, VariantInfo};
91 use middle::ty::{Polytype};
92 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
94 use middle::ty_fold::TypeFolder;
95 use middle::typeck::astconv::AstConv;
96 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
97 use middle::typeck::astconv;
98 use middle::typeck::check::_match::pat_ctxt;
99 use middle::typeck::check::method::{AutoderefReceiver};
100 use middle::typeck::check::method::{AutoderefReceiverFlag};
101 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
102 use middle::typeck::check::method::{DontAutoderefReceiver};
103 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
104 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
105 use middle::typeck::check::vtable::VtableContext;
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, vtable_map};
113 use middle::typeck::{MethodCall, MethodMap};
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};
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;
141 use syntax::visit::Visitor;
152 /// Fields that are part of a `FnCtxt` which are inherited by
153 /// closures defined within the function. For example:
156 /// bar(proc() { ... })
159 /// Here, the function `foo()` and the closure passed to
160 /// `bar()` will each have their own `FnCtxt`, but they will
161 /// share the inherited fields.
162 pub struct Inherited<'a, 'tcx: 'a> {
163 infcx: infer::InferCtxt<'a, 'tcx>,
164 locals: RefCell<NodeMap<ty::t>>,
165 param_env: ty::ParameterEnvironment,
168 node_types: RefCell<NodeMap<ty::t>>,
169 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
170 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
171 method_map: MethodMap,
172 vtable_map: vtable_map,
173 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
174 unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
176 // A mapping from each fn's id to its signature, with all bound
177 // regions replaced with free ones. Unlike the other tables, this
178 // one is never copied into the tcx: it is only used by regionck.
179 fn_sig_map: RefCell<NodeMap<Vec<ty::t>>>,
181 // A set of constraints that regionck must validate. Each
182 // constraint has the form `T:'a`, meaning "some type `T` must
183 // outlive the lifetime 'a". These constraints derive from
184 // instantiated type parameters. So if you had a struct defined
187 // struct Foo<T:'static> { ... }
189 // then in some expression `let x = Foo { ... }` it will
190 // instantiate the type parameter `T` with a fresh type `$0`. At
191 // the same time, it will record a region obligation of
192 // `$0:'static`. This will get checked later by regionck. (We
193 // can't generally check these things right away because we have
194 // to wait until types are resolved.)
196 // These are stored in a map keyed to the id of the innermost
197 // enclosing fn body / static initializer expression. This is
198 // because the location where the obligation was incurred can be
199 // relevant with respect to which sublifetime assumptions are in
200 // place. The reason that we store under the fn-id, and not
201 // something more fine-grained, is so that it is easier for
202 // regionck to be sure that it has found *all* the region
203 // obligations (otherwise, it's easy to fail to walk to a
204 // particular node-id).
205 region_obligations: RefCell<NodeMap<Vec<RegionObligation>>>,
208 struct RegionObligation {
209 sub_region: ty::Region,
211 origin: infer::SubregionOrigin,
214 /// When type-checking an expression, we propagate downward
215 /// whatever type hint we are able in the form of an `Expectation`.
217 /// We know nothing about what type this expression should have.
220 /// This expression should have the type given (or some subtype)
221 ExpectHasType(ty::t),
223 /// This expression will be cast to the `ty::t`
224 ExpectCastableToType(ty::t),
228 pub struct FnStyleState {
229 pub def: ast::NodeId,
230 pub fn_style: ast::FnStyle,
235 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
236 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
239 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
240 match self.fn_style {
241 // If this unsafe, then if the outer function was already marked as
242 // unsafe we shouldn't attribute the unsafe'ness to the block. This
243 // way the block can be warned about instead of ignoring this
244 // extraneous block (functions are never warned about).
245 ast::UnsafeFn if self.from_fn => *self,
248 let (fn_style, def) = match blk.rules {
249 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
250 ast::DefaultBlock => (fn_style, self.def),
252 FnStyleState{ def: def,
260 /// Whether `check_binop` is part of an assignment or not.
261 /// Used to know whether we allow user overloads and to print
262 /// better messages on error.
263 #[deriving(PartialEq)]
264 enum IsBinopAssignment{
270 pub struct FnCtxt<'a, 'tcx: 'a> {
271 body_id: ast::NodeId,
273 // This flag is set to true if, during the writeback phase, we encounter
274 // a type error in this function.
275 writeback_errors: Cell<bool>,
277 // Number of errors that had been reported when we started
278 // checking this function. On exit, if we find that *more* errors
279 // have been reported, we will skip regionck and other work that
280 // expects the types within the function to be consistent.
281 err_count_on_creation: uint,
285 ps: RefCell<FnStyleState>,
287 inh: &'a Inherited<'a, 'tcx>,
289 ccx: &'a CrateCtxt<'a, 'tcx>,
292 impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
293 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
296 fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
297 self.ccx.tcx.node_ty(id)
299 fn node_method_ty(&self, method_call: typeck::MethodCall)
301 self.ccx.tcx.node_method_ty(method_call)
303 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
304 self.ccx.tcx.adjustments()
306 fn is_method_call(&self, id: ast::NodeId) -> bool {
307 self.ccx.tcx.is_method_call(id)
309 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
310 self.ccx.tcx.temporary_scope(rvalue_id)
312 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
313 self.ccx.tcx.upvar_borrow(upvar_id)
315 fn capture_mode(&self, closure_expr_id: ast::NodeId)
316 -> freevars::CaptureMode {
317 self.ccx.tcx.capture_mode(closure_expr_id)
319 fn unboxed_closures<'a>(&'a self)
320 -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
321 &self.inh.unboxed_closures
325 impl<'a, 'tcx> Inherited<'a, 'tcx> {
326 fn new(tcx: &'a ty::ctxt<'tcx>,
327 param_env: ty::ParameterEnvironment)
328 -> Inherited<'a, 'tcx> {
330 infcx: infer::new_infer_ctxt(tcx),
331 locals: RefCell::new(NodeMap::new()),
332 param_env: param_env,
333 node_types: RefCell::new(NodeMap::new()),
334 item_substs: RefCell::new(NodeMap::new()),
335 adjustments: RefCell::new(NodeMap::new()),
336 method_map: RefCell::new(FnvHashMap::new()),
337 vtable_map: RefCell::new(FnvHashMap::new()),
338 upvar_borrow_map: RefCell::new(HashMap::new()),
339 unboxed_closures: RefCell::new(DefIdMap::new()),
340 fn_sig_map: RefCell::new(NodeMap::new()),
341 region_obligations: RefCell::new(NodeMap::new()),
346 // Used by check_const and check_enum_variants
347 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
348 inh: &'a Inherited<'a, 'tcx>,
350 body_id: ast::NodeId)
351 -> FnCtxt<'a, 'tcx> {
354 writeback_errors: Cell::new(false),
355 err_count_on_creation: ccx.tcx.sess.err_count(),
357 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
363 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
364 -> Inherited<'a, 'tcx> {
365 // It's kind of a kludge to manufacture a fake function context
366 // and statement context, but we might as well do write the code only once
367 let param_env = ty::ParameterEnvironment {
368 free_substs: subst::Substs::empty(),
369 bounds: subst::VecPerParamSpace::empty(),
370 implicit_region_bound: ty::ReStatic,
372 Inherited::new(ccx.tcx, param_env)
375 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
376 struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> }
378 impl<'a, 'tcx> Visitor<()> for CheckTypeWellFormedVisitor<'a, 'tcx> {
379 fn visit_item(&mut self, i: &ast::Item, _: ()) {
380 check_type_well_formed(self.ccx, i);
381 visit::walk_item(self, i, ());
386 impl<'a, 'tcx> Visitor<()> for CheckItemTypesVisitor<'a, 'tcx> {
387 fn visit_item(&mut self, i: &ast::Item, _: ()) {
388 check_item(self.ccx, i);
389 visit::walk_item(self, i, ());
393 struct CheckItemSizedTypesVisitor<'a, 'tcx: 'a> {
394 ccx: &'a CrateCtxt<'a, 'tcx>
397 impl<'a, 'tcx> Visitor<()> for CheckItemSizedTypesVisitor<'a, 'tcx> {
398 fn visit_item(&mut self, i: &ast::Item, _: ()) {
399 check_item_sized(self.ccx, i);
400 visit::walk_item(self, i, ());
404 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
405 let mut visit = CheckTypeWellFormedVisitor { ccx: ccx };
406 visit::walk_crate(&mut visit, krate, ());
408 // If types are not well-formed, it leads to all manner of errors
409 // downstream, so stop reporting errors at this point.
410 ccx.tcx.sess.abort_if_errors();
412 let mut visit = CheckItemTypesVisitor { ccx: ccx };
413 visit::walk_crate(&mut visit, krate, ());
415 ccx.tcx.sess.abort_if_errors();
417 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
418 visit::walk_crate(&mut visit, krate, ());
421 fn check_bare_fn(ccx: &CrateCtxt,
426 param_env: ty::ParameterEnvironment) {
427 // Compute the fty from point of view of inside fn
428 // (replace any type-scheme with a type)
429 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
431 match ty::get(fty).sty {
432 ty::ty_bare_fn(ref fn_ty) => {
433 let inh = Inherited::new(ccx.tcx, param_env);
434 let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
435 decl, id, body, &inh);
437 vtable::resolve_in_block(&fcx, body);
438 regionck::regionck_fn(&fcx, id, body);
439 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
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, nid: ast::NodeId, ty_opt: Option<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);
460 // take type that the user specified
461 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
467 impl<'a, 'tcx> Visitor<()> for GatherLocalsVisitor<'a, 'tcx> {
468 // Add explicitly-declared locals.
469 fn visit_local(&mut self, local: &ast::Local, _: ()) {
470 let o_ty = match local.ty.node {
471 ast::TyInfer => None,
472 _ => Some(self.fcx.to_ty(&*local.ty))
474 self.assign(local.id, o_ty);
475 debug!("Local variable {} is assigned type {}",
476 self.fcx.pat_to_string(&*local.pat),
477 self.fcx.infcx().ty_to_string(
478 self.fcx.inh.locals.borrow().get_copy(&local.id)));
479 visit::walk_local(self, local, ());
482 // Add pattern bindings.
483 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
485 ast::PatIdent(_, ref path1, _)
486 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
487 self.assign(p.id, None);
488 debug!("Pattern binding {} is assigned to {}",
489 token::get_ident(path1.node),
490 self.fcx.infcx().ty_to_string(
491 self.fcx.inh.locals.borrow().get_copy(&p.id)));
495 visit::walk_pat(self, p, ());
499 fn visit_block(&mut self, b: &ast::Block, _: ()) {
500 // non-obvious: the `blk` variable maps to region lb, so
501 // we have to keep this up-to-date. This
502 // is... unfortunate. It'd be nice to not need this.
503 visit::walk_block(self, b, ());
506 // Since an expr occurs as part of the type fixed size arrays we
507 // need to record the type for that node
508 fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
510 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
511 self.visit_ty(&**ty, ());
512 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
514 _ => visit::walk_ty(self, t, ())
518 // Don't descend into fns and items
519 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
520 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
521 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
525 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
526 fn_style: ast::FnStyle,
527 fn_style_id: ast::NodeId,
532 inherited: &'a Inherited<'a, 'tcx>)
533 -> FnCtxt<'a, 'tcx> {
535 * Helper used by check_bare_fn and check_expr_fn. Does the
536 * grungy work of checking a function body and returns the
537 * function context used for that purpose, since in the case of a
538 * fn item there is still a bit more to do.
541 * - inherited: other fields inherited from the enclosing fn (if any)
545 let err_count_on_creation = tcx.sess.err_count();
547 // First, we have to replace any bound regions in the fn type with free ones.
548 // The free region references will be bound the node_id of the body block.
549 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
550 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
553 let arg_tys = fn_sig.inputs.as_slice();
554 let ret_ty = fn_sig.output;
556 debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
561 // Create the function context. This is either derived from scratch or,
562 // in the case of function expressions, based on the outer context.
565 writeback_errors: Cell::new(false),
566 err_count_on_creation: err_count_on_creation,
568 ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)),
573 // Remember return type so that regionck can access it later.
574 let fn_sig_tys: Vec<ty::t> =
576 .chain([ret_ty].iter())
579 debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
581 fn_sig_tys.repr(tcx));
584 .insert(fn_id, fn_sig_tys);
587 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
589 // Add formal parameters.
590 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
591 // Create type variables for each argument.
592 pat_util::pat_bindings(&tcx.def_map,
594 |_bm, pat_id, _sp, _path| {
595 visit.assign(pat_id, None);
598 // Check the pattern.
601 map: pat_id_map(&tcx.def_map, &*input.pat),
603 _match::check_pat(&pcx, &*input.pat, *arg_ty);
606 visit.visit_block(body, ());
609 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
611 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
612 fcx.write_ty(input.id, *arg);
618 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
619 assert!(field.id.krate == ast::LOCAL_CRATE);
620 let item = match tcx.map.find(struct_id.node) {
621 Some(ast_map::NodeItem(item)) => item,
622 None => fail!("node not in ast map: {}", struct_id.node),
623 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
627 ast::ItemStruct(struct_def, _) => {
628 match struct_def.fields.iter().find(|f| match f.node.kind {
629 ast::NamedField(ident, _) => ident.name == field.name,
635 .bug(format!("Could not find field {}",
636 token::get_name(field.name)).as_slice())
640 _ => tcx.sess.bug("Field found outside of a struct?"),
644 // Check struct fields are uniquely named wrt parents.
645 fn check_for_field_shadowing(tcx: &ty::ctxt,
647 let struct_fields = tcx.struct_fields.borrow();
648 let fields = struct_fields.get(&id);
650 let superstructs = tcx.superstructs.borrow();
651 let super_struct = superstructs.get(&id);
652 match *super_struct {
654 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
655 for f in fields.iter() {
656 match super_fields.iter().find(|sf| f.name == sf.name) {
657 Some(prev_field) => {
658 span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
659 "field `{}` hides field declared in super-struct",
660 token::get_name(f.name));
661 span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
662 "previously declared here");
672 fn check_fields_sized(tcx: &ty::ctxt,
673 struct_def: &ast::StructDef) {
674 let len = struct_def.fields.len();
678 for f in struct_def.fields.slice_to(len - 1).iter() {
679 let t = ty::node_id_to_type(tcx, f.node.id);
680 if !ty::type_is_sized(tcx, t) {
682 ast::NamedField(ident, _) => {
683 span_err!(tcx.sess, f.span, E0042,
684 "type `{}` is dynamically sized. \
685 dynamically sized types may only \
686 appear as the type of the final \
688 token::get_ident(ident));
690 ast::UnnamedField(_) => {
691 span_err!(tcx.sess, f.span, E0043,
692 "dynamically sized type in field");
699 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
702 check_representable(tcx, span, id, "struct");
703 check_instantiable(tcx, span, id);
705 // Check there are no overlapping fields in super-structs
706 check_for_field_shadowing(tcx, local_def(id));
708 if ty::lookup_simd(tcx, local_def(id)) {
709 check_simd(tcx, span, id);
713 fn check_type_well_formed(ccx: &CrateCtxt, item: &ast::Item) {
715 * Checks that the field types (in a struct def'n) or
716 * argument types (in an enum def'n) are well-formed,
717 * meaning that they do not require any constraints not
718 * declared in the struct definition itself.
719 * For example, this definition would be illegal:
721 * struct Ref<'a, T> { x: &'a T }
723 * because the type did not declare that `T:'a`.
725 * We do this check as a pre-pass before checking fn bodies
726 * because if these constraints are not included it frequently
727 * leads to confusing errors in fn bodies. So it's better to check
731 debug!("check_type_well_formed(it.id={}, it.ident={})",
733 ty::item_path_str(ccx.tcx, local_def(item.id)));
736 ast::ItemStruct(..) => {
737 check_type_defn(ccx, item, |fcx| {
738 ty::struct_fields(ccx.tcx, local_def(item.id),
739 &fcx.inh.param_env.free_substs)
745 ast::ItemEnum(..) => {
746 check_type_defn(ccx, item, |fcx| {
747 ty::substd_enum_variants(ccx.tcx, local_def(item.id),
748 &fcx.inh.param_env.free_substs)
750 .flat_map(|variant| {
753 .map(|&arg_ty| arg_ty)
761 fn check_type_defn(ccx: &CrateCtxt,
763 lookup_fields: |&FnCtxt| -> Vec<ty::t>)
765 let item_def_id = local_def(item.id);
766 let polytype = ty::lookup_item_type(ccx.tcx, item_def_id);
768 ty::construct_parameter_environment(ccx.tcx,
771 let inh = Inherited::new(ccx.tcx, param_env);
772 let fcx = blank_fn_ctxt(ccx, &inh, polytype.ty, item.id);
773 let field_tys = lookup_fields(&fcx);
774 regionck::regionck_type_defn(&fcx, item.span, field_tys.as_slice());
778 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
779 debug!("check_item(it.id={}, it.ident={})",
781 ty::item_path_str(ccx.tcx, local_def(it.id)));
782 let _indenter = indenter();
785 ast::ItemEnum(ref enum_definition, _) => {
786 check_enum_variants_sized(ccx,
787 enum_definition.variants.as_slice());
789 ast::ItemStruct(..) => {
790 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
796 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
797 debug!("check_item(it.id={}, it.ident={})",
799 ty::item_path_str(ccx.tcx, local_def(it.id)));
800 let _indenter = indenter();
803 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
804 ast::ItemEnum(ref enum_definition, _) => {
805 check_enum_variants(ccx,
807 enum_definition.variants.as_slice(),
810 ast::ItemFn(ref decl, _, _, _, ref body) => {
811 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
812 let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
813 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
815 ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
816 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
818 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
819 for impl_item in impl_items.iter() {
821 ast::MethodImplItem(m) => {
822 check_method_body(ccx, &impl_pty.generics, &*m);
827 match *opt_trait_ref {
828 Some(ref ast_trait_ref) => {
830 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
831 check_impl_items_against_trait(ccx,
835 impl_items.as_slice());
836 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
842 ast::ItemTrait(_, _, _, ref trait_methods) => {
843 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
844 for trait_method in (*trait_methods).iter() {
845 match *trait_method {
846 RequiredMethod(..) => {
847 // Nothing to do, since required methods don't have
850 ProvidedMethod(m) => {
851 check_method_body(ccx, &trait_def.generics, &*m);
856 ast::ItemStruct(..) => {
857 check_struct(ccx, it.id, it.span);
859 ast::ItemTy(ref t, ref generics) => {
860 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
861 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
863 ast::ItemForeignMod(ref m) => {
864 if m.abi == abi::RustIntrinsic {
865 for item in m.items.iter() {
866 check_intrinsic_type(ccx, &**item);
869 for item in m.items.iter() {
870 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
871 if !pty.generics.types.is_empty() {
872 span_err!(ccx.tcx.sess, item.span, E0044,
873 "foreign items may not have type parameters");
877 ast::ForeignItemFn(ref fn_decl, _) => {
878 if fn_decl.variadic && m.abi != abi::C {
879 span_err!(ccx.tcx.sess, item.span, E0045,
880 "variadic function must have C calling convention");
888 _ => {/* nothing to do */ }
892 fn check_method_body(ccx: &CrateCtxt,
893 item_generics: &ty::Generics,
894 method: &ast::Method) {
896 * Type checks a method body.
899 * - `item_generics`: generics defined on the impl/trait that contains
901 * - `self_bound`: bound for the `Self` type parameter, if any
902 * - `method`: the method definition
905 debug!("check_method_body(item_generics={}, method.id={})",
906 item_generics.repr(ccx.tcx),
908 let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
910 let fty = ty::node_id_to_type(ccx.tcx, method.id);
913 &*method.pe_fn_decl(),
920 fn check_impl_items_against_trait(ccx: &CrateCtxt,
922 ast_trait_ref: &ast::TraitRef,
923 impl_trait_ref: &ty::TraitRef,
924 impl_items: &[ast::ImplItem]) {
925 // Locate trait methods
927 let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
929 // Check existing impl methods to see if they are both present in trait
930 // and compatible with trait signature
931 for impl_item in impl_items.iter() {
933 ast::MethodImplItem(impl_method) => {
934 let impl_method_def_id = local_def(impl_method.id);
935 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
938 // If this is an impl of a trait method, find the
939 // corresponding method definition in the trait.
940 let opt_trait_method_ty =
943 ti.ident().name == impl_item_ty.ident()
946 match opt_trait_method_ty {
947 Some(trait_method_ty) => {
948 match (trait_method_ty, &impl_item_ty) {
949 (&ty::MethodTraitItem(ref trait_method_ty),
950 &ty::MethodTraitItem(ref impl_method_ty)) => {
951 compare_impl_method(ccx.tcx,
954 impl_method.pe_body().id,
956 &impl_trait_ref.substs);
961 // This is span_bug as it should have already been
962 // caught in resolve.
966 "method `{}` is not a member of trait `{}`",
967 token::get_ident(impl_item_ty.ident()),
968 pprust::path_to_string(
969 &ast_trait_ref.path)).as_slice());
976 // Check for missing methods from trait
977 let provided_methods = ty::provided_trait_methods(tcx,
978 impl_trait_ref.def_id);
979 let mut missing_methods = Vec::new();
980 for trait_item in trait_items.iter() {
982 ty::MethodTraitItem(ref trait_method) => {
984 impl_items.iter().any(|ii| {
986 ast::MethodImplItem(m) => {
987 m.pe_ident().name == trait_method.ident.name
992 provided_methods.iter().any(
993 |m| m.ident.name == trait_method.ident.name);
994 if !is_implemented && !is_provided {
995 missing_methods.push(
997 token::get_ident(trait_method.ident)));
1003 if !missing_methods.is_empty() {
1004 span_err!(tcx.sess, impl_span, E0046,
1005 "not all trait methods implemented, missing: {}",
1006 missing_methods.connect(", "));
1011 * Checks that a method from an impl conforms to the signature of
1012 * the same method as declared in the trait.
1016 * - impl_generics: the generics declared on the impl itself (not the method!)
1017 * - impl_m: type of the method we are checking
1018 * - impl_m_span: span to use for reporting errors
1019 * - impl_m_body_id: id of the method body
1020 * - trait_m: the method in the trait
1021 * - trait_to_impl_substs: the substitutions used on the type of the trait
1023 fn compare_impl_method(tcx: &ty::ctxt,
1024 impl_m: &ty::Method,
1026 impl_m_body_id: ast::NodeId,
1027 trait_m: &ty::Method,
1028 trait_to_impl_substs: &subst::Substs) {
1029 debug!("compare_impl_method()");
1030 let infcx = infer::new_infer_ctxt(tcx);
1032 // Try to give more informative error messages about self typing
1033 // mismatches. Note that any mismatch will also be detected
1034 // below, where we construct a canonical function type that
1035 // includes the self parameter as a normal parameter. It's just
1036 // that the error messages you get out of this code are a bit more
1037 // inscrutable, particularly for cases where one method has no
1039 match (&trait_m.explicit_self, &impl_m.explicit_self) {
1040 (&ty::StaticExplicitSelfCategory,
1041 &ty::StaticExplicitSelfCategory) => {}
1042 (&ty::StaticExplicitSelfCategory, _) => {
1045 format!("method `{}` has a `{}` declaration in the impl, \
1046 but not in the trait",
1047 token::get_ident(trait_m.ident),
1048 ppaux::explicit_self_category_to_str(
1049 &impl_m.explicit_self)).as_slice());
1052 (_, &ty::StaticExplicitSelfCategory) => {
1055 format!("method `{}` has a `{}` declaration in the trait, \
1056 but not in the impl",
1057 token::get_ident(trait_m.ident),
1058 ppaux::explicit_self_category_to_str(
1059 &trait_m.explicit_self)).as_slice());
1063 // Let the type checker catch other errors below
1067 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
1068 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
1069 if num_impl_m_type_params != num_trait_m_type_params {
1070 span_err!(tcx.sess, impl_m_span, E0049,
1071 "method `{}` has {} type parameter{} \
1072 but its trait declaration has {} type parameter{}",
1073 token::get_ident(trait_m.ident),
1074 num_impl_m_type_params,
1075 if num_impl_m_type_params == 1 {""} else {"s"},
1076 num_trait_m_type_params,
1077 if num_trait_m_type_params == 1 {""} else {"s"});
1081 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
1082 span_err!(tcx.sess, impl_m_span, E0050,
1083 "method `{}` has {} parameter{} \
1084 but the declaration in trait `{}` has {}",
1085 token::get_ident(trait_m.ident),
1086 impl_m.fty.sig.inputs.len(),
1087 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
1088 ty::item_path_str(tcx, trait_m.def_id),
1089 trait_m.fty.sig.inputs.len());
1093 // This code is best explained by example. Consider a trait:
1096 // fn method<'a,M>(t: T, m: &'a M) -> Self;
1101 // impl<'i, U> Trait<&'i U> for Foo {
1102 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
1105 // We wish to decide if those two method types are compatible.
1107 // We start out with trait_to_impl_substs, that maps the trait type
1108 // parameters to impl type parameters:
1110 // trait_to_impl_substs = {T => &'i U, Self => Foo}
1112 // We create a mapping `dummy_substs` that maps from the impl type
1113 // parameters to fresh types and regions. For type parameters,
1114 // this is the identity transform, but we could as well use any
1115 // skolemized types. For regions, we convert from bound to free
1116 // regions (Note: but only early-bound regions, i.e., those
1117 // declared on the impl or used in type parameter bounds).
1119 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
1121 // Now we can apply skol_substs to the type of the impl method
1122 // to yield a new function type in terms of our fresh, skolemized
1125 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
1127 // We now want to extract and substitute the type of the *trait*
1128 // method and compare it. To do so, we must create a compound
1129 // substitution by combining trait_to_impl_substs and
1130 // impl_to_skol_substs, and also adding a mapping for the method
1131 // type parameters. We extend the mapping to also include
1132 // the method parameters.
1134 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
1136 // Applying this to the trait method type yields:
1138 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1140 // This type is also the same but the name of the bound region ('a
1141 // vs 'b). However, the normal subtyping rules on fn types handle
1142 // this kind of equivalency just fine.
1144 // Create mapping from impl to skolemized.
1146 impl_m.generics.types.map(
1147 |d| ty::mk_param_from_def(tcx, d));
1149 impl_m.generics.regions.map(
1150 |l| ty::free_region_from_def(impl_m_body_id, l));
1151 let impl_to_skol_substs =
1152 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1154 // Create mapping from trait to skolemized.
1155 let trait_to_skol_substs =
1156 trait_to_impl_substs
1157 .subst(tcx, &impl_to_skol_substs)
1158 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
1159 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
1161 // Check region bounds.
1162 if !check_region_bounds_on_impl_method(tcx,
1167 &trait_to_skol_substs,
1168 &impl_to_skol_substs) {
1173 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
1174 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
1175 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1176 // Check that the impl does not require any builtin-bounds
1177 // that the trait does not guarantee:
1179 impl_param_def.bounds.builtin_bounds -
1180 trait_param_def.bounds.builtin_bounds;
1181 if !extra_bounds.is_empty() {
1182 span_err!(tcx.sess, impl_m_span, E0051,
1183 "in method `{}`, type parameter {} requires `{}`, \
1184 which is not required by the corresponding type parameter \
1185 in the trait declaration",
1186 token::get_ident(trait_m.ident),
1188 extra_bounds.user_string(tcx));
1192 // Check that the trait bounds of the trait imply the bounds of its
1195 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1196 // traits, but I doubt that'll be wanted often, so meh.
1197 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1198 let impl_trait_bound =
1199 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1202 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1204 trait_bound.subst(tcx, &trait_to_skol_substs);
1205 let infcx = infer::new_infer_ctxt(tcx);
1206 match infer::mk_sub_trait_refs(&infcx,
1208 infer::Misc(impl_m_span),
1210 impl_trait_bound.clone()) {
1220 span_err!(tcx.sess, impl_m_span, E0052,
1221 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1222 required by the corresponding type parameter in the trait declaration",
1223 token::get_ident(trait_m.ident),
1225 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1230 // Compute skolemized form of impl and trait method tys.
1231 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1232 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1233 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1234 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1236 // Check the impl method type IM is a subtype of the trait method
1237 // type TM. To see why this makes sense, think of a vtable. The
1238 // expected type of the function pointers in the vtable is the
1239 // type TM of the trait method. The actual type will be the type
1240 // IM of the impl method. Because we know that IM <: TM, that
1241 // means that anywhere a TM is expected, a IM will do instead. In
1242 // other words, anyone expecting to call a method with the type
1243 // from the trait, can safely call a method with the type from the
1245 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1246 impl_fty, trait_fty) {
1249 span_err!(tcx.sess, impl_m_span, E0053,
1250 "method `{}` has an incompatible type for trait: {}",
1251 token::get_ident(trait_m.ident),
1252 ty::type_err_to_str(tcx, terr));
1253 ty::note_and_explain_type_err(tcx, terr);
1257 // Finally, resolve all regions. This catches wily misuses of lifetime
1259 infcx.resolve_regions_and_report_errors();
1261 fn check_region_bounds_on_impl_method(tcx: &ty::ctxt,
1263 impl_m: &ty::Method,
1264 trait_generics: &ty::Generics,
1265 impl_generics: &ty::Generics,
1266 trait_to_skol_substs: &Substs,
1267 impl_to_skol_substs: &Substs)
1272 Check that region bounds on impl method are the same as those
1273 on the trait. In principle, it could be ok for there to be
1274 fewer region bounds on the impl method, but this leads to an
1275 annoying corner case that is painful to handle (described
1276 below), so for now we can just forbid it.
1279 `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
1283 fn method2<'b:'a>();
1286 impl<'a> Foo<'a> for ... {
1287 fn method1<'b:'a>() { .. case 1, definitely bad .. }
1288 fn method2<'b>() { .. case 2, could be ok .. }
1291 The "definitely bad" case is case #1. Here, the impl adds an
1292 extra constraint not present in the trait.
1294 The "maybe bad" case is case #2. Here, the impl adds an extra
1295 constraint not present in the trait. We could in principle
1296 allow this, but it interacts in a complex way with early/late
1297 bound resolution of lifetimes. Basically the presence or
1298 absence of a lifetime bound affects whether the lifetime is
1299 early/late bound, and right now the code breaks if the trait
1300 has an early bound lifetime parameter and the method does not.
1304 let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
1305 let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
1307 debug!("check_region_bounds_on_impl_method: \
1310 trait_generics.repr(tcx),
1311 impl_generics.repr(tcx));
1313 // Must have same number of early-bound lifetime parameters.
1314 // Unfortunately, if the user screws up the bounds, then this
1315 // will change classification between early and late. E.g.,
1316 // if in trait we have `<'a,'b:'a>`, and in impl we just have
1317 // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1318 // in trait but 0 in the impl. But if we report "expected 2
1319 // but found 0" it's confusing, because it looks like there
1320 // are zero. Since I don't quite know how to phrase things at
1321 // the moment, give a kind of vague error message.
1322 if trait_params.len() != impl_params.len() {
1325 format!("lifetime parameters or bounds on method `{}` do \
1326 not match the trait declaration",
1327 token::get_ident(impl_m.ident)).as_slice());
1331 // Each parameter `'a:'b+'c+'d` in trait should have the same
1332 // set of bounds in the impl, after subst.
1333 for (trait_param, impl_param) in
1334 trait_params.iter().zip(
1338 trait_param.bounds.subst(tcx, trait_to_skol_substs);
1340 impl_param.bounds.subst(tcx, impl_to_skol_substs);
1342 debug!("check_region_bounds_on_impl_method: \
1347 trait_param.repr(tcx),
1348 impl_param.repr(tcx),
1349 trait_bounds.repr(tcx),
1350 impl_bounds.repr(tcx));
1352 // Collect the set of bounds present in trait but not in
1354 let missing: Vec<ty::Region> =
1356 .filter(|&b| !impl_bounds.contains(b))
1360 // Collect set present in impl but not in trait.
1361 let extra: Vec<ty::Region> =
1363 .filter(|&b| !trait_bounds.contains(b))
1367 debug!("missing={} extra={}",
1368 missing.repr(tcx), extra.repr(tcx));
1370 let err = if missing.len() != 0 || extra.len() != 0 {
1374 "the lifetime parameter `{}` declared in the impl \
1375 has a distinct set of bounds \
1376 from its counterpart `{}` \
1377 declared in the trait",
1378 impl_param.name.user_string(tcx),
1379 trait_param.name.user_string(tcx)).as_slice());
1385 if missing.len() != 0 {
1388 format!("the impl is missing the following bounds: `{}`",
1389 missing.user_string(tcx)).as_slice());
1392 if extra.len() != 0 {
1395 format!("the impl has the following extra bounds: `{}`",
1396 extra.user_string(tcx)).as_slice());
1408 fn check_cast(fcx: &FnCtxt,
1413 // Find the type of `e`. Supply hints based on the type we are casting to,
1415 let t_1 = fcx.to_ty(t);
1416 let t_1 = structurally_resolved_type(fcx, span, t_1);
1418 if ty::type_is_scalar(t_1) {
1419 // Supply the type as a hint so as to influence integer
1420 // literals and other things that might care.
1421 check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1))
1426 let t_e = fcx.expr_ty(e);
1428 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1429 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1431 if ty::type_is_error(t_e) {
1432 fcx.write_error(id);
1436 if ty::type_is_bot(t_e) {
1441 if ty::type_is_trait(t_1) {
1442 // This will be looked up later on.
1443 fcx.write_ty(id, t_1);
1447 let t_1 = structurally_resolved_type(fcx, span, t_1);
1448 let t_e = structurally_resolved_type(fcx, span, t_e);
1450 if ty::type_is_nil(t_e) {
1451 fcx.type_error_message(span, |actual| {
1452 format!("cast from nil: `{}` as `{}`",
1454 fcx.infcx().ty_to_string(t_1))
1456 } else if ty::type_is_nil(t_1) {
1457 fcx.type_error_message(span, |actual| {
1458 format!("cast to nil: `{}` as `{}`",
1460 fcx.infcx().ty_to_string(t_1))
1464 let t_1_is_scalar = ty::type_is_scalar(t_1);
1465 let t_1_is_char = ty::type_is_char(t_1);
1466 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1467 let t_1_is_float = ty::type_is_floating_point(t_1);
1469 // casts to scalars other than `char` and `bare fn` are trivial
1470 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1471 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1473 fcx.type_error_message(span, |actual| {
1474 format!("illegal cast; cast through an \
1475 integer first: `{}` as `{}`",
1477 fcx.infcx().ty_to_string(t_1))
1480 // casts from C-like enums are allowed
1481 } else if t_1_is_char {
1482 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1483 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1484 fcx.type_error_message(span, |actual| {
1485 format!("only `u8` can be cast as \
1486 `char`, not `{}`", actual)
1489 } else if ty::get(t_1).sty == ty::ty_bool {
1490 span_err!(fcx.tcx().sess, span, E0054,
1491 "cannot cast as `bool`, compare with zero instead");
1492 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1493 fn types_compatible(fcx: &FnCtxt, sp: Span,
1494 t1: ty::t, t2: ty::t) -> bool {
1495 match ty::get(t1).sty {
1496 ty::ty_vec(_, Some(_)) => {}
1499 if ty::type_needs_infer(t2) {
1500 // This prevents this special case from going off when casting
1501 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1506 let el = ty::sequence_element_type(fcx.tcx(), t1);
1507 infer::mk_eqty(fcx.infcx(),
1514 // Due to the limitations of LLVM global constants,
1515 // region pointers end up pointing at copies of
1516 // vector elements instead of the original values.
1517 // To allow unsafe pointers to work correctly, we
1518 // need to special-case obtaining an unsafe pointer
1519 // from a region pointer to a vector.
1521 /* this cast is only allowed from &[T, ..n] to *T or
1523 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1524 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1525 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1526 if types_compatible(fcx, e.span, mt1, mt2) => {
1527 /* this case is allowed */
1530 demand::coerce(fcx, e.span, t_1, &*e);
1533 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1535 If more type combinations should be supported than are
1536 supported here, then file an enhancement issue and
1537 record the issue number in this comment.
1539 fcx.type_error_message(span, |actual| {
1540 format!("non-scalar cast: `{}` as `{}`",
1542 fcx.infcx().ty_to_string(t_1))
1544 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1545 fcx.type_error_message(span, |actual| {
1546 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1549 fcx.infcx().ty_to_string(t_1))
1553 fcx.write_ty(id, t_1);
1556 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
1557 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1559 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1560 ty::lookup_item_type(self.tcx(), id)
1563 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1564 ty::lookup_trait_def(self.tcx(), id)
1567 fn ty_infer(&self, _span: Span) -> ty::t {
1568 self.infcx().next_ty_var()
1572 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1573 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
1575 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
1579 pub fn err_count_since_creation(&self) -> uint {
1580 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1583 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a, 'tcx> {
1585 infcx: self.infcx(),
1586 param_env: &self.inh.param_env,
1587 unboxed_closures: &self.inh.unboxed_closures,
1592 impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
1593 fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
1594 Some(self.next_region_var(infer::MiscVariable(span)))
1597 fn anon_regions(&self, span: Span, count: uint)
1598 -> Result<Vec<ty::Region> , ()> {
1599 Ok(Vec::from_fn(count, |_| {
1600 self.next_region_var(infer::MiscVariable(span))
1605 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1606 pub fn tag(&self) -> String {
1607 format!("{}", self as *const FnCtxt)
1610 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1611 match self.inh.locals.borrow().find(&nid) {
1614 self.tcx().sess.span_bug(
1616 format!("no type for local variable {:?}",
1623 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1624 debug!("write_ty({}, {}) in fcx {}",
1625 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1626 self.inh.node_types.borrow_mut().insert(node_id, ty);
1629 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1630 if !substs.substs.is_noop() {
1631 debug!("write_substs({}, {}) in fcx {}",
1633 substs.repr(self.tcx()),
1636 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1640 pub fn write_ty_substs(&self,
1641 node_id: ast::NodeId,
1643 substs: ty::ItemSubsts) {
1644 let ty = ty.subst(self.tcx(), &substs.substs);
1645 self.write_ty(node_id, ty);
1646 self.write_substs(node_id, substs);
1649 pub fn write_autoderef_adjustment(&self,
1650 node_id: ast::NodeId,
1652 if derefs == 0 { return; }
1653 self.write_adjustment(
1655 ty::AutoDerefRef(ty::AutoDerefRef {
1661 pub fn write_adjustment(&self,
1662 node_id: ast::NodeId,
1663 adj: ty::AutoAdjustment) {
1664 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1665 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1668 pub fn write_nil(&self, node_id: ast::NodeId) {
1669 self.write_ty(node_id, ty::mk_nil());
1671 pub fn write_bot(&self, node_id: ast::NodeId) {
1672 self.write_ty(node_id, ty::mk_bot());
1674 pub fn write_error(&self, node_id: ast::NodeId) {
1675 self.write_ty(node_id, ty::mk_err());
1678 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1679 ast_ty_to_ty(self, self.infcx(), ast_t)
1682 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1683 pat.repr(self.tcx())
1686 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1687 match self.inh.node_types.borrow().find(&ex.id) {
1690 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1691 self.tag()).as_slice());
1696 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1697 match self.inh.node_types.borrow().find(&id) {
1700 self.tcx().sess.bug(
1701 format!("no type for node {}: {} in fcx {}",
1702 id, self.tcx().map.node_to_string(id),
1703 self.tag()).as_slice());
1708 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1709 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1710 Some(method) => method.substs.clone(),
1712 self.tcx().sess.bug(
1713 format!("no method entry for node {}: {} in fcx {}",
1714 id, self.tcx().map.node_to_string(id),
1715 self.tag()).as_slice());
1720 pub fn opt_node_ty_substs(&self,
1722 f: |&ty::ItemSubsts|) {
1723 match self.inh.item_substs.borrow().find(&id) {
1729 pub fn mk_subty(&self,
1730 a_is_expected: bool,
1731 origin: infer::TypeOrigin,
1734 -> Result<(), ty::type_err> {
1735 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1738 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1739 -> Result<(), ty::type_err> {
1740 infer::can_mk_subty(self.infcx(), sub, sup)
1743 pub fn mk_assignty(&self,
1747 -> Result<(), ty::type_err> {
1748 match infer::mk_coercety(self.infcx(),
1750 infer::ExprAssignable(expr.span),
1754 Err(ref e) => Err((*e)),
1755 Ok(Some(adjustment)) => {
1756 self.write_adjustment(expr.id, adjustment);
1762 pub fn mk_eqty(&self,
1763 a_is_expected: bool,
1764 origin: infer::TypeOrigin,
1767 -> Result<(), ty::type_err> {
1768 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1771 pub fn mk_subr(&self,
1772 origin: infer::SubregionOrigin,
1775 infer::mk_subr(self.infcx(), origin, sub, sup)
1778 pub fn type_error_message(&self,
1780 mk_msg: |String| -> String,
1782 err: Option<&ty::type_err>) {
1783 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1786 pub fn report_mismatched_return_types(&self,
1790 err: &ty::type_err) {
1792 if ty::type_is_error(e) || ty::type_is_error(a) {
1795 self.infcx().report_mismatched_types(sp, e, a, err)
1798 pub fn report_mismatched_types(&self,
1802 err: &ty::type_err) {
1803 self.infcx().report_mismatched_types(sp, e, a, err)
1806 pub fn register_region_obligation(&self,
1807 origin: infer::SubregionOrigin,
1812 * Registers an obligation for checking later, during
1813 * regionck, that the type `ty` must outlive the region `r`.
1816 let mut region_obligations = self.inh.region_obligations.borrow_mut();
1817 let v = region_obligations.find_or_insert_with(self.body_id,
1819 v.push(RegionObligation { sub_region: r,
1824 pub fn add_region_obligations_for_parameters(&self,
1827 generics: &ty::Generics)
1830 * Given a set of generic parameter definitions (`generics`)
1831 * and the values provided for each of them (`substs`),
1832 * creates and registers suitable region obligations.
1834 * For example, if there is a function:
1836 * fn foo<'a,T:'a>(...)
1842 * Then we will create a fresh region variable `'$0` and a
1843 * fresh type variable `$1` for `'a` and `T`. This routine
1844 * will add a region obligation `$1:'$0` and register it
1848 debug!("add_region_obligations_for_parameters(substs={}, generics={})",
1849 substs.repr(self.tcx()),
1850 generics.repr(self.tcx()));
1852 assert_eq!(generics.types.iter().len(),
1853 substs.types.iter().len());
1854 for (type_def, &type_param) in
1855 generics.types.iter().zip(
1856 substs.types.iter())
1858 let param_ty = ty::ParamTy { space: type_def.space,
1859 idx: type_def.index,
1860 def_id: type_def.def_id };
1861 let bounds = type_def.bounds.subst(self.tcx(), substs);
1862 add_region_obligations_for_type_parameter(
1863 self, span, param_ty, &bounds, type_param);
1866 assert_eq!(generics.regions.iter().len(),
1867 substs.regions().iter().len());
1868 for (region_def, ®ion_param) in
1869 generics.regions.iter().zip(
1870 substs.regions().iter())
1872 let bounds = region_def.bounds.subst(self.tcx(), substs);
1873 add_region_obligations_for_region_parameter(
1874 self, span, bounds.as_slice(), region_param);
1877 fn add_region_obligations_for_type_parameter(
1880 param_ty: ty::ParamTy,
1881 param_bound: &ty::ParamBounds,
1884 // For each declared region bound `T:r`, `T` must outlive `r`.
1886 ty::required_region_bounds(
1888 param_bound.opt_region_bound.as_slice(),
1889 param_bound.builtin_bounds,
1890 param_bound.trait_bounds.as_slice());
1891 for &r in region_bounds.iter() {
1892 let origin = infer::RelateParamBound(span, param_ty, ty);
1893 fcx.register_region_obligation(origin, ty, r);
1897 fn add_region_obligations_for_region_parameter(
1900 region_bounds: &[ty::Region],
1901 region_param: ty::Region)
1903 for &b in region_bounds.iter() {
1904 // For each bound `region:b`, `b <= region` must hold
1905 // (i.e., `region` must outlive `b`).
1906 let origin = infer::RelateRegionParamBound(span);
1907 fcx.mk_subr(origin, b, region_param);
1913 pub enum LvaluePreference {
1918 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1919 expr_id: Option<ast::NodeId>,
1920 mut lvalue_pref: LvaluePreference,
1921 should_stop: |ty::t, uint| -> Option<T>)
1922 -> (ty::t, uint, Option<T>) {
1924 * Executes an autoderef loop for the type `t`. At each step, invokes
1925 * `should_stop` to decide whether to terminate the loop. Returns
1926 * the final type and number of derefs that it performed.
1928 * Note: this method does not modify the adjustments table. The caller is
1929 * responsible for inserting an AutoAdjustment record into the `fcx`
1930 * using one of the suitable methods.
1933 let mut t = base_ty;
1934 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1935 let resolved_t = structurally_resolved_type(fcx, sp, t);
1937 match should_stop(resolved_t, autoderefs) {
1938 Some(x) => return (resolved_t, autoderefs, Some(x)),
1942 // Otherwise, deref if type is derefable:
1943 let mt = match ty::deref(resolved_t, false) {
1944 Some(mt) => Some(mt),
1946 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1947 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1953 if mt.mutbl == ast::MutImmutable {
1954 lvalue_pref = NoPreference;
1957 None => return (resolved_t, autoderefs, None)
1961 // We've reached the recursion limit, error gracefully.
1962 span_err!(fcx.tcx().sess, sp, E0055,
1963 "reached the recursion limit while auto-dereferencing {}",
1964 base_ty.repr(fcx.tcx()));
1965 (ty::mk_err(), 0, None)
1968 /// Attempts to resolve a call expression as an overloaded call.
1969 fn try_overloaded_call(fcx: &FnCtxt,
1970 call_expression: &ast::Expr,
1971 callee: Gc<ast::Expr>,
1973 args: &[Gc<ast::Expr>])
1975 // Bail out if the callee is a bare function or a closure. We check those
1977 match *structure_of(fcx, callee.span, callee_type) {
1978 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
1982 // Try `FnOnce`, then `FnMut`, then `Fn`.
1983 for &(maybe_function_trait, method_name) in [
1984 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1985 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1986 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1988 let function_trait = match maybe_function_trait {
1990 Some(function_trait) => function_trait,
1992 let method_callee = match method::lookup_in_trait(
1994 call_expression.span,
2000 DontAutoderefReceiver,
2001 IgnoreStaticMethods) {
2003 Some(method_callee) => method_callee,
2005 let method_call = MethodCall::expr(call_expression.id);
2006 let output_type = check_method_argument_types(fcx,
2007 call_expression.span,
2013 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
2014 write_call(fcx, call_expression, output_type);
2016 if !fcx.tcx().sess.features.overloaded_calls.get() {
2017 span_err!(fcx.tcx().sess, call_expression.span, E0056,
2018 "overloaded calls are experimental");
2019 span_note!(fcx.tcx().sess, call_expression.span,
2020 "add `#![feature(overloaded_calls)]` to \
2021 the crate attributes to enable");
2030 fn try_overloaded_deref(fcx: &FnCtxt,
2032 method_call: Option<MethodCall>,
2033 base_expr: Option<&ast::Expr>,
2035 lvalue_pref: LvaluePreference)
2037 // Try DerefMut first, if preferred.
2038 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
2039 (PreferMutLvalue, Some(trait_did)) => {
2040 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2041 token::intern("deref_mut"), trait_did,
2042 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2047 // Otherwise, fall back to Deref.
2048 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
2049 (None, Some(trait_did)) => {
2050 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
2051 token::intern("deref"), trait_did,
2052 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
2054 (method, _) => method
2059 let ref_ty = ty::ty_fn_ret(method.ty);
2061 Some(method_call) => {
2062 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2066 ty::deref(ref_ty, true)
2072 fn try_overloaded_index(fcx: &FnCtxt,
2073 method_call: Option<MethodCall>,
2075 base_expr: Gc<ast::Expr>,
2077 index_expr: Gc<ast::Expr>,
2078 lvalue_pref: LvaluePreference)
2080 // Try `IndexMut` first, if preferred.
2081 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
2082 (PreferMutLvalue, Some(trait_did)) => {
2083 method::lookup_in_trait(fcx,
2086 token::intern("index_mut"),
2090 DontAutoderefReceiver,
2091 IgnoreStaticMethods)
2096 // Otherwise, fall back to `Index`.
2097 let method = match (method, fcx.tcx().lang_items.index_trait()) {
2098 (None, Some(trait_did)) => {
2099 method::lookup_in_trait(fcx,
2102 token::intern("index"),
2106 DontAutoderefReceiver,
2107 IgnoreStaticMethods)
2109 (method, _) => method,
2112 // Regardless of whether the lookup succeeds, check the method arguments
2113 // so that we have *some* type for each argument.
2114 let method_type = match method {
2115 Some(ref method) => method.ty,
2116 None => ty::mk_err()
2118 check_method_argument_types(fcx,
2122 [base_expr, index_expr],
2124 DontTupleArguments);
2128 let ref_ty = ty::ty_fn_ret(method.ty);
2130 Some(method_call) => {
2131 fcx.inh.method_map.borrow_mut().insert(method_call,
2136 ty::deref(ref_ty, true)
2142 /// Given the head of a `for` expression, looks up the `next` method in the
2143 /// `Iterator` trait. Fails if the expression does not implement `next`.
2145 /// The return type of this function represents the concrete element type
2146 /// `A` in the type `Iterator<A>` that the method returns.
2147 fn lookup_method_for_for_loop(fcx: &FnCtxt,
2148 iterator_expr: Gc<ast::Expr>,
2149 loop_id: ast::NodeId)
2151 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
2152 Ok(trait_did) => trait_did,
2153 Err(ref err_string) => {
2154 fcx.tcx().sess.span_err(iterator_expr.span,
2155 err_string.as_slice());
2160 let expr_type = fcx.expr_ty(&*iterator_expr);
2161 let method = method::lookup_in_trait(fcx,
2163 Some(&*iterator_expr),
2164 token::intern("next"),
2168 DontAutoderefReceiver,
2169 IgnoreStaticMethods);
2171 // Regardless of whether the lookup succeeds, check the method arguments
2172 // so that we have *some* type for each argument.
2173 let method_type = match method {
2174 Some(ref method) => method.ty,
2176 let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(expr_type);
2178 if !ty::type_is_error(true_expr_type) {
2179 let ty_string = fcx.infcx().ty_to_string(true_expr_type);
2180 fcx.tcx().sess.span_err(iterator_expr.span,
2181 format!("`for` loop expression has type `{}` which does \
2182 not implement the `Iterator` trait",
2183 ty_string).as_slice());
2188 let return_type = check_method_argument_types(fcx,
2194 DontTupleArguments);
2198 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
2201 // We expect the return type to be `Option` or something like it.
2202 // Grab the first parameter of its type substitution.
2203 let return_type = structurally_resolved_type(fcx,
2206 match ty::get(return_type).sty {
2207 ty::ty_enum(_, ref substs)
2208 if !substs.types.is_empty_in(subst::TypeSpace) => {
2209 *substs.types.get(subst::TypeSpace, 0)
2212 fcx.tcx().sess.span_err(iterator_expr.span,
2213 "`next` method of the `Iterator` \
2214 trait has an unexpected type");
2219 None => ty::mk_err()
2223 fn check_method_argument_types(fcx: &FnCtxt,
2225 method_fn_ty: ty::t,
2226 callee_expr: &ast::Expr,
2227 args: &[Gc<ast::Expr>],
2228 deref_args: DerefArgs,
2229 tuple_arguments: TupleArgumentsFlag)
2231 // HACK(eddyb) ignore provided self (it has special typeck rules).
2232 let args = if tuple_arguments == DontTupleArguments {
2237 if ty::type_is_error(method_fn_ty) {
2238 let err_inputs = err_args(args.len());
2239 check_argument_types(fcx,
2241 err_inputs.as_slice(),
2249 match ty::get(method_fn_ty).sty {
2250 ty::ty_bare_fn(ref fty) => {
2251 // HACK(eddyb) ignore self in the definition (see above).
2252 check_argument_types(fcx,
2254 fty.sig.inputs.slice_from(1),
2263 fcx.tcx().sess.span_bug(callee_expr.span,
2264 "method without bare fn type");
2270 fn check_argument_types(fcx: &FnCtxt,
2272 fn_inputs: &[ty::t],
2273 callee_expr: &ast::Expr,
2274 args: &[Gc<ast::Expr>],
2275 deref_args: DerefArgs,
2277 tuple_arguments: TupleArgumentsFlag) {
2280 * Generic function that factors out common logic from
2281 * function calls, method calls and overloaded operators.
2284 let tcx = fcx.ccx.tcx;
2286 // Grab the argument types, supplying fresh type variables
2287 // if the wrong number of arguments were supplied
2288 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
2294 let expected_arg_count = fn_inputs.len();
2295 let formal_tys = if tuple_arguments == TupleArguments {
2296 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
2297 match ty::get(tuple_type).sty {
2298 ty::ty_tup(ref arg_types) => {
2299 if arg_types.len() != args.len() {
2300 span_err!(tcx.sess, sp, E0057,
2301 "this function takes {} parameter{} but {} parameter{} supplied",
2303 if arg_types.len() == 1 {""} else {"s"},
2305 if args.len() == 1 {" was"} else {"s were"});
2306 err_args(args.len())
2308 (*arg_types).clone()
2312 if args.len() != 0 {
2313 span_err!(tcx.sess, sp, E0058,
2314 "this function takes 0 parameters but {} parameter{} supplied",
2316 if args.len() == 1 {" was"} else {"s were"});
2321 span_err!(tcx.sess, sp, E0059,
2322 "cannot use call notation; the first type parameter \
2323 for the function trait is neither a tuple nor unit");
2324 err_args(supplied_arg_count)
2327 } else if expected_arg_count == supplied_arg_count {
2328 fn_inputs.iter().map(|a| *a).collect()
2329 } else if variadic {
2330 if supplied_arg_count >= expected_arg_count {
2331 fn_inputs.iter().map(|a| *a).collect()
2333 span_err!(tcx.sess, sp, E0060,
2334 "this function takes at least {} parameter{} \
2335 but {} parameter{} supplied",
2337 if expected_arg_count == 1 {""} else {"s"},
2339 if supplied_arg_count == 1 {" was"} else {"s were"});
2340 err_args(supplied_arg_count)
2343 span_err!(tcx.sess, sp, E0061,
2344 "this function takes {} parameter{} but {} parameter{} supplied",
2346 if expected_arg_count == 1 {""} else {"s"},
2348 if supplied_arg_count == 1 {" was"} else {"s were"});
2349 err_args(supplied_arg_count)
2352 debug!("check_argument_types: formal_tys={:?}",
2353 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
2355 // Check the arguments.
2356 // We do this in a pretty awful way: first we typecheck any arguments
2357 // that are not anonymous functions, then we typecheck the anonymous
2358 // functions. This is so that we have more information about the types
2359 // of arguments when we typecheck the functions. This isn't really the
2360 // right way to do this.
2361 let xs = [false, true];
2362 for check_blocks in xs.iter() {
2363 let check_blocks = *check_blocks;
2364 debug!("check_blocks={}", check_blocks);
2366 // More awful hacks: before we check the blocks, try to do
2367 // an "opportunistic" vtable resolution of any trait
2368 // bounds on the call.
2370 vtable::early_resolve_expr(callee_expr, fcx, true);
2373 // For variadic functions, we don't have a declared type for all of
2374 // the arguments hence we only do our usual type checking with
2375 // the arguments who's types we do know.
2376 let t = if variadic {
2378 } else if tuple_arguments == TupleArguments {
2383 for (i, arg) in args.iter().take(t).enumerate() {
2384 let is_block = match arg.node {
2385 ast::ExprFnBlock(..) |
2387 ast::ExprUnboxedFn(..) => true,
2391 if is_block == check_blocks {
2392 debug!("checking the argument");
2393 let mut formal_ty = *formal_tys.get(i);
2397 match ty::get(formal_ty).sty {
2398 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
2401 // So we hit this case when one implements the
2402 // operator traits but leaves an argument as
2403 // just T instead of &T. We'll catch it in the
2404 // mismatch impl/trait method phase no need to
2407 formal_ty = ty::mk_err();
2414 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
2419 // We also need to make sure we at least write the ty of the other
2420 // arguments which we skipped above.
2422 for arg in args.iter().skip(expected_arg_count) {
2423 check_expr(fcx, &**arg);
2425 // There are a few types which get autopromoted when passed via varargs
2426 // in C but we just error out instead and require explicit casts.
2427 let arg_ty = structurally_resolved_type(fcx, arg.span,
2428 fcx.expr_ty(&**arg));
2429 match ty::get(arg_ty).sty {
2430 ty::ty_float(ast::TyF32) => {
2431 fcx.type_error_message(arg.span,
2433 format!("can't pass an {} to variadic \
2434 function, cast to c_double", t)
2437 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2438 fcx.type_error_message(arg.span, |t| {
2439 format!("can't pass {} to variadic \
2440 function, cast to c_int",
2444 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2445 fcx.type_error_message(arg.span, |t| {
2446 format!("can't pass {} to variadic \
2447 function, cast to c_uint",
2457 fn err_args(len: uint) -> Vec<ty::t> {
2458 Vec::from_fn(len, |_| ty::mk_err())
2461 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
2462 fcx.write_ty(call_expr.id, output);
2465 // AST fragment checking
2466 fn check_lit(fcx: &FnCtxt,
2468 expected: Expectation)
2471 let tcx = fcx.ccx.tcx;
2474 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2475 ast::LitBinary(..) => {
2476 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2478 ast::LitByte(_) => ty::mk_u8(),
2479 ast::LitChar(_) => ty::mk_char(),
2480 ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
2481 ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
2482 ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
2483 let opt_ty = expected.map_to_option(fcx, |sty| {
2485 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2486 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2487 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2488 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2489 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2493 opt_ty.unwrap_or_else(
2494 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2496 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2497 ast::LitFloatUnsuffixed(_) => {
2498 let opt_ty = expected.map_to_option(fcx, |sty| {
2500 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2504 opt_ty.unwrap_or_else(
2505 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2507 ast::LitNil => ty::mk_nil(),
2508 ast::LitBool(_) => ty::mk_bool()
2512 pub fn valid_range_bounds(ccx: &CrateCtxt,
2516 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2517 Some(val) => Some(val <= 0),
2522 pub fn check_expr_has_type(fcx: &FnCtxt,
2525 check_expr_with_unifier(
2526 fcx, expr, ExpectHasType(expected), NoPreference,
2527 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2530 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2533 check_expr_with_unifier(
2534 fcx, expr, ExpectHasType(expected), NoPreference,
2535 || demand::coerce(fcx, expr.span, expected, expr));
2538 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2539 check_expr_with_unifier(
2540 fcx, expr, ExpectHasType(expected), NoPreference,
2544 fn check_expr_with_expectation(fcx: &FnCtxt,
2546 expected: Expectation) {
2547 check_expr_with_unifier(
2548 fcx, expr, expected, NoPreference,
2552 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2554 expected: Expectation,
2555 lvalue_pref: LvaluePreference)
2557 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2560 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2561 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2564 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2565 lvalue_pref: LvaluePreference) {
2566 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2570 // determine the `self` type, using fresh variables for all variables
2571 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2572 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2574 pub fn impl_self_ty(vcx: &VtableContext,
2575 span: Span, // (potential) receiver for this impl
2578 let tcx = vcx.tcx();
2580 let ity = ty::lookup_item_type(tcx, did);
2581 let (n_tps, rps, raw_ty) =
2582 (ity.generics.types.len(subst::TypeSpace),
2583 ity.generics.regions.get_slice(subst::TypeSpace),
2586 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2587 let tps = vcx.infcx.next_ty_vars(n_tps);
2588 let substs = subst::Substs::new_type(tps, rps);
2589 let substd_ty = raw_ty.subst(tcx, &substs);
2591 TypeAndSubsts { substs: substs, ty: substd_ty }
2594 // Only for fields! Returns <none> for methods>
2595 // Indifferent to privacy flags
2596 pub fn lookup_field_ty(tcx: &ty::ctxt,
2597 class_id: ast::DefId,
2598 items: &[ty::field_ty],
2599 fieldname: ast::Name,
2600 substs: &subst::Substs) -> Option<ty::t> {
2602 let o_field = items.iter().find(|f| f.name == fieldname);
2603 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2606 // Controls whether the arguments are automatically referenced. This is useful
2607 // for overloaded binary and unary operators.
2608 pub enum DerefArgs {
2613 /// Controls whether the arguments are tupled. This is used for the call
2616 /// Tupling means that all call-side arguments are packed into a tuple and
2617 /// passed as a single parameter. For example, if tupling is enabled, this
2620 /// fn f(x: (int, int))
2622 /// Can be called as:
2629 #[deriving(Clone, Eq, PartialEq)]
2630 enum TupleArgumentsFlag {
2636 /// If an expression has any sub-expressions that result in a type error,
2637 /// inspecting that expression's type with `ty::type_is_error` will return
2638 /// true. Likewise, if an expression is known to diverge, inspecting its
2639 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2640 /// strict, _|_ can appear in the type of an expression that does not,
2641 /// itself, diverge: for example, fn() -> _|_.)
2642 /// Note that inspecting a type's structure *directly* may expose the fact
2643 /// that there are actually multiple representations for both `ty_err` and
2644 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2645 fn check_expr_with_unifier(fcx: &FnCtxt,
2647 expected: Expectation,
2648 lvalue_pref: LvaluePreference,
2651 debug!(">> typechecking: expr={} expected={}",
2652 expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
2654 // A generic function for doing all of the checking for call expressions
2655 fn check_call(fcx: &FnCtxt,
2656 call_expr: &ast::Expr,
2658 args: &[Gc<ast::Expr>]) {
2659 // Store the type of `f` as the type of the callee
2660 let fn_ty = fcx.expr_ty(f);
2662 // Extract the function signature from `in_fty`.
2663 let fn_sty = structure_of(fcx, f.span, fn_ty);
2665 // This is the "default" function signature, used in case of error.
2666 // In that case, we check each argument against "error" in order to
2667 // set up all the node type bindings.
2668 let error_fn_sig = FnSig {
2669 binder_id: ast::CRATE_NODE_ID,
2670 inputs: err_args(args.len()),
2671 output: ty::mk_err(),
2675 let fn_sig = match *fn_sty {
2676 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2677 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2679 fcx.type_error_message(call_expr.span, |actual| {
2680 format!("expected function, found `{}`", actual)
2686 // Replace any bound regions that appear in the function
2687 // signature with region variables
2688 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2689 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2692 // Call the generic checker.
2693 check_argument_types(fcx,
2695 fn_sig.inputs.as_slice(),
2700 DontTupleArguments);
2702 write_call(fcx, call_expr, fn_sig.output);
2705 // Checks a method call.
2706 fn check_method_call(fcx: &FnCtxt,
2708 method_name: ast::SpannedIdent,
2709 args: &[Gc<ast::Expr>],
2710 tps: &[ast::P<ast::Ty>]) {
2711 let rcvr = args[0].clone();
2712 // We can't know if we need &mut self before we look up the method,
2713 // so treat the receiver as mutable just in case - only explicit
2714 // overloaded dereferences care about the distinction.
2715 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2717 // no need to check for bot/err -- callee does that
2718 let expr_t = structurally_resolved_type(fcx,
2720 fcx.expr_ty(&*rcvr));
2722 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2723 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2724 method_name.node.name,
2725 expr_t, tps.as_slice(),
2727 CheckTraitsAndInherentMethods,
2728 AutoderefReceiver, IgnoreStaticMethods) {
2730 let method_ty = method.ty;
2731 let method_call = MethodCall::expr(expr.id);
2732 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2736 debug!("(checking method call) failing expr is {}", expr.id);
2738 fcx.type_error_message(method_name.span,
2740 format!("type `{}` does not implement any \
2741 method in scope named `{}`",
2743 token::get_ident(method_name.node))
2748 // Add error type for the result
2749 fcx.write_error(expr.id);
2751 // Check for potential static matches (missing self parameters)
2755 method_name.node.name,
2759 CheckTraitsAndInherentMethods,
2760 DontAutoderefReceiver,
2761 ReportStaticMethods);
2767 // Call the generic checker.
2768 let ret_ty = check_method_argument_types(fcx,
2774 DontTupleArguments);
2776 write_call(fcx, expr, ret_ty);
2779 // A generic function for checking the then and else in an if
2781 fn check_then_else(fcx: &FnCtxt,
2782 cond_expr: &ast::Expr,
2783 then_blk: &ast::Block,
2784 opt_else_expr: Option<Gc<ast::Expr>>,
2787 expected: Expectation) {
2788 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2790 let branches_ty = match opt_else_expr {
2791 Some(ref else_expr) => {
2792 // Disregard "castable to" expectations because they
2793 // can lead us astray. Consider for example `if cond
2794 // {22} else {c} as u8` -- if we propagate the
2795 // "castable to u8" constraint to 22, it will pick the
2796 // type 22u8, which is overly constrained (c might not
2797 // be a u8). In effect, the problem is that the
2798 // "castable to" expectation is not the tightest thing
2799 // we can say, so we want to drop it in this case.
2800 // The tightest thing we can say is "must unify with
2801 // else branch". Note that in the case of a "has type"
2802 // constraint, this limitation does not hold.
2804 // If the expected type is just a type variable, then don't use
2805 // an expected type. Otherwise, we might write parts of the type
2806 // when checking the 'then' block which are incompatible with the
2808 let expected = match expected.only_has_type() {
2809 ExpectHasType(ety) => {
2810 match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) {
2811 Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
2817 check_block_with_expected(fcx, then_blk, expected);
2818 let then_ty = fcx.node_ty(then_blk.id);
2819 check_expr_with_expectation(fcx, &**else_expr, expected);
2820 let else_ty = fcx.expr_ty(&**else_expr);
2821 infer::common_supertype(fcx.infcx(),
2822 infer::IfExpression(sp),
2828 check_block_no_value(fcx, then_blk);
2833 let cond_ty = fcx.expr_ty(cond_expr);
2834 let if_ty = if ty::type_is_error(cond_ty) {
2836 } else if ty::type_is_bot(cond_ty) {
2842 fcx.write_ty(id, if_ty);
2845 fn lookup_op_method(fcx: &FnCtxt,
2849 trait_did: Option<ast::DefId>,
2850 args: &[Gc<ast::Expr>],
2851 autoderef_receiver: AutoderefReceiverFlag,
2852 unbound_method: ||) -> ty::t {
2853 let method = match trait_did {
2854 Some(trait_did) => {
2855 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2856 trait_did, self_t, [], autoderef_receiver,
2857 IgnoreStaticMethods)
2863 let method_ty = method.ty;
2864 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2865 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2866 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2867 check_method_argument_types(fcx,
2877 // Check the args anyway
2878 // so we get all the error messages
2879 let expected_ty = ty::mk_err();
2880 check_method_argument_types(fcx,
2886 DontTupleArguments);
2892 // could be either an expr_binop or an expr_assign_binop
2893 fn check_binop(fcx: &FnCtxt,
2898 is_binop_assignment: IsBinopAssignment) {
2899 let tcx = fcx.ccx.tcx;
2901 let lvalue_pref = match is_binop_assignment {
2902 BinopAssignment => PreferMutLvalue,
2903 SimpleBinop => NoPreference
2905 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2907 // Callee does bot / err checking
2908 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2909 fcx.expr_ty(&*lhs));
2911 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2912 // Shift is a special case: rhs must be uint, no matter what lhs is
2913 check_expr_has_type(fcx, &*rhs, ty::mk_uint());
2914 fcx.write_ty(expr.id, lhs_t);
2918 if ty::is_binopable(tcx, lhs_t, op) {
2919 let tvar = fcx.infcx().next_ty_var();
2920 demand::suptype(fcx, expr.span, tvar, lhs_t);
2921 check_expr_has_type(fcx, &*rhs, tvar);
2923 let result_t = match op {
2924 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2926 if ty::type_is_simd(tcx, lhs_t) {
2927 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2928 fcx.type_error_message(expr.span,
2930 format!("binary comparison \
2931 operation `{}` not \
2932 supported for floating \
2933 point SIMD vector `{}`",
2934 ast_util::binop_to_string(op),
2951 fcx.write_ty(expr.id, result_t);
2955 if op == ast::BiOr || op == ast::BiAnd {
2956 // This is an error; one of the operands must have the wrong
2958 fcx.write_error(expr.id);
2959 fcx.write_error(rhs.id);
2960 fcx.type_error_message(expr.span,
2962 format!("binary operation `{}` cannot be applied \
2964 ast_util::binop_to_string(op),
2971 // Check for overloaded operators if not an assignment.
2972 let result_t = if is_binop_assignment == SimpleBinop {
2973 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2975 fcx.type_error_message(expr.span,
2977 format!("binary assignment \
2979 cannot be applied to \
2981 ast_util::binop_to_string(op),
2986 check_expr(fcx, &*rhs);
2990 fcx.write_ty(expr.id, result_t);
2991 if ty::type_is_error(result_t) {
2992 fcx.write_ty(rhs.id, result_t);
2996 fn check_user_binop(fcx: &FnCtxt,
2998 lhs_expr: Gc<ast::Expr>,
2999 lhs_resolved_t: ty::t,
3001 rhs: Gc<ast::Expr>) -> ty::t {
3002 let tcx = fcx.ccx.tcx;
3003 let lang = &tcx.lang_items;
3004 let (name, trait_did) = match op {
3005 ast::BiAdd => ("add", lang.add_trait()),
3006 ast::BiSub => ("sub", lang.sub_trait()),
3007 ast::BiMul => ("mul", lang.mul_trait()),
3008 ast::BiDiv => ("div", lang.div_trait()),
3009 ast::BiRem => ("rem", lang.rem_trait()),
3010 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
3011 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
3012 ast::BiBitOr => ("bitor", lang.bitor_trait()),
3013 ast::BiShl => ("shl", lang.shl_trait()),
3014 ast::BiShr => ("shr", lang.shr_trait()),
3015 ast::BiLt => ("lt", lang.ord_trait()),
3016 ast::BiLe => ("le", lang.ord_trait()),
3017 ast::BiGe => ("ge", lang.ord_trait()),
3018 ast::BiGt => ("gt", lang.ord_trait()),
3019 ast::BiEq => ("eq", lang.eq_trait()),
3020 ast::BiNe => ("ne", lang.eq_trait()),
3021 ast::BiAnd | ast::BiOr => {
3022 check_expr(fcx, &*rhs);
3023 return ty::mk_err();
3026 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
3027 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
3028 fcx.type_error_message(ex.span, |actual| {
3029 format!("binary operation `{}` cannot be applied to type `{}`",
3030 ast_util::binop_to_string(op),
3032 }, lhs_resolved_t, None)
3036 fn check_user_unop(fcx: &FnCtxt,
3039 trait_did: Option<ast::DefId>,
3041 rhs_expr: Gc<ast::Expr>,
3042 rhs_t: ty::t) -> ty::t {
3043 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
3044 trait_did, [rhs_expr], DontAutoderefReceiver, || {
3045 fcx.type_error_message(ex.span, |actual| {
3046 format!("cannot apply unary operator `{}` to type `{}`",
3052 fn check_unboxed_closure(fcx: &FnCtxt,
3054 kind: ast::UnboxedClosureKind,
3056 body: ast::P<ast::Block>) {
3057 let mut fn_ty = astconv::ty_of_closure(
3063 // The `RegionTraitStore` and region_existential_bounds
3064 // are lies, but we ignore them so it doesn't matter.
3066 // FIXME(pcwalton): Refactor this API.
3067 ty::region_existential_bound(ty::ReStatic),
3068 ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
3074 let region = match fcx.infcx().anon_regions(expr.span, 1) {
3076 fcx.ccx.tcx.sess.span_bug(expr.span,
3077 "can't make anon regions here?!")
3079 Ok(regions) => *regions.get(0),
3081 let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
3084 fcx.write_ty(expr.id, closure_type);
3095 // Tuple up the arguments and insert the resulting function type into
3096 // the `unboxed_closures` table.
3097 fn_ty.sig.inputs = if fn_ty.sig.inputs.len() == 0 {
3100 vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)]
3103 let kind = match kind {
3104 ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
3105 ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
3106 ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
3109 let unboxed_closure = ty::UnboxedClosure {
3110 closure_type: fn_ty,
3117 .insert(local_def(expr.id), unboxed_closure);
3120 fn check_expr_fn(fcx: &FnCtxt,
3122 store: ty::TraitStore,
3124 body: ast::P<ast::Block>,
3125 expected: Expectation) {
3126 let tcx = fcx.ccx.tcx;
3128 // Find the expected input/output types (if any). Substitute
3129 // fresh bound regions for any bound regions we find in the
3130 // expected types so as to avoid capture.
3131 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
3134 expected_bounds) = {
3135 match expected_sty {
3136 Some(ty::ty_closure(ref cenv)) => {
3138 replace_late_bound_regions_in_fn_sig(
3140 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
3141 let onceness = match (&store, &cenv.store) {
3142 // As the closure type and onceness go, only three
3143 // combinations are legit:
3147 // If the actual and expected closure type disagree with
3148 // each other, set expected onceness to be always Once or
3149 // Many according to the actual type. Otherwise, it will
3150 // yield either an illegal "many proc" or a less known
3151 // "once closure" in the error message.
3152 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
3153 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
3155 (&ty::UniqTraitStore, _) => ast::Once,
3156 (&ty::RegionTraitStore(..), _) => ast::Many,
3158 (Some(sig), onceness, cenv.bounds)
3161 // Not an error! Means we're inferring the closure type
3162 let (bounds, onceness) = match expr.node {
3163 ast::ExprProc(..) => {
3164 let mut bounds = ty::region_existential_bound(ty::ReStatic);
3165 bounds.builtin_bounds.add(ty::BoundSend); // FIXME
3169 let region = fcx.infcx().next_region_var(
3170 infer::AddrOfRegion(expr.span));
3171 (ty::region_existential_bound(region), ast::Many)
3174 (None, onceness, bounds)
3179 // construct the function type
3180 let fn_ty = astconv::ty_of_closure(fcx,
3189 let fty_sig = fn_ty.sig.clone();
3190 let fty = ty::mk_closure(tcx, fn_ty);
3191 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
3193 fcx.write_ty(expr.id, fty);
3195 // If the closure is a stack closure and hasn't had some non-standard
3196 // style inferred for it, then check it under its parent's style.
3197 // Otherwise, use its own
3198 let (inherited_style, inherited_style_id) = match store {
3199 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
3200 fcx.ps.borrow().def),
3201 ty::UniqTraitStore => (ast::NormalFn, expr.id)
3215 // Check field access expressions
3216 fn check_field(fcx: &FnCtxt,
3218 lvalue_pref: LvaluePreference,
3220 field: &ast::SpannedIdent,
3221 tys: &[ast::P<ast::Ty>]) {
3222 let tcx = fcx.ccx.tcx;
3223 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3224 let expr_t = structurally_resolved_type(fcx, expr.span,
3226 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
3227 let (_, autoderefs, field_ty) =
3228 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
3229 match ty::get(base_t).sty {
3230 ty::ty_struct(base_id, ref substs) => {
3231 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
3232 let fields = ty::lookup_struct_fields(tcx, base_id);
3233 lookup_field_ty(tcx, base_id, fields.as_slice(),
3234 field.node.name, &(*substs))
3241 fcx.write_ty(expr.id, field_ty);
3242 fcx.write_autoderef_adjustment(base.id, autoderefs);
3248 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
3249 match method::lookup(fcx,
3256 CheckTraitsAndInherentMethods,
3258 IgnoreStaticMethods) {
3260 fcx.type_error_message(
3263 format!("attempted to take value of method `{}` on type \
3264 `{}`", token::get_ident(field.node), actual)
3268 tcx.sess.span_note(field.span,
3269 "maybe a missing `()` to call it? If not, try an anonymous function.");
3273 fcx.type_error_message(
3276 format!("attempted access of field `{}` on \
3277 type `{}`, but no field with that \
3279 token::get_ident(field.node),
3286 fcx.write_error(expr.id);
3289 fn check_struct_or_variant_fields(fcx: &FnCtxt,
3292 class_id: ast::DefId,
3293 node_id: ast::NodeId,
3294 substitutions: subst::Substs,
3295 field_types: &[ty::field_ty],
3296 ast_fields: &[ast::Field],
3297 check_completeness: bool) {
3298 let tcx = fcx.ccx.tcx;
3300 let mut class_field_map = HashMap::new();
3301 let mut fields_found = 0;
3302 for field in field_types.iter() {
3303 class_field_map.insert(field.name, (field.id, false));
3306 let mut error_happened = false;
3308 // Typecheck each field.
3309 for field in ast_fields.iter() {
3310 let mut expected_field_type = ty::mk_err();
3312 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
3315 fcx.type_error_message(
3318 format!("structure `{}` has no field named `{}`",
3319 actual, token::get_ident(field.ident.node))
3323 error_happened = true;
3325 Some((_, true)) => {
3326 span_err!(fcx.tcx().sess, field.ident.span, E0062,
3327 "field `{}` specified more than once",
3328 token::get_ident(field.ident.node));
3329 error_happened = true;
3331 Some((field_id, false)) => {
3332 expected_field_type =
3333 ty::lookup_field_type(
3334 tcx, class_id, field_id, &substitutions);
3335 class_field_map.insert(
3336 field.ident.node.name, (field_id, true));
3340 // Make sure to give a type to the field even if there's
3341 // an error, so we can continue typechecking
3342 check_expr_coercable_to_type(
3345 expected_field_type);
3349 fcx.write_error(node_id);
3352 if check_completeness && !error_happened {
3353 // Make sure the programmer specified all the fields.
3354 assert!(fields_found <= field_types.len());
3355 if fields_found < field_types.len() {
3356 let mut missing_fields = Vec::new();
3357 for class_field in field_types.iter() {
3358 let name = class_field.name;
3359 let (_, seen) = *class_field_map.get(&name);
3361 missing_fields.push(
3362 format!("`{}`", token::get_name(name).get()))
3366 span_err!(tcx.sess, span, E0063,
3367 "missing field{}: {}",
3368 if missing_fields.len() == 1 {""} else {"s"},
3369 missing_fields.connect(", "));
3373 if !error_happened {
3374 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
3375 class_id, substitutions));
3379 fn check_struct_constructor(fcx: &FnCtxt,
3381 span: codemap::Span,
3382 class_id: ast::DefId,
3383 fields: &[ast::Field],
3384 base_expr: Option<Gc<ast::Expr>>) {
3385 let tcx = fcx.ccx.tcx;
3387 // Look up the number of type parameters and the raw type, and
3388 // determine whether the class is region-parameterized.
3389 let item_type = ty::lookup_item_type(tcx, class_id);
3390 let raw_type = item_type.ty;
3392 // Generate the struct type.
3393 let substitutions = fcx.infcx().fresh_substs_for_type(
3394 span, &item_type.generics);
3395 let mut struct_type = raw_type.subst(tcx, &substitutions);
3397 // Look up and check the fields.
3398 let class_fields = ty::lookup_struct_fields(tcx, class_id);
3399 check_struct_or_variant_fields(fcx,
3405 class_fields.as_slice(),
3407 base_expr.is_none());
3408 if ty::type_is_error(fcx.node_ty(id)) {
3409 struct_type = ty::mk_err();
3412 // Check the base expression if necessary.
3415 Some(base_expr) => {
3416 check_expr_has_type(fcx, &*base_expr, struct_type);
3417 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
3418 struct_type = ty::mk_bot();
3423 // Write in the resulting type.
3424 fcx.write_ty(id, struct_type);
3427 fn check_struct_enum_variant(fcx: &FnCtxt,
3429 span: codemap::Span,
3430 enum_id: ast::DefId,
3431 variant_id: ast::DefId,
3432 fields: &[ast::Field]) {
3433 let tcx = fcx.ccx.tcx;
3435 // Look up the number of type parameters and the raw type, and
3436 // determine whether the enum is region-parameterized.
3437 let item_type = ty::lookup_item_type(tcx, enum_id);
3438 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
3439 let enum_type = item_type.ty.subst(tcx, &substitutions);
3441 // Look up and check the enum variant fields.
3442 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
3443 check_struct_or_variant_fields(fcx,
3449 variant_fields.as_slice(),
3452 fcx.write_ty(id, enum_type);
3455 fn check_struct_fields_on_error(fcx: &FnCtxt,
3457 fields: &[ast::Field],
3458 base_expr: Option<Gc<ast::Expr>>) {
3459 // Make sure to still write the types
3460 // otherwise we might ICE
3461 fcx.write_error(id);
3462 for field in fields.iter() {
3463 check_expr(fcx, &*field.expr);
3466 Some(ref base) => check_expr(fcx, &**base),
3471 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
3473 let tcx = fcx.ccx.tcx;
3476 ast::ExprBox(ref place, ref subexpr) => {
3477 check_expr(fcx, &**place);
3478 check_expr(fcx, &**subexpr);
3480 let mut checked = false;
3482 ast::ExprPath(ref path) => {
3483 // FIXME(pcwalton): For now we hardcode the two permissible
3484 // places: the exchange heap and the managed heap.
3485 let definition = lookup_def(fcx, path.span, place.id);
3486 let def_id = definition.def_id();
3487 let referent_ty = fcx.expr_ty(&**subexpr);
3488 if tcx.lang_items.exchange_heap() == Some(def_id) {
3489 fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
3491 } else if tcx.lang_items.managed_heap() == Some(def_id) {
3492 fcx.register_region_obligation(infer::Managed(expr.span),
3495 fcx.write_ty(id, ty::mk_box(tcx, referent_ty));
3503 span_err!(tcx.sess, expr.span, E0066,
3504 "only the managed heap and exchange heap are currently supported");
3505 fcx.write_ty(id, ty::mk_err());
3509 ast::ExprLit(lit) => {
3510 let typ = check_lit(fcx, &*lit, expected);
3511 fcx.write_ty(id, typ);
3513 ast::ExprBinary(op, ref lhs, ref rhs) => {
3514 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
3516 let lhs_ty = fcx.expr_ty(&**lhs);
3517 let rhs_ty = fcx.expr_ty(&**rhs);
3518 if ty::type_is_error(lhs_ty) ||
3519 ty::type_is_error(rhs_ty) {
3520 fcx.write_error(id);
3522 else if ty::type_is_bot(lhs_ty) ||
3523 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3527 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3528 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3530 let lhs_t = fcx.expr_ty(&**lhs);
3531 let result_t = fcx.expr_ty(expr);
3532 demand::suptype(fcx, expr.span, result_t, lhs_t);
3534 let tcx = fcx.tcx();
3535 if !ty::expr_is_lval(tcx, &**lhs) {
3536 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3539 // Overwrite result of check_binop...this preserves existing behavior
3540 // but seems quite dubious with regard to user-defined methods
3541 // and so forth. - Niko
3542 if !ty::type_is_error(result_t)
3543 && !ty::type_is_bot(result_t) {
3544 fcx.write_nil(expr.id);
3547 ast::ExprUnary(unop, ref oprnd) => {
3548 let expected_inner = expected.map(fcx, |sty| {
3550 ast::UnBox | ast::UnUniq => match *sty {
3551 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3558 ast::UnNot | ast::UnNeg => {
3566 let lvalue_pref = match unop {
3567 ast::UnDeref => lvalue_pref,
3570 check_expr_with_expectation_and_lvalue_pref(
3571 fcx, &**oprnd, expected_inner, lvalue_pref);
3572 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3573 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3576 oprnd_t = ty::mk_box(tcx, oprnd_t)
3579 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3582 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3583 oprnd_t = match ty::deref(oprnd_t, true) {
3585 None => match try_overloaded_deref(fcx, expr.span,
3586 Some(MethodCall::expr(expr.id)),
3587 Some(&**oprnd), oprnd_t, lvalue_pref) {
3590 let is_newtype = match ty::get(oprnd_t).sty {
3591 ty::ty_struct(did, ref substs) => {
3592 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3594 && fields.get(0).ident ==
3595 token::special_idents::unnamed_field
3600 // This is an obsolete struct deref
3601 span_err!(tcx.sess, expr.span, E0068,
3602 "single-field tuple-structs can \
3603 no longer be dereferenced");
3605 fcx.type_error_message(expr.span, |actual| {
3606 format!("type `{}` cannot be \
3607 dereferenced", actual)
3616 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3618 if !(ty::type_is_integral(oprnd_t) ||
3619 ty::get(oprnd_t).sty == ty::ty_bool) {
3620 oprnd_t = check_user_unop(fcx, "!", "not",
3621 tcx.lang_items.not_trait(),
3622 expr, oprnd.clone(), oprnd_t);
3626 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3628 if !(ty::type_is_integral(oprnd_t) ||
3629 ty::type_is_fp(oprnd_t)) {
3630 oprnd_t = check_user_unop(fcx, "-", "neg",
3631 tcx.lang_items.neg_trait(),
3632 expr, oprnd.clone(), oprnd_t);
3637 fcx.write_ty(id, oprnd_t);
3639 ast::ExprAddrOf(mutbl, ref oprnd) => {
3640 let expected = expected.only_has_type();
3641 let hint = expected.map(fcx, |sty| {
3642 match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
3643 _ => NoExpectation }
3645 let lvalue_pref = match mutbl {
3646 ast::MutMutable => PreferMutLvalue,
3647 ast::MutImmutable => NoPreference
3649 check_expr_with_expectation_and_lvalue_pref(fcx,
3654 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3655 let oprnd_t = if ty::type_is_error(tm.ty) {
3657 } else if ty::type_is_bot(tm.ty) {
3661 // Note: at this point, we cannot say what the best lifetime
3662 // is to use for resulting pointer. We want to use the
3663 // shortest lifetime possible so as to avoid spurious borrowck
3664 // errors. Moreover, the longest lifetime will depend on the
3665 // precise details of the value whose address is being taken
3666 // (and how long it is valid), which we don't know yet until type
3667 // inference is complete.
3669 // Therefore, here we simply generate a region variable. The
3670 // region inferencer will then select the ultimate value.
3671 // Finally, borrowck is charged with guaranteeing that the
3672 // value whose address was taken can actually be made to live
3673 // as long as it needs to live.
3675 // String literals are already, implicitly converted to slices.
3676 //ast::ExprLit(lit) if ast_util::lit_is_str(lit) => fcx.expr_ty(oprnd),
3677 // Empty slices live in static memory.
3678 ast::ExprVec(ref elements) if elements.len() == 0 => {
3679 // Note: we do not assign a lifetime of
3680 // static. This is because the resulting type
3681 // `&'static [T]` would require that T outlives
3683 let region = fcx.infcx().next_region_var(
3684 infer::AddrOfSlice(expr.span));
3685 ty::mk_rptr(tcx, region, tm)
3688 let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
3689 ty::mk_rptr(tcx, region, tm)
3693 fcx.write_ty(id, oprnd_t);
3695 ast::ExprPath(ref pth) => {
3696 let defn = lookup_def(fcx, pth.span, id);
3697 let pty = polytype_for_def(fcx, expr.span, defn);
3698 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3700 // We always require that the type provided as the value for
3701 // a type parameter outlives the moment of instantiation.
3702 constrain_path_type_parameters(fcx, expr);
3704 ast::ExprInlineAsm(ref ia) => {
3705 for &(_, ref input) in ia.inputs.iter() {
3706 check_expr(fcx, &**input);
3708 for &(_, ref out, _) in ia.outputs.iter() {
3709 check_expr(fcx, &**out);
3713 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3714 ast::ExprBreak(_) => { fcx.write_bot(id); }
3715 ast::ExprAgain(_) => { fcx.write_bot(id); }
3716 ast::ExprRet(ref expr_opt) => {
3717 let ret_ty = fcx.ret_ty;
3719 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3720 ret_ty, ty::mk_nil()) {
3721 Ok(_) => { /* fall through */ }
3723 span_err!(tcx.sess, expr.span, E0069,
3724 "`return;` in function returning non-nil");
3728 check_expr_coercable_to_type(fcx, &**e, ret_ty);
3733 ast::ExprParen(a) => {
3734 check_expr_with_expectation_and_lvalue_pref(fcx,
3738 fcx.write_ty(id, fcx.expr_ty(&*a));
3740 ast::ExprAssign(ref lhs, ref rhs) => {
3741 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3743 let tcx = fcx.tcx();
3744 if !ty::expr_is_lval(tcx, &**lhs) {
3745 span_err!(tcx.sess, expr.span, E0070,
3746 "illegal left-hand side expression");
3749 let lhs_ty = fcx.expr_ty(&**lhs);
3750 check_expr_has_type(fcx, &**rhs, lhs_ty);
3751 let rhs_ty = fcx.expr_ty(&**rhs);
3753 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3754 fcx.write_error(id);
3755 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3761 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3762 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3763 id, expr.span, expected);
3765 ast::ExprWhile(ref cond, ref body, _) => {
3766 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3767 check_block_no_value(fcx, &**body);
3768 let cond_ty = fcx.expr_ty(&**cond);
3769 let body_ty = fcx.node_ty(body.id);
3770 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3771 fcx.write_error(id);
3773 else if ty::type_is_bot(cond_ty) {
3780 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3781 check_expr(fcx, &**head);
3782 let typ = lookup_method_for_for_loop(fcx, *head, expr.id);
3783 vtable::early_resolve_expr(expr, fcx, true);
3785 let pcx = pat_ctxt {
3787 map: pat_id_map(&tcx.def_map, &**pat),
3789 _match::check_pat(&pcx, &**pat, typ);
3791 check_block_no_value(fcx, &**block);
3794 ast::ExprLoop(ref body, _) => {
3795 check_block_no_value(fcx, &**body);
3796 if !may_break(tcx, expr.id, body.clone()) {
3803 ast::ExprMatch(ref discrim, ref arms) => {
3804 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3806 ast::ExprFnBlock(_, ref decl, ref body) => {
3807 let region = astconv::opt_ast_region_to_region(fcx,
3813 ty::RegionTraitStore(region, ast::MutMutable),
3818 ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
3819 check_unboxed_closure(fcx,
3825 ast::ExprProc(ref decl, ref body) => {
3833 ast::ExprBlock(ref b) => {
3834 check_block_with_expected(fcx, &**b, expected);
3835 fcx.write_ty(id, fcx.node_ty(b.id));
3837 ast::ExprCall(ref f, ref args) => {
3838 // Index expressions need to be handled separately, to inform them
3839 // that they appear in call position.
3840 check_expr(fcx, &**f);
3841 let f_ty = fcx.expr_ty(&**f);
3843 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3844 check_call(fcx, expr, &**f, args.as_slice());
3845 let (args_bot, args_err) = args.iter().fold((false, false),
3846 |(rest_bot, rest_err), a| {
3847 // is this not working?
3848 let a_ty = fcx.expr_ty(&**a);
3849 (rest_bot || ty::type_is_bot(a_ty),
3850 rest_err || ty::type_is_error(a_ty))});
3851 if ty::type_is_error(f_ty) || args_err {
3852 fcx.write_error(id);
3854 else if ty::type_is_bot(f_ty) || args_bot {
3859 ast::ExprMethodCall(ident, ref tps, ref args) => {
3860 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3861 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3862 let (args_bot, args_err) = arg_tys.fold((false, false),
3863 |(rest_bot, rest_err), a| {
3864 (rest_bot || ty::type_is_bot(a),
3865 rest_err || ty::type_is_error(a))});
3867 fcx.write_error(id);
3868 } else if args_bot {
3872 ast::ExprCast(ref e, ref t) => {
3874 ast::TyFixedLengthVec(_, ref count_expr) => {
3875 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3879 check_cast(fcx, &**e, &**t, id, expr.span);
3881 ast::ExprVec(ref args) => {
3882 let uty = match expected {
3883 ExpectHasType(uty) => {
3884 match ty::get(uty).sty {
3885 ty::ty_vec(ty, _) => Some(ty),
3892 let typ = match uty {
3894 for e in args.iter() {
3895 check_expr_coercable_to_type(fcx, &**e, uty);
3900 let t: ty::t = fcx.infcx().next_ty_var();
3901 for e in args.iter() {
3902 check_expr_has_type(fcx, &**e, t);
3907 let typ = ty::mk_vec(tcx, typ, Some(args.len()));
3908 fcx.write_ty(id, typ);
3910 ast::ExprRepeat(ref element, ref count_expr) => {
3911 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3912 let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
3914 let uty = match expected {
3915 ExpectHasType(uty) => {
3916 match ty::get(uty).sty {
3917 ty::ty_vec(ty, _) => Some(ty),
3924 let (element_ty, t) = match uty {
3926 check_expr_coercable_to_type(fcx, &**element, uty);
3930 let t: ty::t = fcx.infcx().next_ty_var();
3931 check_expr_has_type(fcx, &**element, t);
3932 (fcx.expr_ty(&**element), t)
3936 if ty::type_is_error(element_ty) {
3937 fcx.write_error(id);
3938 } else if ty::type_is_bot(element_ty) {
3941 let t = ty::mk_vec(tcx, t, Some(count));
3942 fcx.write_ty(id, t);
3945 ast::ExprTup(ref elts) => {
3946 let expected = expected.only_has_type();
3947 let flds = expected.map_to_option(fcx, |sty| {
3949 ty::ty_tup(ref flds) => Some((*flds).clone()),
3953 let mut bot_field = false;
3954 let mut err_field = false;
3956 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3957 let t = match flds {
3958 Some(ref fs) if i < fs.len() => {
3959 let ety = *fs.get(i);
3960 check_expr_coercable_to_type(fcx, &**e, ety);
3964 check_expr_with_expectation(fcx, &**e, NoExpectation);
3968 err_field = err_field || ty::type_is_error(t);
3969 bot_field = bot_field || ty::type_is_bot(t);
3974 } else if err_field {
3975 fcx.write_error(id);
3977 let typ = ty::mk_tup(tcx, elt_ts);
3978 fcx.write_ty(id, typ);
3981 ast::ExprStruct(ref path, ref fields, base_expr) => {
3982 // Resolve the path.
3983 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3984 let struct_id = match def {
3985 Some(def::DefVariant(enum_id, variant_id, _)) => {
3986 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3987 variant_id, fields.as_slice());
3990 Some(def::DefTrait(def_id)) => {
3991 span_err!(tcx.sess, path.span, E0159,
3992 "use of trait `{}` as a struct constructor",
3993 pprust::path_to_string(path));
3994 check_struct_fields_on_error(fcx,
4001 // Verify that this was actually a struct.
4002 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
4003 match ty::get(typ.ty).sty {
4004 ty::ty_struct(struct_did, _) => {
4005 check_struct_constructor(fcx,
4013 span_err!(tcx.sess, path.span, E0071,
4014 "`{}` does not name a structure",
4015 pprust::path_to_string(path));
4016 check_struct_fields_on_error(fcx,
4026 tcx.sess.span_bug(path.span,
4027 "structure constructor wasn't resolved")
4031 // Turn the path into a type and verify that that type unifies with
4032 // the resulting structure type. This is needed to handle type
4033 // parameters correctly.
4034 let actual_structure_type = fcx.expr_ty(&*expr);
4035 if !ty::type_is_error(actual_structure_type) {
4036 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4040 match fcx.mk_subty(false,
4041 infer::Misc(path.span),
4042 actual_structure_type,
4043 type_and_substs.ty) {
4045 Err(type_error) => {
4046 let type_error_description =
4047 ty::type_err_to_str(tcx, &type_error);
4050 .span_err(path.span,
4051 format!("structure constructor specifies a \
4052 structure of type `{}`, but this \
4053 structure has type `{}`: {}",
4055 .ty_to_string(type_and_substs.ty),
4058 actual_structure_type),
4059 type_error_description).as_slice());
4060 ty::note_and_explain_type_err(tcx, &type_error);
4065 ast::ExprField(ref base, ref field, ref tys) => {
4066 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
4068 ast::ExprIndex(ref base, ref idx) => {
4069 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
4070 check_expr(fcx, &**idx);
4071 let raw_base_t = fcx.expr_ty(&**base);
4072 let idx_t = fcx.expr_ty(&**idx);
4073 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
4074 fcx.write_ty(id, raw_base_t);
4075 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
4076 fcx.write_ty(id, idx_t);
4078 let (_, autoderefs, field_ty) =
4079 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
4080 lvalue_pref, |base_t, _| ty::index(base_t));
4083 check_expr_has_type(fcx, &**idx, ty::mk_uint());
4084 fcx.write_ty(id, ty);
4085 fcx.write_autoderef_adjustment(base.id, autoderefs);
4088 // This is an overloaded method.
4089 let base_t = structurally_resolved_type(fcx,
4092 let method_call = MethodCall::expr(expr.id);
4093 match try_overloaded_index(fcx,
4100 Some(mt) => fcx.write_ty(id, mt.ty),
4102 fcx.type_error_message(expr.span,
4112 fcx.write_ty(id, ty::mk_err())
4121 debug!("type of expr({}) {} is...", expr.id,
4122 syntax::print::pprust::expr_to_string(expr));
4123 debug!("... {}, expected is {}",
4124 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
4125 expected.repr(tcx));
4130 fn constrain_path_type_parameters(fcx: &FnCtxt,
4133 fcx.opt_node_ty_substs(expr.id, |item_substs| {
4134 for &ty in item_substs.substs.types.iter() {
4135 let default_bound = ty::ReScope(expr.id);
4136 let origin = infer::RelateDefaultParamBound(expr.span, ty);
4137 fcx.register_region_obligation(origin, ty, default_bound);
4143 fn only_has_type(self) -> Expectation {
4145 NoExpectation | ExpectCastableToType(..) => NoExpectation,
4146 ExpectHasType(t) => ExpectHasType(t)
4150 // Resolves `expected` by a single level if it is a variable. If
4151 // there is no expected type or resolution is not possible (e.g.,
4152 // no constraints yet present), just returns `None`.
4153 fn resolve(self, fcx: &FnCtxt) -> Expectation {
4158 ExpectCastableToType(t) => {
4159 ExpectCastableToType(
4160 fcx.infcx().resolve_type_vars_if_possible(t))
4162 ExpectHasType(t) => {
4164 fcx.infcx().resolve_type_vars_if_possible(t))
4169 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
4170 match self.resolve(fcx) {
4171 NoExpectation => NoExpectation,
4172 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4176 fn map_to_option<O>(self,
4178 unpack: |&ty::sty| -> Option<O>)
4181 match self.resolve(fcx) {
4182 NoExpectation => None,
4183 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
4188 impl Repr for Expectation {
4189 fn repr(&self, tcx: &ty::ctxt) -> String {
4191 NoExpectation => format!("NoExpectation"),
4192 ExpectHasType(t) => format!("ExpectHasType({})",
4194 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
4200 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
4201 if !type_is_uint(fcx, sp, t) {
4202 fcx.type_error_message(sp, |actual| {
4203 format!("mismatched types: expected `uint` type, found `{}`",
4209 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
4210 if !type_is_integral(fcx, sp, t) {
4211 fcx.type_error_message(sp, |actual| {
4212 format!("mismatched types: expected integral type, found `{}`",
4218 pub fn check_decl_initializer(fcx: &FnCtxt,
4222 let local_ty = fcx.local_ty(init.span, nid);
4223 check_expr_coercable_to_type(fcx, init, local_ty)
4226 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
4227 let tcx = fcx.ccx.tcx;
4229 let t = fcx.local_ty(local.span, local.id);
4230 fcx.write_ty(local.id, t);
4234 check_decl_initializer(fcx, local.id, &**init);
4235 let init_ty = fcx.expr_ty(&**init);
4236 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
4237 fcx.write_ty(local.id, init_ty);
4243 let pcx = pat_ctxt {
4245 map: pat_id_map(&tcx.def_map, &*local.pat),
4247 _match::check_pat(&pcx, &*local.pat, t);
4248 let pat_ty = fcx.node_ty(local.pat.id);
4249 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
4250 fcx.write_ty(local.id, pat_ty);
4254 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
4256 let mut saw_bot = false;
4257 let mut saw_err = false;
4259 ast::StmtDecl(decl, id) => {
4262 ast::DeclLocal(ref l) => {
4263 check_decl_local(fcx, &**l);
4264 let l_t = fcx.node_ty(l.id);
4265 saw_bot = saw_bot || ty::type_is_bot(l_t);
4266 saw_err = saw_err || ty::type_is_error(l_t);
4268 ast::DeclItem(_) => {/* ignore for now */ }
4271 ast::StmtExpr(ref expr, id) => {
4273 // Check with expected type of ()
4274 check_expr_has_type(fcx, &**expr, ty::mk_nil());
4275 let expr_ty = fcx.expr_ty(&**expr);
4276 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
4277 saw_err = saw_err || ty::type_is_error(expr_ty);
4279 ast::StmtSemi(ref expr, id) => {
4281 check_expr(fcx, &**expr);
4282 let expr_ty = fcx.expr_ty(&**expr);
4283 saw_bot |= ty::type_is_bot(expr_ty);
4284 saw_err |= ty::type_is_error(expr_ty);
4286 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
4289 fcx.write_bot(node_id);
4292 fcx.write_error(node_id);
4295 fcx.write_nil(node_id)
4299 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
4300 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
4301 let blkty = fcx.node_ty(blk.id);
4302 if ty::type_is_error(blkty) {
4303 fcx.write_error(blk.id);
4305 else if ty::type_is_bot(blkty) {
4306 fcx.write_bot(blk.id);
4309 let nilty = ty::mk_nil();
4310 demand::suptype(fcx, blk.span, nilty, blkty);
4314 fn check_block_with_expected(fcx: &FnCtxt,
4316 expected: Expectation) {
4318 let mut fcx_ps = fcx.ps.borrow_mut();
4319 let fn_style_state = fcx_ps.recurse(blk);
4320 replace(&mut *fcx_ps, fn_style_state)
4323 let mut warned = false;
4324 let mut last_was_bot = false;
4325 let mut any_bot = false;
4326 let mut any_err = false;
4327 for s in blk.stmts.iter() {
4328 check_stmt(fcx, &**s);
4329 let s_id = ast_util::stmt_id(&**s);
4330 let s_ty = fcx.node_ty(s_id);
4331 if last_was_bot && !warned && match s.node {
4332 ast::StmtDecl(decl, _) => {
4334 ast::DeclLocal(_) => true,
4338 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
4344 .add_lint(lint::builtin::UNREACHABLE_CODE,
4347 "unreachable statement".to_string());
4350 if ty::type_is_bot(s_ty) {
4351 last_was_bot = true;
4353 any_bot = any_bot || ty::type_is_bot(s_ty);
4354 any_err = any_err || ty::type_is_error(s_ty);
4357 None => if any_err {
4358 fcx.write_error(blk.id);
4361 fcx.write_bot(blk.id);
4364 fcx.write_nil(blk.id);
4367 if any_bot && !warned {
4371 .add_lint(lint::builtin::UNREACHABLE_CODE,
4374 "unreachable expression".to_string());
4376 let ety = match expected {
4377 ExpectHasType(ety) => {
4378 check_expr_coercable_to_type(fcx, &*e, ety);
4382 check_expr_with_expectation(fcx, &*e, expected);
4387 fcx.write_ty(blk.id, ety);
4389 fcx.write_error(blk.id);
4391 fcx.write_bot(blk.id);
4396 *fcx.ps.borrow_mut() = prev;
4399 /// Checks a constant appearing in a type. At the moment this is just the
4400 /// length expression in a fixed-length vector, but someday it might be
4401 /// extended to type-level numeric literals.
4402 pub fn check_const_in_type(tcx: &ty::ctxt,
4404 expected_type: ty::t) {
4405 // Synthesize a crate context. The trait map is not needed here (though I
4406 // imagine it will be if we have associated statics --pcwalton), so we
4408 let ccx = CrateCtxt {
4409 trait_map: NodeMap::new(),
4412 let inh = static_inherited_fields(&ccx);
4413 let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
4414 check_const_with_ty(&fcx, expr.span, expr, expected_type);
4417 pub fn check_const(ccx: &CrateCtxt,
4421 let inh = static_inherited_fields(ccx);
4422 let rty = ty::node_id_to_type(ccx.tcx, id);
4423 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4424 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
4425 check_const_with_ty(&fcx, sp, e, declty);
4428 pub fn check_const_with_ty(fcx: &FnCtxt,
4432 // Gather locals in statics (because of block expressions).
4433 // This is technically unnecessary because locals in static items are forbidden,
4434 // but prevents type checking from blowing up before const checking can properly
4436 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
4438 check_expr_with_hint(fcx, e, declty);
4439 demand::coerce(fcx, e.span, declty, e);
4440 regionck::regionck_expr(fcx, e);
4441 writeback::resolve_type_vars_in_expr(fcx, e);
4444 /// Checks whether a type can be represented in memory. In particular, it
4445 /// identifies types that contain themselves without indirection through a
4446 /// pointer, which would mean their size is unbounded. This is different from
4447 /// the question of whether a type can be instantiated. See the definition of
4448 /// `check_instantiable`.
4449 pub fn check_representable(tcx: &ty::ctxt,
4451 item_id: ast::NodeId,
4452 designation: &str) -> bool {
4453 let rty = ty::node_id_to_type(tcx, item_id);
4455 // Check that it is possible to represent this type. This call identifies
4456 // (1) types that contain themselves and (2) types that contain a different
4457 // recursive type. It is only necessary to throw an error on those that
4458 // contain themselves. For case 2, there must be an inner type that will be
4459 // caught by case 1.
4460 match ty::is_type_representable(tcx, sp, rty) {
4461 ty::SelfRecursive => {
4462 span_err!(tcx.sess, sp, E0072,
4463 "illegal recursive {} type; \
4464 wrap the inner value in a box to make it representable",
4468 ty::Representable | ty::ContainsRecursive => (),
4473 /// Checks whether a type can be created without an instance of itself.
4474 /// This is similar but different from the question of whether a type
4475 /// can be represented. For example, the following type:
4477 /// enum foo { None, Some(foo) }
4479 /// is instantiable but is not representable. Similarly, the type
4481 /// enum foo { Some(@foo) }
4483 /// is representable, but not instantiable.
4484 pub fn check_instantiable(tcx: &ty::ctxt,
4486 item_id: ast::NodeId)
4488 let item_ty = ty::node_id_to_type(tcx, item_id);
4489 if !ty::is_instantiable(tcx, item_ty) {
4490 span_err!(tcx.sess, sp, E0073,
4491 "this type cannot be instantiated without an \
4492 instance of itself; consider using `Option<{}>`",
4493 ppaux::ty_to_string(tcx, item_ty));
4500 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
4501 let t = ty::node_id_to_type(tcx, id);
4502 if ty::type_needs_subst(t) {
4503 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4506 match ty::get(t).sty {
4507 ty::ty_struct(did, ref substs) => {
4508 let fields = ty::lookup_struct_fields(tcx, did);
4509 if fields.is_empty() {
4510 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4513 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
4514 if !fields.iter().all(
4515 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4516 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4519 if !ty::type_is_machine(e) {
4520 span_err!(tcx.sess, sp, E0077,
4521 "SIMD vector element type should be machine type");
4530 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4531 vs: &[ast::P<ast::Variant>]) {
4532 for &v in vs.iter() {
4534 ast::TupleVariantKind(ref args) if args.len() > 0 => {
4535 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4536 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4537 let len = arg_tys.len();
4541 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4542 // Allow the last field in an enum to be unsized.
4543 // We want to do this so that we can support smart pointers.
4544 // A struct value with an unsized final field is itself
4545 // unsized and we must track this in the type system.
4546 if !ty::type_is_sized(ccx.tcx, *t) {
4547 span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4548 "type `{}` is dynamically sized. dynamically sized types may only \
4549 appear as the final type in a variant",
4550 ppaux::ty_to_string(ccx.tcx, *t));
4554 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
4560 pub fn check_enum_variants(ccx: &CrateCtxt,
4562 vs: &[ast::P<ast::Variant>],
4565 fn disr_in_range(ccx: &CrateCtxt,
4567 disr: ty::Disr) -> bool {
4568 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4570 ast::TyU8 => disr as u8 as Disr == disr,
4571 ast::TyU16 => disr as u16 as Disr == disr,
4572 ast::TyU32 => disr as u32 as Disr == disr,
4573 ast::TyU64 => disr as u64 as Disr == disr,
4574 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4577 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4579 ast::TyI8 => disr as i8 as Disr == disr,
4580 ast::TyI16 => disr as i16 as Disr == disr,
4581 ast::TyI32 => disr as i32 as Disr == disr,
4582 ast::TyI64 => disr as i64 as Disr == disr,
4583 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4587 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4588 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4592 fn do_check(ccx: &CrateCtxt,
4593 vs: &[ast::P<ast::Variant>],
4595 hint: attr::ReprAttr)
4596 -> Vec<Rc<ty::VariantInfo>> {
4598 let rty = ty::node_id_to_type(ccx.tcx, id);
4599 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4600 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4601 let mut prev_disr_val: Option<ty::Disr> = None;
4603 for &v in vs.iter() {
4605 // If the discriminant value is specified explicitly in the enum check whether the
4606 // initialization expression is valid, otherwise use the last value plus one.
4607 let mut current_disr_val = match prev_disr_val {
4608 Some(prev_disr_val) => prev_disr_val + 1,
4609 None => ty::INITIAL_DISCRIMINANT_VALUE
4612 match v.node.disr_expr {
4614 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
4616 let inh = static_inherited_fields(ccx);
4617 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4618 let declty = match hint {
4619 attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
4620 attr::ReprInt(_, attr::SignedInt(ity)) => {
4621 ty::mk_mach_int(ity)
4623 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4624 ty::mk_mach_uint(ity)
4627 check_const_with_ty(&fcx, e.span, &*e, declty);
4628 // check_expr (from check_const pass) doesn't guarantee
4629 // that the expression is in a form that eval_const_expr can
4630 // handle, so we may still get an internal compiler error
4632 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
4633 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4634 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4636 span_err!(ccx.tcx.sess, e.span, E0079,
4637 "expected signed integer constant");
4640 span_err!(ccx.tcx.sess, e.span, E0080,
4641 "expected constant: {}", *err);
4648 // Check for duplicate discriminant values
4649 if disr_vals.contains(¤t_disr_val) {
4650 span_err!(ccx.tcx.sess, v.span, E0081,
4651 "discriminant value already exists");
4653 // Check for unrepresentable discriminant values
4655 attr::ReprAny | attr::ReprExtern => (),
4656 attr::ReprInt(sp, ity) => {
4657 if !disr_in_range(ccx, ity, current_disr_val) {
4658 span_err!(ccx.tcx.sess, v.span, E0082,
4659 "discriminant value outside specified type");
4660 span_note!(ccx.tcx.sess, sp,
4661 "discriminant type specified here");
4664 attr::ReprPacked => {
4665 ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4668 disr_vals.push(current_disr_val);
4670 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
4672 prev_disr_val = Some(current_disr_val);
4674 variants.push(variant_info);
4680 let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
4681 .as_slice().get(0).unwrap_or(&attr::ReprAny);
4683 if hint != attr::ReprAny && vs.len() <= 1 {
4685 span_err!(ccx.tcx.sess, sp, E0083,
4686 "unsupported representation for univariant enum");
4688 span_err!(ccx.tcx.sess, sp, E0084,
4689 "unsupported representation for zero-variant enum");
4693 let variants = do_check(ccx, vs, id, hint);
4695 // cache so that ty::enum_variants won't repeat this work
4696 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4698 check_representable(ccx.tcx, sp, id, "enum");
4700 // Check that it is possible to instantiate this enum:
4702 // This *sounds* like the same that as representable, but it's
4703 // not. See def'n of `check_instantiable()` for details.
4704 check_instantiable(ccx.tcx, sp, id);
4707 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4708 lookup_def_ccx(fcx.ccx, sp, id)
4711 // Returns the type parameter count and the type for the given definition.
4712 pub fn polytype_for_def(fcx: &FnCtxt,
4717 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4718 def::DefBinding(nid, _) => {
4719 let typ = fcx.local_ty(sp, nid);
4720 return no_params(typ);
4722 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4723 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4724 def::DefStruct(id) => {
4725 return ty::lookup_item_type(fcx.ccx.tcx, id);
4727 def::DefUpvar(_, inner, _, _) => {
4728 return polytype_for_def(fcx, sp, *inner);
4733 def::DefTyParam(..)=> {
4734 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
4736 def::DefMod(..) | def::DefForeignMod(..) => {
4737 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found module");
4739 def::DefUse(..) => {
4740 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found use");
4742 def::DefRegion(..) => {
4743 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found region");
4745 def::DefTyParamBinder(..) => {
4746 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type parameter");
4748 def::DefLabel(..) => {
4749 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found label");
4751 def::DefSelfTy(..) => {
4752 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found self ty");
4754 def::DefMethod(..) => {
4755 fcx.ccx.tcx.sess.span_bug(sp, "expected value, found method");
4760 // Instantiates the given path, which must refer to an item with the given
4761 // number of type parameters and type.
4762 pub fn instantiate_path(fcx: &FnCtxt,
4767 node_id: ast::NodeId) {
4768 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4769 path.repr(fcx.tcx()),
4770 def.repr(fcx.tcx()),
4772 polytype.repr(fcx.tcx()));
4774 // We need to extract the type parameters supplied by the user in
4775 // the path `path`. Due to the current setup, this is a bit of a
4776 // tricky-process; the problem is that resolve only tells us the
4777 // end-point of the path resolution, and not the intermediate steps.
4778 // Luckily, we can (at least for now) deduce the intermediate steps
4779 // just from the end-point.
4781 // There are basically three cases to consider:
4783 // 1. Reference to a *type*, such as a struct or enum:
4785 // mod a { struct Foo<T> { ... } }
4787 // Because we don't allow types to be declared within one
4788 // another, a path that leads to a type will always look like
4789 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4790 // that only the final segment can have type parameters, and
4791 // they are located in the TypeSpace.
4793 // *Note:* Generally speaking, references to types don't
4794 // actually pass through this function, but rather the
4795 // `ast_ty_to_ty` function in `astconv`. However, in the case
4796 // of struct patterns (and maybe literals) we do invoke
4797 // `instantiate_path` to get the general type of an instance of
4798 // a struct. (In these cases, there are actually no type
4799 // parameters permitted at present, but perhaps we will allow
4800 // them in the future.)
4802 // 1b. Reference to a enum variant or tuple-like struct:
4804 // struct foo<T>(...)
4805 // enum E<T> { foo(...) }
4807 // In these cases, the parameters are declared in the type
4810 // 2. Reference to a *fn item*:
4814 // In this case, the path will again always have the form
4815 // `a::b::foo::<T>` where only the final segment should have
4816 // type parameters. However, in this case, those parameters are
4817 // declared on a value, and hence are in the `FnSpace`.
4819 // 3. Reference to a *method*:
4821 // impl<A> SomeStruct<A> {
4825 // Here we can have a path like
4826 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4827 // may appear in two places. The penultimate segment,
4828 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4829 // final segment, `foo::<B>` contains parameters in fn space.
4831 // The first step then is to categorize the segments appropriately.
4833 assert!(path.segments.len() >= 1);
4834 let mut segment_spaces;
4836 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4837 def::DefSelfTy(..) |
4838 def::DefStruct(..) |
4839 def::DefVariant(..) |
4840 def::DefTyParamBinder(..) |
4843 def::DefPrimTy(..) |
4844 def::DefTyParam(..) => {
4845 // Everything but the final segment should have no
4846 // parameters at all.
4847 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4848 segment_spaces.push(Some(subst::TypeSpace));
4851 // Case 2. Reference to a top-level value.
4853 def::DefStatic(..) => {
4854 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4855 segment_spaces.push(Some(subst::FnSpace));
4858 // Case 3. Reference to a method.
4859 def::DefStaticMethod(..) => {
4860 assert!(path.segments.len() >= 2);
4861 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4862 segment_spaces.push(Some(subst::TypeSpace));
4863 segment_spaces.push(Some(subst::FnSpace));
4866 // Other cases. Various nonsense that really shouldn't show up
4867 // here. If they do, an error will have been reported
4868 // elsewhere. (I hope)
4870 def::DefForeignMod(..) |
4873 def::DefMethod(..) |
4874 def::DefBinding(..) |
4876 def::DefRegion(..) |
4878 def::DefUpvar(..) => {
4879 segment_spaces = Vec::from_elem(path.segments.len(), None);
4882 assert_eq!(segment_spaces.len(), path.segments.len());
4884 debug!("segment_spaces={}", segment_spaces);
4886 // Next, examine the definition, and determine how many type
4887 // parameters we expect from each space.
4888 let type_defs = &polytype.generics.types;
4889 let region_defs = &polytype.generics.regions;
4891 // Now that we have categorized what space the parameters for each
4892 // segment belong to, let's sort out the parameters that the user
4893 // provided (if any) into their appropriate spaces. We'll also report
4894 // errors if type parameters are provided in an inappropriate place.
4895 let mut substs = Substs::empty();
4896 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4899 report_error_if_segment_contains_type_parameters(fcx, segment);
4903 push_explicit_parameters_from_segment_to_substs(fcx,
4913 // Now we have to compare the types that the user *actually*
4914 // provided against the types that were *expected*. If the user
4915 // did not provide any types, then we want to substitute inference
4916 // variables. If the user provided some types, we may still need
4917 // to add defaults. If the user provided *too many* types, that's
4919 for &space in ParamSpace::all().iter() {
4920 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4921 assert_eq!(substs.types.len(space), type_defs.len(space));
4923 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4924 assert_eq!(substs.regions().len(space), region_defs.len(space));
4927 fcx.add_region_obligations_for_parameters(
4928 span, &substs, &polytype.generics);
4930 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4934 fn report_error_if_segment_contains_type_parameters(
4936 segment: &ast::PathSegment)
4938 for typ in segment.types.iter() {
4939 span_err!(fcx.tcx().sess, typ.span, E0085,
4940 "type parameters may not appear here");
4944 for lifetime in segment.lifetimes.iter() {
4945 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4946 "lifetime parameters may not appear here");
4951 fn push_explicit_parameters_from_segment_to_substs(
4953 space: subst::ParamSpace,
4954 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4955 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4956 segment: &ast::PathSegment,
4957 substs: &mut Substs)
4960 * Finds the parameters that the user provided and adds them
4961 * to `substs`. If too many parameters are provided, then
4962 * reports an error and clears the output vector.
4964 * We clear the output vector because that will cause the
4965 * `adjust_XXX_parameters()` later to use inference
4966 * variables. This seems less likely to lead to derived
4969 * Note that we *do not* check for *too few* parameters here.
4970 * Due to the presence of defaults etc that is more
4971 * complicated. I wanted however to do the reporting of *too
4972 * many* parameters here because we can easily use the precise
4973 * span of the N+1'th parameter.
4977 let type_count = type_defs.len(space);
4978 assert_eq!(substs.types.len(space), 0);
4979 for (i, &typ) in segment.types.iter().enumerate() {
4980 let t = fcx.to_ty(&*typ);
4982 substs.types.push(space, t);
4983 } else if i == type_count {
4984 span_err!(fcx.tcx().sess, typ.span, E0087,
4985 "too many type parameters provided: \
4986 expected at most {} parameter(s), \
4987 found {} parameter(s)",
4988 type_count, segment.types.len());
4989 substs.types.truncate(space, 0);
4995 let region_count = region_defs.len(space);
4996 assert_eq!(substs.regions().len(space), 0);
4997 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4998 let r = ast_region_to_region(fcx.tcx(), lifetime);
4999 if i < region_count {
5000 substs.mut_regions().push(space, r);
5001 } else if i == region_count {
5002 span_err!(fcx.tcx().sess, lifetime.span, E0088,
5003 "too many lifetime parameters provided: \
5004 expected {} parameter(s), found {} parameter(s)",
5006 segment.lifetimes.len());
5007 substs.mut_regions().truncate(space, 0);
5013 fn adjust_type_parameters(
5017 defs: &VecPerParamSpace<ty::TypeParameterDef>,
5018 substs: &mut Substs)
5020 let provided_len = substs.types.len(space);
5021 let desired = defs.get_slice(space);
5022 let required_len = desired.iter()
5023 .take_while(|d| d.default.is_none())
5026 debug!("adjust_type_parameters(space={}, \
5035 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5036 assert!(provided_len <= desired.len());
5038 // Nothing specified at all: supply inference variables for
5040 if provided_len == 0 {
5041 substs.types.replace(space,
5042 fcx.infcx().next_ty_vars(desired.len()));
5046 // Too few parameters specified: report an error and use Err
5048 if provided_len < required_len {
5050 if desired.len() != required_len { "at least " } else { "" };
5051 span_err!(fcx.tcx().sess, span, E0089,
5052 "too few type parameters provided: expected {}{} parameter(s) \
5053 , found {} parameter(s)",
5054 qualifier, required_len, provided_len);
5055 substs.types.replace(space,
5056 Vec::from_elem(desired.len(), ty::mk_err()));
5060 // Otherwise, add in any optional parameters that the user
5061 // omitted. The case of *too many* parameters is handled
5063 // push_explicit_parameters_from_segment_to_substs(). Note
5064 // that the *default* type are expressed in terms of all prior
5065 // parameters, so we have to substitute as we go with the
5066 // partial substitution that we have built up.
5067 for i in range(provided_len, desired.len()) {
5068 let default = desired[i].default.unwrap();
5069 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
5070 substs.types.push(space, default);
5072 assert_eq!(substs.types.len(space), desired.len());
5074 debug!("Final substs: {}", substs.repr(fcx.tcx()));
5077 fn adjust_region_parameters(
5081 defs: &VecPerParamSpace<ty::RegionParameterDef>,
5082 substs: &mut Substs)
5084 let provided_len = substs.mut_regions().len(space);
5085 let desired = defs.get_slice(space);
5087 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
5088 assert!(provided_len <= desired.len());
5090 // If nothing was provided, just use inference variables.
5091 if provided_len == 0 {
5092 substs.mut_regions().replace(
5094 fcx.infcx().region_vars_for_defs(span, desired));
5098 // If just the right number were provided, everybody is happy.
5099 if provided_len == desired.len() {
5103 // Otherwise, too few were provided. Report an error and then
5104 // use inference variables.
5105 span_err!(fcx.tcx().sess, span, E0090,
5106 "too few lifetime parameters provided: expected {} parameter(s), \
5107 found {} parameter(s)",
5108 desired.len(), provided_len);
5110 substs.mut_regions().replace(
5112 fcx.infcx().region_vars_for_defs(span, desired));
5116 // Resolves `typ` by a single level if `typ` is a type variable. If no
5117 // resolution is possible, then an error is reported.
5118 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
5119 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
5120 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
5122 fcx.type_error_message(sp, |_actual| {
5123 "the type of this value must be known in this \
5124 context".to_string()
5126 demand::suptype(fcx, sp, ty::mk_err(), tp);
5132 // Returns the one-level-deep structure of the given type.
5133 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
5135 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
5138 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5139 let typ_s = structurally_resolved_type(fcx, sp, typ);
5140 return ty::type_is_integral(typ_s);
5143 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5144 let typ_s = structurally_resolved_type(fcx, sp, typ);
5145 return ty::type_is_uint(typ_s);
5148 pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5149 let typ_s = structurally_resolved_type(fcx, sp, typ);
5150 return ty::type_is_scalar(typ_s);
5153 pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5154 let typ_s = structurally_resolved_type(fcx, sp, typ);
5155 return ty::type_is_char(typ_s);
5158 pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5159 let typ_s = structurally_resolved_type(fcx, sp, typ);
5160 return ty::type_is_bare_fn(typ_s);
5163 pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5164 let typ_s = structurally_resolved_type(fcx, sp, typ);
5165 return ty::type_is_floating_point(typ_s);
5168 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5169 let typ_s = structurally_resolved_type(fcx, sp, typ);
5170 return ty::type_is_unsafe_ptr(typ_s);
5173 pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5174 let typ_s = structurally_resolved_type(fcx, sp, typ);
5175 return ty::type_is_region_ptr(typ_s);
5178 pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
5179 let typ_s = structurally_resolved_type(fcx, sp, typ);
5180 return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
5183 // Returns true if b contains a break that can exit from b
5184 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
5185 // First: is there an unlabeled break immediately
5187 (loop_query(&*b, |e| {
5189 ast::ExprBreak(_) => true,
5193 // Second: is there a labeled break with label
5194 // <id> nested anywhere inside the loop?
5195 (block_query(b, |e| {
5197 ast::ExprBreak(Some(_)) => {
5198 match cx.def_map.borrow().find(&e.id) {
5199 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
5207 pub fn check_bounds_are_used(ccx: &CrateCtxt,
5209 tps: &OwnedSlice<ast::TyParam>,
5211 debug!("check_bounds_are_used(n_tps={}, ty={})",
5212 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
5214 // make a vector of booleans initially false, set to true when used
5215 if tps.len() == 0u { return; }
5216 let mut tps_used = Vec::from_elem(tps.len(), false);
5218 ty::walk_ty(ty, |t| {
5219 match ty::get(t).sty {
5220 ty::ty_param(ParamTy {idx, ..}) => {
5221 debug!("Found use of ty param num {}", idx);
5222 *tps_used.get_mut(idx) = true;
5228 for (i, b) in tps_used.iter().enumerate() {
5230 span_err!(ccx.tcx.sess, span, E0091,
5231 "type parameter `{}` is unused",
5232 token::get_ident(tps.get(i).ident));
5237 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
5238 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
5239 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
5243 let name = token::get_ident(it.ident);
5244 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
5245 let split : Vec<&str> = name.get().split('_').collect();
5246 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
5248 //We only care about the operation here
5249 match *split.get(1) {
5250 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
5254 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
5256 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5259 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
5260 "min" | "umax" | "umin" => {
5261 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
5265 (0, Vec::new(), ty::mk_nil())
5268 span_err!(tcx.sess, it.span, E0092,
5269 "unrecognized atomic operation function: `{}`", op);
5276 "abort" => (0, Vec::new(), ty::mk_bot()),
5277 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
5279 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
5280 "init" => (1u, Vec::new(), param(ccx, 0u)),
5281 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
5282 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
5283 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
5284 "move_val_init" => {
5287 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
5292 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
5293 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
5296 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5298 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5300 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5302 mutbl: ast::MutImmutable
5304 (1u, Vec::new(), td_ptr)
5307 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
5311 ty::mk_struct(ccx.tcx, did,
5312 subst::Substs::empty())),
5314 tcx.sess.span_fatal(it.span, msg.as_slice());
5319 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
5321 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5323 let region0 = ty::ReLateBound(it.id, ty::BrAnon(0));
5324 let region1 = ty::ReLateBound(it.id, ty::BrAnon(1));
5325 let visitor_object_ty =
5326 match ty::visitor_object_ty(tcx, region0, region1) {
5327 Ok((_, vot)) => vot,
5328 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
5331 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
5333 mutbl: ast::MutImmutable
5335 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
5340 ty::mk_ptr(tcx, ty::mt {
5342 mutbl: ast::MutImmutable
5346 ty::mk_ptr(tcx, ty::mt {
5348 mutbl: ast::MutImmutable
5351 "copy_memory" | "copy_nonoverlapping_memory" |
5352 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
5355 ty::mk_ptr(tcx, ty::mt {
5357 mutbl: ast::MutMutable
5359 ty::mk_ptr(tcx, ty::mt {
5361 mutbl: ast::MutImmutable
5367 "set_memory" | "volatile_set_memory" => {
5370 ty::mk_ptr(tcx, ty::mt {
5372 mutbl: ast::MutMutable
5379 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5380 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5383 vec!( ty::mk_f32(), ty::mk_i32() ),
5388 vec!( ty::mk_f64(), ty::mk_i32() ),
5391 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5392 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5393 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5394 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5397 vec!( ty::mk_f32(), ty::mk_f32() ),
5402 vec!( ty::mk_f64(), ty::mk_f64() ),
5405 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5406 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5407 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5408 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5409 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5410 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5411 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5412 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5413 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5414 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5417 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
5422 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
5425 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5426 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5427 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
5428 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
5429 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5430 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5431 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5432 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5433 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5434 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5435 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5436 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5437 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5438 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5439 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
5440 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
5441 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5442 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5443 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5444 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5445 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5446 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5447 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5448 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5449 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
5450 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5451 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5452 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5453 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
5454 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
5455 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
5458 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
5460 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
5462 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
5463 (0, vec!(ty::mk_i8(), ty::mk_i8()),
5464 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
5466 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
5467 (0, vec!(ty::mk_i16(), ty::mk_i16()),
5468 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
5470 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
5471 (0, vec!(ty::mk_i32(), ty::mk_i32()),
5472 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
5474 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
5475 (0, vec!(ty::mk_i64(), ty::mk_i64()),
5476 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
5478 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
5479 (0, vec!(ty::mk_u8(), ty::mk_u8()),
5480 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
5482 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
5483 (0, vec!(ty::mk_u16(), ty::mk_u16()),
5484 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
5486 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
5487 (0, vec!(ty::mk_u32(), ty::mk_u32()),
5488 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
5490 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
5491 (0, vec!(ty::mk_u64(), ty::mk_u64()),
5492 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
5494 "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
5497 span_err!(tcx.sess, it.span, E0093,
5498 "unrecognized intrinsic function: `{}`", *other);
5503 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
5504 fn_style: ast::UnsafeFn,
5505 abi: abi::RustIntrinsic,
5513 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
5514 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
5515 if i_n_tps != n_tps {
5516 span_err!(tcx.sess, it.span, E0094,
5517 "intrinsic has wrong number of type \
5518 parameters: found {}, expected {}",
5521 require_same_types(tcx,
5528 format!("intrinsic has wrong type: expected `{}`",
5529 ppaux::ty_to_string(ccx.tcx, fty))
5534 impl Repr for RegionObligation {
5535 fn repr(&self, tcx: &ty::ctxt) -> String {
5536 format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
5537 self.sub_region.repr(tcx),
5538 self.sup_type.repr(tcx),
5539 self.origin.repr(tcx))