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;
82 use middle::lang_items::IteratorItem;
83 use middle::pat_util::pat_id_map;
86 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
87 use middle::ty::{FnSig, VariantInfo};
88 use middle::ty::{Polytype};
89 use middle::ty::{ParamTy, Disr, ExprTyProvider};
91 use middle::ty_fold::TypeFolder;
92 use middle::typeck::astconv::AstConv;
93 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
94 use middle::typeck::astconv;
95 use middle::typeck::check::_match::pat_ctxt;
96 use middle::typeck::check::method::{AutoderefReceiver};
97 use middle::typeck::check::method::{AutoderefReceiverFlag};
98 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
99 use middle::typeck::check::method::{DontAutoderefReceiver};
100 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
101 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
102 use middle::typeck::check::regionmanip::relate_free_regions;
103 use middle::typeck::check::vtable::VtableContext;
104 use middle::typeck::CrateCtxt;
105 use middle::typeck::infer::{resolve_type, force_tvar};
106 use middle::typeck::infer;
107 use middle::typeck::rscope::RegionScope;
108 use middle::typeck::{lookup_def_ccx};
109 use middle::typeck::no_params;
110 use middle::typeck::{require_same_types, vtable_map};
111 use middle::typeck::{MethodCall, MethodMap};
112 use middle::typeck::{TypeAndSubsts};
113 use middle::lang_items::TypeIdLangItem;
115 use util::common::{block_query, indenter, loop_query};
117 use util::ppaux::{UserString, Repr};
118 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
120 use std::cell::{Cell, RefCell};
121 use std::collections::HashMap;
122 use std::mem::replace;
126 use syntax::ast::{Provided, Required};
129 use syntax::ast_util::{local_def, PostExpansionMethod};
130 use syntax::ast_util;
132 use syntax::codemap::Span;
134 use syntax::owned_slice::OwnedSlice;
135 use syntax::parse::token;
136 use syntax::print::pprust;
138 use syntax::visit::Visitor;
149 /// Fields that are part of a `FnCtxt` which are inherited by
150 /// closures defined within the function. For example:
153 /// bar(proc() { ... })
156 /// Here, the function `foo()` and the closure passed to
157 /// `bar()` will each have their own `FnCtxt`, but they will
158 /// share the inherited fields.
159 pub struct Inherited<'a> {
160 infcx: infer::InferCtxt<'a>,
161 locals: RefCell<NodeMap<ty::t>>,
162 param_env: ty::ParameterEnvironment,
165 node_types: RefCell<NodeMap<ty::t>>,
166 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
167 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
168 method_map: MethodMap,
169 vtable_map: vtable_map,
170 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
171 unboxed_closure_types: RefCell<DefIdMap<ty::ClosureTy>>,
174 /// When type-checking an expression, we propagate downward
175 /// whatever type hint we are able in the form of an `Expectation`.
177 /// We know nothing about what type this expression should have.
180 /// This expression should have the type given (or some subtype)
181 ExpectHasType(ty::t),
183 /// This expression will be cast to the `ty::t`
184 ExpectCastableToType(ty::t),
188 pub struct FnStyleState {
189 pub def: ast::NodeId,
190 pub fn_style: ast::FnStyle,
195 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
196 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
199 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
200 match self.fn_style {
201 // If this unsafe, then if the outer function was already marked as
202 // unsafe we shouldn't attribute the unsafe'ness to the block. This
203 // way the block can be warned about instead of ignoring this
204 // extraneous block (functions are never warned about).
205 ast::UnsafeFn if self.from_fn => *self,
208 let (fn_style, def) = match blk.rules {
209 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
210 ast::DefaultBlock => (fn_style, self.def),
212 FnStyleState{ def: def,
220 /// Whether `check_binop` is part of an assignment or not.
221 /// Used to know whether we allow user overloads and to print
222 /// better messages on error.
223 #[deriving(PartialEq)]
224 enum IsBinopAssignment{
230 pub struct FnCtxt<'a> {
231 // This flag is set to true if, during the writeback phase, we encounter
232 // a type error in this function.
233 writeback_errors: Cell<bool>,
235 // Number of errors that had been reported when we started
236 // checking this function. On exit, if we find that *more* errors
237 // have been reported, we will skip regionck and other work that
238 // expects the types within the function to be consistent.
239 err_count_on_creation: uint,
242 ps: RefCell<FnStyleState>,
244 // Sometimes we generate region pointers where the precise region
245 // to use is not known. For example, an expression like `&x.f`
246 // where `x` is of type `@T`: in this case, we will be rooting
247 // `x` onto the stack frame, and we could choose to root it until
248 // the end of (almost) any enclosing block or expression. We
249 // want to pick the narrowest block that encompasses all uses.
251 // What we do in such cases is to generate a region variable with
252 // `region_lb` as a lower bound. The regionck pass then adds
253 // other constraints based on how the variable is used and region
254 // inference selects the ultimate value. Finally, borrowck is
255 // charged with guaranteeing that the value whose address was taken
256 // can actually be made to live as long as it needs to live.
257 region_lb: Cell<ast::NodeId>,
259 inh: &'a Inherited<'a>,
261 ccx: &'a CrateCtxt<'a>,
264 impl<'a> Inherited<'a> {
265 fn new(tcx: &'a ty::ctxt,
266 param_env: ty::ParameterEnvironment)
269 infcx: infer::new_infer_ctxt(tcx),
270 locals: RefCell::new(NodeMap::new()),
271 param_env: param_env,
272 node_types: RefCell::new(NodeMap::new()),
273 item_substs: RefCell::new(NodeMap::new()),
274 adjustments: RefCell::new(NodeMap::new()),
275 method_map: RefCell::new(FnvHashMap::new()),
276 vtable_map: RefCell::new(FnvHashMap::new()),
277 upvar_borrow_map: RefCell::new(HashMap::new()),
278 unboxed_closure_types: RefCell::new(DefIdMap::new()),
283 // Used by check_const and check_enum_variants
284 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
285 inh: &'a Inherited<'a>,
287 region_bnd: ast::NodeId)
290 writeback_errors: Cell::new(false),
291 err_count_on_creation: ccx.tcx.sess.err_count(),
293 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
294 region_lb: Cell::new(region_bnd),
300 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
301 // It's kind of a kludge to manufacture a fake function context
302 // and statement context, but we might as well do write the code only once
303 let param_env = ty::ParameterEnvironment {
304 free_substs: subst::Substs::empty(),
305 bounds: subst::VecPerParamSpace::empty()
307 Inherited::new(ccx.tcx, param_env)
310 impl<'a> ExprTyProvider for FnCtxt<'a> {
311 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
315 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
320 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
322 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
323 fn visit_item(&mut self, i: &ast::Item, _: ()) {
324 check_item(self.ccx, i);
325 visit::walk_item(self, i, ());
329 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
331 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
332 fn visit_item(&mut self, i: &ast::Item, _: ()) {
333 check_item_sized(self.ccx, i);
334 visit::walk_item(self, i, ());
338 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
339 let mut visit = CheckItemTypesVisitor { ccx: ccx };
340 visit::walk_crate(&mut visit, krate, ());
342 ccx.tcx.sess.abort_if_errors();
344 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
345 visit::walk_crate(&mut visit, krate, ());
348 fn check_bare_fn(ccx: &CrateCtxt,
353 param_env: ty::ParameterEnvironment) {
354 // Compute the fty from point of view of inside fn
355 // (replace any type-scheme with a type)
356 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
358 match ty::get(fty).sty {
359 ty::ty_bare_fn(ref fn_ty) => {
360 let inh = Inherited::new(ccx.tcx, param_env);
361 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
362 decl, id, body, &inh);
364 vtable::resolve_in_block(&fcx, body);
365 regionck::regionck_fn(&fcx, body);
366 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
368 _ => ccx.tcx.sess.impossible_case(body.span,
369 "check_bare_fn: function type expected")
373 struct GatherLocalsVisitor<'a> {
377 impl<'a> GatherLocalsVisitor<'a> {
378 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
381 // infer the variable's type
382 let var_id = self.fcx.infcx().next_ty_var_id();
383 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
384 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
387 // take type that the user specified
388 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
394 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
395 // Add explicitly-declared locals.
396 fn visit_local(&mut self, local: &ast::Local, _: ()) {
397 let o_ty = match local.ty.node {
398 ast::TyInfer => None,
399 _ => Some(self.fcx.to_ty(&*local.ty))
401 self.assign(local.id, o_ty);
402 debug!("Local variable {} is assigned type {}",
403 self.fcx.pat_to_string(&*local.pat),
404 self.fcx.infcx().ty_to_string(
405 self.fcx.inh.locals.borrow().get_copy(&local.id)));
406 visit::walk_local(self, local, ());
409 // Add pattern bindings.
410 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
412 ast::PatIdent(_, ref path1, _)
413 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
414 self.assign(p.id, None);
415 debug!("Pattern binding {} is assigned to {}",
416 token::get_ident(path1.node),
417 self.fcx.infcx().ty_to_string(
418 self.fcx.inh.locals.borrow().get_copy(&p.id)));
422 visit::walk_pat(self, p, ());
426 fn visit_block(&mut self, b: &ast::Block, _: ()) {
427 // non-obvious: the `blk` variable maps to region lb, so
428 // we have to keep this up-to-date. This
429 // is... unfortunate. It'd be nice to not need this.
430 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
433 // Since an expr occurs as part of the type fixed size arrays we
434 // need to record the type for that node
435 fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
437 ast::TyFixedLengthVec(ref ty, ref count_expr) => {
438 self.visit_ty(&**ty, ());
439 check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
441 _ => visit::walk_ty(self, t, ())
445 // Don't descend into fns and items
446 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
447 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
448 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
452 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
453 fn_style: ast::FnStyle,
458 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
461 * Helper used by check_bare_fn and check_expr_fn. Does the
462 * grungy work of checking a function body and returns the
463 * function context used for that purpose, since in the case of a
464 * fn item there is still a bit more to do.
467 * - inherited: other fields inherited from the enclosing fn (if any)
471 let err_count_on_creation = tcx.sess.err_count();
473 // First, we have to replace any bound regions in the fn type with free ones.
474 // The free region references will be bound the node_id of the body block.
475 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
476 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
479 relate_free_regions(tcx, &fn_sig);
481 let arg_tys = fn_sig.inputs.as_slice();
482 let ret_ty = fn_sig.output;
484 debug!("check_fn(arg_tys={}, ret_ty={})",
488 // Create the function context. This is either derived from scratch or,
489 // in the case of function expressions, based on the outer context.
491 writeback_errors: Cell::new(false),
492 err_count_on_creation: err_count_on_creation,
494 ps: RefCell::new(FnStyleState::function(fn_style, id)),
495 region_lb: Cell::new(body.id),
502 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
503 // Add formal parameters.
504 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
505 // Create type variables for each argument.
506 pat_util::pat_bindings(&tcx.def_map,
508 |_bm, pat_id, _sp, _path| {
509 visit.assign(pat_id, None);
512 // Check the pattern.
515 map: pat_id_map(&tcx.def_map, &*input.pat),
517 _match::check_pat(&pcx, &*input.pat, *arg_ty);
520 visit.visit_block(body, ());
523 check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
525 // We unify the tail expr's type with the
526 // function result type, if there is a tail expr.
528 Some(ref tail_expr) => {
529 // Special case: we print a special error if there appears
530 // to be do-block/for-loop confusion
531 demand::suptype_with_fn(&fcx, tail_expr.span, false,
532 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
534 fcx.report_mismatched_return_types(sp, e, a, s);
540 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
541 fcx.write_ty(input.id, *arg);
547 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
548 assert!(field.id.krate == ast::LOCAL_CRATE);
549 let item = match tcx.map.find(struct_id.node) {
550 Some(ast_map::NodeItem(item)) => item,
551 None => fail!("node not in ast map: {}", struct_id.node),
552 _ => fail!("expected item, found {}", tcx.map.node_to_string(struct_id.node))
556 ast::ItemStruct(struct_def, _) => {
557 match struct_def.fields.iter().find(|f| match f.node.kind {
558 ast::NamedField(ident, _) => ident.name == field.name,
564 .bug(format!("Could not find field {}",
565 token::get_name(field.name)).as_slice())
569 _ => tcx.sess.bug("Field found outside of a struct?"),
573 // Check struct fields are uniquely named wrt parents.
574 fn check_for_field_shadowing(tcx: &ty::ctxt,
576 let struct_fields = tcx.struct_fields.borrow();
577 let fields = struct_fields.get(&id);
579 let superstructs = tcx.superstructs.borrow();
580 let super_struct = superstructs.get(&id);
581 match *super_struct {
583 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
584 for f in fields.iter() {
585 match super_fields.iter().find(|sf| f.name == sf.name) {
586 Some(prev_field) => {
587 span_err!(tcx.sess, span_for_field(tcx, f, id), E0041,
588 "field `{}` hides field declared in super-struct",
589 token::get_name(f.name));
590 span_note!(tcx.sess, span_for_field(tcx, prev_field, parent_id),
591 "previously declared here");
601 fn check_fields_sized(tcx: &ty::ctxt,
602 struct_def: &ast::StructDef) {
603 let len = struct_def.fields.len();
607 for f in struct_def.fields.slice_to(len - 1).iter() {
608 let t = ty::node_id_to_type(tcx, f.node.id);
609 if !ty::type_is_sized(tcx, t) {
611 ast::NamedField(ident, _) => {
612 span_err!(tcx.sess, f.span, E0042,
613 "type `{}` is dynamically sized. \
614 dynamically sized types may only \
615 appear as the type of the final \
617 token::get_ident(ident));
619 ast::UnnamedField(_) => {
620 span_err!(tcx.sess, f.span, E0043,
621 "dynamically sized type in field");
628 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
631 check_representable(tcx, span, id, "struct");
632 check_instantiable(tcx, span, id);
634 // Check there are no overlapping fields in super-structs
635 check_for_field_shadowing(tcx, local_def(id));
637 if ty::lookup_simd(tcx, local_def(id)) {
638 check_simd(tcx, span, id);
642 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
643 debug!("check_item(it.id={}, it.ident={})",
645 ty::item_path_str(ccx.tcx, local_def(it.id)));
646 let _indenter = indenter();
649 ast::ItemEnum(ref enum_definition, _) => {
650 check_enum_variants_sized(ccx,
651 enum_definition.variants.as_slice());
653 ast::ItemStruct(..) => {
654 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
660 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
661 debug!("check_item(it.id={}, it.ident={})",
663 ty::item_path_str(ccx.tcx, local_def(it.id)));
664 let _indenter = indenter();
667 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
668 ast::ItemEnum(ref enum_definition, _) => {
669 check_enum_variants(ccx,
671 enum_definition.variants.as_slice(),
674 ast::ItemFn(ref decl, _, _, _, ref body) => {
675 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
677 let param_env = ty::construct_parameter_environment(ccx.tcx,
681 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
683 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
684 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
686 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
688 check_method_body(ccx, &impl_pty.generics, &**m);
691 match *opt_trait_ref {
692 Some(ref ast_trait_ref) => {
694 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
695 check_impl_methods_against_trait(ccx,
700 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
706 ast::ItemTrait(_, _, _, ref trait_methods) => {
707 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
708 for trait_method in (*trait_methods).iter() {
709 match *trait_method {
711 // Nothing to do, since required methods don't have
715 check_method_body(ccx, &trait_def.generics, &*m);
720 ast::ItemStruct(..) => {
721 check_struct(ccx, it.id, it.span);
723 ast::ItemTy(ref t, ref generics) => {
724 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
725 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
727 ast::ItemForeignMod(ref m) => {
728 if m.abi == abi::RustIntrinsic {
729 for item in m.items.iter() {
730 check_intrinsic_type(ccx, &**item);
733 for item in m.items.iter() {
734 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
735 if !pty.generics.types.is_empty() {
736 span_err!(ccx.tcx.sess, item.span, E0044,
737 "foreign items may not have type parameters");
741 ast::ForeignItemFn(ref fn_decl, _) => {
742 if fn_decl.variadic && m.abi != abi::C {
743 span_err!(ccx.tcx.sess, item.span, E0045,
744 "variadic function must have C calling convention");
752 _ => {/* nothing to do */ }
756 fn check_method_body(ccx: &CrateCtxt,
757 item_generics: &ty::Generics,
758 method: &ast::Method) {
760 * Type checks a method body.
763 * - `item_generics`: generics defined on the impl/trait that contains
765 * - `self_bound`: bound for the `Self` type parameter, if any
766 * - `method`: the method definition
769 debug!("check_method_body(item_generics={}, method.id={})",
770 item_generics.repr(ccx.tcx),
772 let method_def_id = local_def(method.id);
773 let method_ty = ty::method(ccx.tcx, method_def_id);
774 let method_generics = &method_ty.generics;
776 let param_env = ty::construct_parameter_environment(ccx.tcx,
778 method.pe_body().id);
780 let fty = ty::node_id_to_type(ccx.tcx, method.id);
783 &*method.pe_fn_decl(),
790 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
792 ast_trait_ref: &ast::TraitRef,
793 impl_trait_ref: &ty::TraitRef,
794 impl_methods: &[Gc<ast::Method>]) {
795 // Locate trait methods
797 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
799 // Check existing impl methods to see if they are both present in trait
800 // and compatible with trait signature
801 for impl_method in impl_methods.iter() {
802 let impl_method_def_id = local_def(impl_method.id);
803 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
805 // If this is an impl of a trait method, find the corresponding
806 // method definition in the trait.
807 let opt_trait_method_ty =
808 trait_methods.iter().
809 find(|tm| tm.ident.name == impl_method_ty.ident.name);
810 match opt_trait_method_ty {
811 Some(trait_method_ty) => {
812 compare_impl_method(ccx.tcx,
815 impl_method.pe_body().id,
817 &impl_trait_ref.substs);
820 // This is span_bug as it should have already been caught in resolve.
824 "method `{}` is not a member of trait `{}`",
825 token::get_ident(impl_method_ty.ident),
826 pprust::path_to_string(&ast_trait_ref.path)).as_slice());
831 // Check for missing methods from trait
832 let provided_methods = ty::provided_trait_methods(tcx,
833 impl_trait_ref.def_id);
834 let mut missing_methods = Vec::new();
835 for trait_method in trait_methods.iter() {
837 impl_methods.iter().any(
838 |m| m.pe_ident().name == trait_method.ident.name);
840 provided_methods.iter().any(
841 |m| m.ident.name == trait_method.ident.name);
842 if !is_implemented && !is_provided {
843 missing_methods.push(
844 format!("`{}`", token::get_ident(trait_method.ident)));
848 if !missing_methods.is_empty() {
849 span_err!(tcx.sess, impl_span, E0046,
850 "not all trait methods implemented, missing: {}",
851 missing_methods.connect(", "));
856 * Checks that a method from an impl/class conforms to the signature of
857 * the same method as declared in the trait.
861 * - impl_generics: the generics declared on the impl itself (not the method!)
862 * - impl_m: type of the method we are checking
863 * - impl_m_span: span to use for reporting errors
864 * - impl_m_body_id: id of the method body
865 * - trait_m: the method in the trait
866 * - trait_to_impl_substs: the substitutions used on the type of the trait
868 fn compare_impl_method(tcx: &ty::ctxt,
871 impl_m_body_id: ast::NodeId,
872 trait_m: &ty::Method,
873 trait_to_impl_substs: &subst::Substs) {
874 debug!("compare_impl_method()");
875 let infcx = infer::new_infer_ctxt(tcx);
877 // Try to give more informative error messages about self typing
878 // mismatches. Note that any mismatch will also be detected
879 // below, where we construct a canonical function type that
880 // includes the self parameter as a normal parameter. It's just
881 // that the error messages you get out of this code are a bit more
882 // inscrutable, particularly for cases where one method has no
884 match (&trait_m.explicit_self, &impl_m.explicit_self) {
885 (&ty::StaticExplicitSelfCategory,
886 &ty::StaticExplicitSelfCategory) => {}
887 (&ty::StaticExplicitSelfCategory, _) => {
890 format!("method `{}` has a `{}` declaration in the impl, \
891 but not in the trait",
892 token::get_ident(trait_m.ident),
893 ppaux::explicit_self_category_to_str(
894 &impl_m.explicit_self)).as_slice());
897 (_, &ty::StaticExplicitSelfCategory) => {
900 format!("method `{}` has a `{}` declaration in the trait, \
901 but not in the impl",
902 token::get_ident(trait_m.ident),
903 ppaux::explicit_self_category_to_str(
904 &trait_m.explicit_self)).as_slice());
908 // Let the type checker catch other errors below
912 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
913 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
914 if num_impl_m_type_params != num_trait_m_type_params {
915 span_err!(tcx.sess, impl_m_span, E0049,
916 "method `{}` has {} type parameter{} \
917 but its trait declaration has {} type parameter{}",
918 token::get_ident(trait_m.ident),
919 num_impl_m_type_params,
920 if num_impl_m_type_params == 1 {""} else {"s"},
921 num_trait_m_type_params,
922 if num_trait_m_type_params == 1 {""} else {"s"});
926 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
927 span_err!(tcx.sess, impl_m_span, E0050,
928 "method `{}` has {} parameter{} \
929 but the declaration in trait `{}` has {}",
930 token::get_ident(trait_m.ident),
931 impl_m.fty.sig.inputs.len(),
932 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
933 ty::item_path_str(tcx, trait_m.def_id),
934 trait_m.fty.sig.inputs.len());
938 let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
939 .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
941 // This code is best explained by example. Consider a trait:
944 // fn method<'a,M>(t: T, m: &'a M) -> Self;
949 // impl<'i, U> Trait<&'i U> for Foo {
950 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
953 // We wish to decide if those two method types are compatible.
955 // We start out with trait_to_impl_substs, that maps the trait type
956 // parameters to impl type parameters:
958 // trait_to_impl_substs = {T => &'i U, Self => Foo}
960 // We create a mapping `dummy_substs` that maps from the impl type
961 // parameters to fresh types and regions. For type parameters,
962 // this is the identity transform, but we could as well use any
963 // skolemized types. For regions, we convert from bound to free
964 // regions (Note: but only early-bound regions, i.e., those
965 // declared on the impl or used in type parameter bounds).
967 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
969 // Now we can apply skol_substs to the type of the impl method
970 // to yield a new function type in terms of our fresh, skolemized
973 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
975 // We now want to extract and substitute the type of the *trait*
976 // method and compare it. To do so, we must create a compound
977 // substitution by combining trait_to_impl_substs and
978 // impl_to_skol_substs, and also adding a mapping for the method
979 // type parameters. We extend the mapping to also include
980 // the method parameters.
982 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
984 // Applying this to the trait method type yields:
986 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
988 // This type is also the same but the name of the bound region ('a
989 // vs 'b). However, the normal subtyping rules on fn types handle
990 // this kind of equivalency just fine.
992 // Create mapping from impl to skolemized.
994 impl_m.generics.types.map(
995 |d| ty::mk_param_from_def(tcx, d));
997 impl_m.generics.regions.map(
998 |l| ty::free_region_from_def(impl_m_body_id, l));
999 let impl_to_skol_substs =
1000 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1002 // Compute skolemized form of impl method ty.
1003 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1004 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1006 // Compute skolemized form of trait method ty.
1007 let trait_to_skol_substs =
1008 trait_to_impl_substs
1009 .subst(tcx, &impl_to_skol_substs)
1010 .with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
1011 Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
1012 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1013 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1016 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
1017 // Check that the impl does not require any builtin-bounds
1018 // that the trait does not guarantee:
1020 impl_param_def.bounds.builtin_bounds -
1021 trait_param_def.bounds.builtin_bounds;
1022 if !extra_bounds.is_empty() {
1023 span_err!(tcx.sess, impl_m_span, E0051,
1024 "in method `{}`, type parameter {} requires `{}`, \
1025 which is not required by the corresponding type parameter \
1026 in the trait declaration",
1027 token::get_ident(trait_m.ident),
1029 extra_bounds.user_string(tcx));
1033 // Check that the trait bounds of the trait imply the bounds of its
1036 // FIXME(pcwalton): We could be laxer here regarding sub- and super-
1037 // traits, but I doubt that'll be wanted often, so meh.
1038 for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
1039 let impl_trait_bound =
1040 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
1043 for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
1045 trait_bound.subst(tcx, &trait_to_skol_substs);
1046 let infcx = infer::new_infer_ctxt(tcx);
1047 match infer::mk_sub_trait_refs(&infcx,
1049 infer::Misc(impl_m_span),
1051 impl_trait_bound.clone()) {
1061 span_err!(tcx.sess, impl_m_span, E0052,
1062 "in method `{}`, type parameter {} requires bound `{}`, which is not \
1063 required by the corresponding type parameter in the trait declaration",
1064 token::get_ident(trait_m.ident),
1066 ppaux::trait_ref_to_string(tcx, &*impl_trait_bound));
1071 // Check the impl method type IM is a subtype of the trait method
1072 // type TM. To see why this makes sense, think of a vtable. The
1073 // expected type of the function pointers in the vtable is the
1074 // type TM of the trait method. The actual type will be the type
1075 // IM of the impl method. Because we know that IM <: TM, that
1076 // means that anywhere a TM is expected, a IM will do instead. In
1077 // other words, anyone expecting to call a method with the type
1078 // from the trait, can safely call a method with the type from the
1080 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1081 impl_fty, trait_fty) {
1084 span_err!(tcx.sess, impl_m_span, E0053,
1085 "method `{}` has an incompatible type for trait: {}",
1086 token::get_ident(trait_m.ident),
1087 ty::type_err_to_str(tcx, terr));
1088 ty::note_and_explain_type_err(tcx, terr);
1092 // Finally, resolve all regions. This catches wily misuses of lifetime
1094 infcx.resolve_regions_and_report_errors();
1097 fn check_cast(fcx: &FnCtxt,
1102 // Find the type of `e`. Supply hints based on the type we are casting to,
1104 let t_1 = fcx.to_ty(t);
1105 let t_1 = structurally_resolved_type(fcx, span, t_1);
1107 if ty::type_is_scalar(t_1) {
1108 // Supply the type as a hint so as to influence integer
1109 // literals and other things that might care.
1110 check_expr_with_hint(fcx, e, t_1)
1115 let t_e = fcx.expr_ty(e);
1117 debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
1118 debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
1120 if ty::type_is_error(t_e) {
1121 fcx.write_error(id);
1124 if ty::type_is_bot(t_e) {
1129 if ty::type_is_trait(t_1) {
1130 // This will be looked up later on.
1131 fcx.write_ty(id, t_1);
1135 let t_1 = structurally_resolved_type(fcx, span, t_1);
1136 let t_e = structurally_resolved_type(fcx, span, t_e);
1138 if ty::type_is_nil(t_e) {
1139 fcx.type_error_message(span, |actual| {
1140 format!("cast from nil: `{}` as `{}`",
1142 fcx.infcx().ty_to_string(t_1))
1144 } else if ty::type_is_nil(t_1) {
1145 fcx.type_error_message(span, |actual| {
1146 format!("cast to nil: `{}` as `{}`",
1148 fcx.infcx().ty_to_string(t_1))
1152 let t_1_is_scalar = ty::type_is_scalar(t_1);
1153 let t_1_is_char = ty::type_is_char(t_1);
1154 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1155 let t_1_is_float = ty::type_is_floating_point(t_1);
1157 // casts to scalars other than `char` and `bare fn` are trivial
1158 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1159 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1161 fcx.type_error_message(span, |actual| {
1162 format!("illegal cast; cast through an \
1163 integer first: `{}` as `{}`",
1165 fcx.infcx().ty_to_string(t_1))
1168 // casts from C-like enums are allowed
1169 } else if t_1_is_char {
1170 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1171 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1172 fcx.type_error_message(span, |actual| {
1173 format!("only `u8` can be cast as \
1174 `char`, not `{}`", actual)
1177 } else if ty::get(t_1).sty == ty::ty_bool {
1178 span_err!(fcx.tcx().sess, span, E0054,
1179 "cannot cast as `bool`, compare with zero instead");
1180 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1181 fn types_compatible(fcx: &FnCtxt, sp: Span,
1182 t1: ty::t, t2: ty::t) -> bool {
1183 if !ty::type_is_vec(t1) {
1184 // If the type being casted from is not a vector, this special
1185 // case does not apply.
1188 if ty::type_needs_infer(t2) {
1189 // This prevents this special case from going off when casting
1190 // to a type that isn't fully specified; e.g. `as *_`. (Issue
1195 let el = ty::sequence_element_type(fcx.tcx(), t1);
1196 infer::mk_eqty(fcx.infcx(),
1203 // Due to the limitations of LLVM global constants,
1204 // region pointers end up pointing at copies of
1205 // vector elements instead of the original values.
1206 // To allow unsafe pointers to work correctly, we
1207 // need to special-case obtaining an unsafe pointer
1208 // from a region pointer to a vector.
1210 /* this cast is only allowed from &[T] to *T or
1212 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1213 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1214 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1215 if types_compatible(fcx, e.span, mt1, mt2) => {
1216 /* this case is allowed */
1219 demand::coerce(fcx, e.span, t_1, &*e);
1222 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1224 If more type combinations should be supported than are
1225 supported here, then file an enhancement issue and
1226 record the issue number in this comment.
1228 fcx.type_error_message(span, |actual| {
1229 format!("non-scalar cast: `{}` as `{}`",
1231 fcx.infcx().ty_to_string(t_1))
1233 } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float {
1234 fcx.type_error_message(span, |actual| {
1235 format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1238 fcx.infcx().ty_to_string(t_1))
1242 fcx.write_ty(id, t_1);
1245 impl<'a> AstConv for FnCtxt<'a> {
1246 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1248 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1249 ty::lookup_item_type(self.tcx(), id)
1252 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1253 ty::lookup_trait_def(self.tcx(), id)
1256 fn ty_infer(&self, _span: Span) -> ty::t {
1257 self.infcx().next_ty_var()
1261 impl<'a> FnCtxt<'a> {
1262 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1266 pub fn err_count_since_creation(&self) -> uint {
1267 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1270 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1272 infcx: self.infcx(),
1273 param_env: &self.inh.param_env,
1274 unboxed_closure_types: &self.inh.unboxed_closure_types,
1279 impl<'a> RegionScope for infer::InferCtxt<'a> {
1280 fn anon_regions(&self, span: Span, count: uint)
1281 -> Result<Vec<ty::Region> , ()> {
1282 Ok(Vec::from_fn(count, |_| {
1283 self.next_region_var(infer::MiscVariable(span))
1288 impl<'a> FnCtxt<'a> {
1289 pub fn tag(&self) -> String {
1290 format!("{}", self as *const FnCtxt)
1293 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1294 match self.inh.locals.borrow().find(&nid) {
1297 self.tcx().sess.span_bug(
1299 format!("no type for local variable {:?}",
1306 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1307 debug!("write_ty({}, {}) in fcx {}",
1308 node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
1309 self.inh.node_types.borrow_mut().insert(node_id, ty);
1312 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1313 if !substs.substs.is_noop() {
1314 debug!("write_substs({}, {}) in fcx {}",
1316 substs.repr(self.tcx()),
1319 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1323 pub fn write_ty_substs(&self,
1324 node_id: ast::NodeId,
1326 substs: ty::ItemSubsts) {
1327 let ty = ty.subst(self.tcx(), &substs.substs);
1328 self.write_ty(node_id, ty);
1329 self.write_substs(node_id, substs);
1332 pub fn write_autoderef_adjustment(&self,
1333 node_id: ast::NodeId,
1335 if derefs == 0 { return; }
1336 self.write_adjustment(
1338 ty::AutoDerefRef(ty::AutoDerefRef {
1344 pub fn write_adjustment(&self,
1345 node_id: ast::NodeId,
1346 adj: ty::AutoAdjustment) {
1347 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1348 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1351 pub fn write_nil(&self, node_id: ast::NodeId) {
1352 self.write_ty(node_id, ty::mk_nil());
1354 pub fn write_bot(&self, node_id: ast::NodeId) {
1355 self.write_ty(node_id, ty::mk_bot());
1357 pub fn write_error(&self, node_id: ast::NodeId) {
1358 self.write_ty(node_id, ty::mk_err());
1361 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1362 ast_ty_to_ty(self, self.infcx(), ast_t)
1365 pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
1366 pat.repr(self.tcx())
1369 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1370 match self.inh.node_types.borrow().find(&ex.id) {
1373 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1374 self.tag()).as_slice());
1379 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1380 match self.inh.node_types.borrow().find(&id) {
1383 self.tcx().sess.bug(
1384 format!("no type for node {}: {} in fcx {}",
1385 id, self.tcx().map.node_to_string(id),
1386 self.tag()).as_slice());
1391 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1392 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1393 Some(method) => method.substs.clone(),
1395 self.tcx().sess.bug(
1396 format!("no method entry for node {}: {} in fcx {}",
1397 id, self.tcx().map.node_to_string(id),
1398 self.tag()).as_slice());
1403 pub fn opt_node_ty_substs(&self,
1405 f: |&ty::ItemSubsts|) {
1406 match self.inh.item_substs.borrow().find(&id) {
1412 pub fn mk_subty(&self,
1413 a_is_expected: bool,
1414 origin: infer::TypeOrigin,
1417 -> Result<(), ty::type_err> {
1418 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1421 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1422 -> Result<(), ty::type_err> {
1423 infer::can_mk_subty(self.infcx(), sub, sup)
1426 pub fn mk_assignty(&self,
1430 -> Result<(), ty::type_err> {
1431 match infer::mk_coercety(self.infcx(),
1433 infer::ExprAssignable(expr.span),
1437 Err(ref e) => Err((*e)),
1438 Ok(Some(adjustment)) => {
1439 self.write_adjustment(expr.id, adjustment);
1445 pub fn mk_eqty(&self,
1446 a_is_expected: bool,
1447 origin: infer::TypeOrigin,
1450 -> Result<(), ty::type_err> {
1451 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1454 pub fn mk_subr(&self,
1455 a_is_expected: bool,
1456 origin: infer::SubregionOrigin,
1459 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1462 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1463 let old_region_lb = self.region_lb.get();
1464 self.region_lb.set(lb);
1466 self.region_lb.set(old_region_lb);
1470 pub fn type_error_message(&self,
1472 mk_msg: |String| -> String,
1474 err: Option<&ty::type_err>) {
1475 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1478 pub fn report_mismatched_return_types(&self,
1482 err: &ty::type_err) {
1484 if ty::type_is_error(e) || ty::type_is_error(a) {
1487 self.infcx().report_mismatched_types(sp, e, a, err)
1490 pub fn report_mismatched_types(&self,
1494 err: &ty::type_err) {
1495 self.infcx().report_mismatched_types(sp, e, a, err)
1499 pub enum LvaluePreference {
1504 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1505 expr_id: Option<ast::NodeId>,
1506 mut lvalue_pref: LvaluePreference,
1507 should_stop: |ty::t, uint| -> Option<T>)
1508 -> (ty::t, uint, Option<T>) {
1510 * Executes an autoderef loop for the type `t`. At each step, invokes
1511 * `should_stop` to decide whether to terminate the loop. Returns
1512 * the final type and number of derefs that it performed.
1514 * Note: this method does not modify the adjustments table. The caller is
1515 * responsible for inserting an AutoAdjustment record into the `fcx`
1516 * using one of the suitable methods.
1519 let mut t = base_ty;
1520 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1521 let resolved_t = structurally_resolved_type(fcx, sp, t);
1523 match should_stop(resolved_t, autoderefs) {
1524 Some(x) => return (resolved_t, autoderefs, Some(x)),
1528 // Otherwise, deref if type is derefable:
1529 let mt = match ty::deref(resolved_t, false) {
1530 Some(mt) => Some(mt),
1532 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1533 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1539 if mt.mutbl == ast::MutImmutable {
1540 lvalue_pref = NoPreference;
1543 None => return (resolved_t, autoderefs, None)
1547 // We've reached the recursion limit, error gracefully.
1548 span_err!(fcx.tcx().sess, sp, E0055,
1549 "reached the recursion limit while auto-dereferencing {}",
1550 base_ty.repr(fcx.tcx()));
1551 (ty::mk_err(), 0, None)
1554 /// Attempts to resolve a call expression as an overloaded call.
1555 fn try_overloaded_call(fcx: &FnCtxt,
1556 call_expression: &ast::Expr,
1557 callee: Gc<ast::Expr>,
1559 args: &[Gc<ast::Expr>])
1561 // Bail out if the callee is a bare function or a closure. We check those
1563 match *structure_of(fcx, callee.span, callee_type) {
1564 ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
1568 // Try `FnOnce`, then `FnMut`, then `Fn`.
1569 for &(maybe_function_trait, method_name) in [
1570 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1571 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1572 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1574 let function_trait = match maybe_function_trait {
1576 Some(function_trait) => function_trait,
1578 let method_callee = match method::lookup_in_trait(
1580 call_expression.span,
1586 DontAutoderefReceiver,
1587 IgnoreStaticMethods) {
1589 Some(method_callee) => method_callee,
1591 let method_call = MethodCall::expr(call_expression.id);
1592 let output_type = check_method_argument_types(fcx,
1593 call_expression.span,
1599 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1600 write_call(fcx, call_expression, output_type);
1602 if !fcx.tcx().sess.features.overloaded_calls.get() {
1603 span_err!(fcx.tcx().sess, call_expression.span, E0056,
1604 "overloaded calls are experimental");
1605 span_note!(fcx.tcx().sess, call_expression.span,
1606 "add `#[feature(overloaded_calls)]` to \
1607 the crate attributes to enable");
1616 fn try_overloaded_deref(fcx: &FnCtxt,
1618 method_call: Option<MethodCall>,
1619 base_expr: Option<&ast::Expr>,
1621 lvalue_pref: LvaluePreference)
1623 // Try DerefMut first, if preferred.
1624 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1625 (PreferMutLvalue, Some(trait_did)) => {
1626 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1627 token::intern("deref_mut"), trait_did,
1628 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1633 // Otherwise, fall back to Deref.
1634 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1635 (None, Some(trait_did)) => {
1636 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1637 token::intern("deref"), trait_did,
1638 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1640 (method, _) => method
1645 let ref_ty = ty::ty_fn_ret(method.ty);
1647 Some(method_call) => {
1648 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1652 ty::deref(ref_ty, true)
1658 fn try_overloaded_index(fcx: &FnCtxt,
1659 method_call: Option<MethodCall>,
1661 base_expr: Gc<ast::Expr>,
1663 index_expr: Gc<ast::Expr>,
1664 lvalue_pref: LvaluePreference)
1666 // Try `IndexMut` first, if preferred.
1667 let method = match (lvalue_pref, fcx.tcx().lang_items.index_mut_trait()) {
1668 (PreferMutLvalue, Some(trait_did)) => {
1669 method::lookup_in_trait(fcx,
1672 token::intern("index_mut"),
1676 DontAutoderefReceiver,
1677 IgnoreStaticMethods)
1682 // Otherwise, fall back to `Index`.
1683 let method = match (method, fcx.tcx().lang_items.index_trait()) {
1684 (None, Some(trait_did)) => {
1685 method::lookup_in_trait(fcx,
1688 token::intern("index"),
1692 DontAutoderefReceiver,
1693 IgnoreStaticMethods)
1695 (method, _) => method,
1698 // Regardless of whether the lookup succeeds, check the method arguments
1699 // so that we have *some* type for each argument.
1700 let method_type = match method {
1701 Some(ref method) => method.ty,
1702 None => ty::mk_err()
1704 check_method_argument_types(fcx,
1708 [base_expr, index_expr],
1710 DontTupleArguments);
1714 let ref_ty = ty::ty_fn_ret(method.ty);
1716 Some(method_call) => {
1717 fcx.inh.method_map.borrow_mut().insert(method_call,
1722 ty::deref(ref_ty, true)
1728 /// Given the head of a `for` expression, looks up the `next` method in the
1729 /// `Iterator` trait. Fails if the expression does not implement `next`.
1731 /// The return type of this function represents the concrete element type
1732 /// `A` in the type `Iterator<A>` that the method returns.
1733 fn lookup_method_for_for_loop(fcx: &FnCtxt,
1734 iterator_expr: Gc<ast::Expr>,
1735 loop_id: ast::NodeId)
1737 let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
1738 Ok(trait_did) => trait_did,
1739 Err(ref err_string) => {
1740 fcx.tcx().sess.span_err(iterator_expr.span,
1741 err_string.as_slice());
1746 let method = method::lookup_in_trait(fcx,
1748 Some(&*iterator_expr),
1749 token::intern("next"),
1751 fcx.expr_ty(&*iterator_expr),
1753 DontAutoderefReceiver,
1754 IgnoreStaticMethods);
1756 // Regardless of whether the lookup succeeds, check the method arguments
1757 // so that we have *some* type for each argument.
1758 let method_type = match method {
1759 Some(ref method) => method.ty,
1761 fcx.tcx().sess.span_err(iterator_expr.span,
1762 "`for` loop expression does not \
1763 implement the `Iterator` trait");
1767 let return_type = check_method_argument_types(fcx,
1773 DontTupleArguments);
1777 fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
1780 // We expect the return type to be `Option` or something like it.
1781 // Grab the first parameter of its type substitution.
1782 let return_type = structurally_resolved_type(fcx,
1785 match ty::get(return_type).sty {
1786 ty::ty_enum(_, ref substs)
1787 if !substs.types.is_empty_in(subst::TypeSpace) => {
1788 *substs.types.get(subst::TypeSpace, 0)
1791 fcx.tcx().sess.span_err(iterator_expr.span,
1792 "`next` method of the `Iterator` \
1793 trait has an unexpected type");
1798 None => ty::mk_err()
1802 fn check_method_argument_types(fcx: &FnCtxt,
1804 method_fn_ty: ty::t,
1805 callee_expr: &ast::Expr,
1806 args: &[Gc<ast::Expr>],
1807 deref_args: DerefArgs,
1808 tuple_arguments: TupleArgumentsFlag)
1810 // HACK(eddyb) ignore provided self (it has special typeck rules).
1811 let args = if tuple_arguments == DontTupleArguments {
1816 if ty::type_is_error(method_fn_ty) {
1817 let err_inputs = err_args(args.len());
1818 check_argument_types(fcx,
1820 err_inputs.as_slice(),
1828 match ty::get(method_fn_ty).sty {
1829 ty::ty_bare_fn(ref fty) => {
1830 // HACK(eddyb) ignore self in the definition (see above).
1831 check_argument_types(fcx,
1833 fty.sig.inputs.slice_from(1),
1842 fcx.tcx().sess.span_bug(callee_expr.span,
1843 "method without bare fn type");
1849 fn check_argument_types(fcx: &FnCtxt,
1851 fn_inputs: &[ty::t],
1852 callee_expr: &ast::Expr,
1853 args: &[Gc<ast::Expr>],
1854 deref_args: DerefArgs,
1856 tuple_arguments: TupleArgumentsFlag) {
1859 * Generic function that factors out common logic from
1860 * function calls, method calls and overloaded operators.
1863 let tcx = fcx.ccx.tcx;
1865 // Grab the argument types, supplying fresh type variables
1866 // if the wrong number of arguments were supplied
1867 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1873 let expected_arg_count = fn_inputs.len();
1874 let formal_tys = if tuple_arguments == TupleArguments {
1875 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1876 match ty::get(tuple_type).sty {
1877 ty::ty_tup(ref arg_types) => {
1878 if arg_types.len() != args.len() {
1879 span_err!(tcx.sess, sp, E0057,
1880 "this function takes {} parameter{} but {} parameter{} supplied",
1882 if arg_types.len() == 1 {""} else {"s"},
1884 if args.len() == 1 {" was"} else {"s were"});
1885 err_args(args.len())
1887 (*arg_types).clone()
1891 if args.len() != 0 {
1892 span_err!(tcx.sess, sp, E0058,
1893 "this function takes 0 parameters but {} parameter{} supplied",
1895 if args.len() == 1 {" was"} else {"s were"});
1900 span_err!(tcx.sess, sp, E0059,
1901 "cannot use call notation; the first type parameter \
1902 for the function trait is neither a tuple nor unit");
1903 err_args(supplied_arg_count)
1906 } else if expected_arg_count == supplied_arg_count {
1907 fn_inputs.iter().map(|a| *a).collect()
1908 } else if variadic {
1909 if supplied_arg_count >= expected_arg_count {
1910 fn_inputs.iter().map(|a| *a).collect()
1912 span_err!(tcx.sess, sp, E0060,
1913 "this function takes at least {} parameter{} \
1914 but {} parameter{} supplied",
1916 if expected_arg_count == 1 {""} else {"s"},
1918 if supplied_arg_count == 1 {" was"} else {"s were"});
1919 err_args(supplied_arg_count)
1922 span_err!(tcx.sess, sp, E0061,
1923 "this function takes {} parameter{} but {} parameter{} supplied",
1925 if expected_arg_count == 1 {""} else {"s"},
1927 if supplied_arg_count == 1 {" was"} else {"s were"});
1928 err_args(supplied_arg_count)
1931 debug!("check_argument_types: formal_tys={:?}",
1932 formal_tys.iter().map(|t| fcx.infcx().ty_to_string(*t)).collect::<Vec<String>>());
1934 // Check the arguments.
1935 // We do this in a pretty awful way: first we typecheck any arguments
1936 // that are not anonymous functions, then we typecheck the anonymous
1937 // functions. This is so that we have more information about the types
1938 // of arguments when we typecheck the functions. This isn't really the
1939 // right way to do this.
1940 let xs = [false, true];
1941 for check_blocks in xs.iter() {
1942 let check_blocks = *check_blocks;
1943 debug!("check_blocks={}", check_blocks);
1945 // More awful hacks: before we check the blocks, try to do
1946 // an "opportunistic" vtable resolution of any trait
1947 // bounds on the call.
1949 vtable::early_resolve_expr(callee_expr, fcx, true);
1952 // For variadic functions, we don't have a declared type for all of
1953 // the arguments hence we only do our usual type checking with
1954 // the arguments who's types we do know.
1955 let t = if variadic {
1957 } else if tuple_arguments == TupleArguments {
1962 for (i, arg) in args.iter().take(t).enumerate() {
1963 let is_block = match arg.node {
1964 ast::ExprFnBlock(..) |
1966 ast::ExprUnboxedFn(..) => true,
1970 if is_block == check_blocks {
1971 debug!("checking the argument");
1972 let mut formal_ty = *formal_tys.get(i);
1976 match ty::get(formal_ty).sty {
1977 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1980 // So we hit this case when one implements the
1981 // operator traits but leaves an argument as
1982 // just T instead of &T. We'll catch it in the
1983 // mismatch impl/trait method phase no need to
1986 formal_ty = ty::mk_err();
1993 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1999 // We also need to make sure we at least write the ty of the other
2000 // arguments which we skipped above.
2002 for arg in args.iter().skip(expected_arg_count) {
2003 check_expr(fcx, &**arg);
2005 // There are a few types which get autopromoted when passed via varargs
2006 // in C but we just error out instead and require explicit casts.
2007 let arg_ty = structurally_resolved_type(fcx, arg.span,
2008 fcx.expr_ty(&**arg));
2009 match ty::get(arg_ty).sty {
2010 ty::ty_float(ast::TyF32) => {
2011 fcx.type_error_message(arg.span,
2013 format!("can't pass an {} to variadic \
2014 function, cast to c_double", t)
2017 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
2018 fcx.type_error_message(arg.span, |t| {
2019 format!("can't pass {} to variadic \
2020 function, cast to c_int",
2024 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
2025 fcx.type_error_message(arg.span, |t| {
2026 format!("can't pass {} to variadic \
2027 function, cast to c_uint",
2037 fn err_args(len: uint) -> Vec<ty::t> {
2038 Vec::from_fn(len, |_| ty::mk_err())
2041 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
2042 fcx.write_ty(call_expr.id, output);
2045 // AST fragment checking
2046 fn check_lit(fcx: &FnCtxt,
2048 expected: Expectation)
2051 let tcx = fcx.ccx.tcx;
2054 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
2055 ast::LitBinary(..) => {
2056 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
2058 ast::LitByte(_) => ty::mk_u8(),
2059 ast::LitChar(_) => ty::mk_char(),
2060 ast::LitInt(_, t) => ty::mk_mach_int(t),
2061 ast::LitUint(_, t) => ty::mk_mach_uint(t),
2062 ast::LitIntUnsuffixed(_) => {
2063 let opt_ty = expected.map_to_option(fcx, |sty| {
2065 ty::ty_int(i) => Some(ty::mk_mach_int(i)),
2066 ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
2067 ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
2068 ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
2069 ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
2073 opt_ty.unwrap_or_else(
2074 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
2076 ast::LitFloat(_, t) => ty::mk_mach_float(t),
2077 ast::LitFloatUnsuffixed(_) => {
2078 let opt_ty = expected.map_to_option(fcx, |sty| {
2080 ty::ty_float(i) => Some(ty::mk_mach_float(i)),
2084 opt_ty.unwrap_or_else(
2085 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
2087 ast::LitNil => ty::mk_nil(),
2088 ast::LitBool(_) => ty::mk_bool()
2092 pub fn valid_range_bounds(ccx: &CrateCtxt,
2096 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
2097 Some(val) => Some(val <= 0),
2102 pub fn check_expr_has_type(fcx: &FnCtxt,
2105 check_expr_with_unifier(
2106 fcx, expr, ExpectHasType(expected), NoPreference,
2107 || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
2110 fn check_expr_coercable_to_type(fcx: &FnCtxt,
2113 check_expr_with_unifier(
2114 fcx, expr, ExpectHasType(expected), NoPreference,
2115 || demand::coerce(fcx, expr.span, expected, expr));
2118 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
2119 check_expr_with_unifier(
2120 fcx, expr, ExpectHasType(expected), NoPreference,
2124 fn check_expr_with_expectation(fcx: &FnCtxt,
2126 expected: Expectation) {
2127 check_expr_with_unifier(
2128 fcx, expr, expected, NoPreference,
2132 fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
2134 expected: Expectation,
2135 lvalue_pref: LvaluePreference)
2137 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
2140 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
2141 check_expr_with_unifier(fcx, expr, NoExpectation, NoPreference, || ())
2144 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
2145 lvalue_pref: LvaluePreference) {
2146 check_expr_with_unifier(fcx, expr, NoExpectation, lvalue_pref, || ())
2150 // determine the `self` type, using fresh variables for all variables
2151 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
2152 // would return ($0, $1) where $0 and $1 are freshly instantiated type
2154 pub fn impl_self_ty(vcx: &VtableContext,
2155 span: Span, // (potential) receiver for this impl
2158 let tcx = vcx.tcx();
2160 let ity = ty::lookup_item_type(tcx, did);
2161 let (n_tps, rps, raw_ty) =
2162 (ity.generics.types.len(subst::TypeSpace),
2163 ity.generics.regions.get_slice(subst::TypeSpace),
2166 let rps = vcx.infcx.region_vars_for_defs(span, rps);
2167 let tps = vcx.infcx.next_ty_vars(n_tps);
2168 let substs = subst::Substs::new_type(tps, rps);
2169 let substd_ty = raw_ty.subst(tcx, &substs);
2171 TypeAndSubsts { substs: substs, ty: substd_ty }
2174 // Only for fields! Returns <none> for methods>
2175 // Indifferent to privacy flags
2176 pub fn lookup_field_ty(tcx: &ty::ctxt,
2177 class_id: ast::DefId,
2178 items: &[ty::field_ty],
2179 fieldname: ast::Name,
2180 substs: &subst::Substs) -> Option<ty::t> {
2182 let o_field = items.iter().find(|f| f.name == fieldname);
2183 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
2186 // Controls whether the arguments are automatically referenced. This is useful
2187 // for overloaded binary and unary operators.
2188 pub enum DerefArgs {
2193 /// Controls whether the arguments are tupled. This is used for the call
2196 /// Tupling means that all call-side arguments are packed into a tuple and
2197 /// passed as a single parameter. For example, if tupling is enabled, this
2200 /// fn f(x: (int, int))
2202 /// Can be called as:
2209 #[deriving(Clone, Eq, PartialEq)]
2210 enum TupleArgumentsFlag {
2216 /// If an expression has any sub-expressions that result in a type error,
2217 /// inspecting that expression's type with `ty::type_is_error` will return
2218 /// true. Likewise, if an expression is known to diverge, inspecting its
2219 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
2220 /// strict, _|_ can appear in the type of an expression that does not,
2221 /// itself, diverge: for example, fn() -> _|_.)
2222 /// Note that inspecting a type's structure *directly* may expose the fact
2223 /// that there are actually multiple representations for both `ty_err` and
2224 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
2225 fn check_expr_with_unifier(fcx: &FnCtxt,
2227 expected: Expectation,
2228 lvalue_pref: LvaluePreference,
2231 debug!(">> typechecking");
2233 // A generic function for doing all of the checking for call expressions
2234 fn check_call(fcx: &FnCtxt,
2235 call_expr: &ast::Expr,
2237 args: &[Gc<ast::Expr>]) {
2238 // Store the type of `f` as the type of the callee
2239 let fn_ty = fcx.expr_ty(f);
2241 // Extract the function signature from `in_fty`.
2242 let fn_sty = structure_of(fcx, f.span, fn_ty);
2244 // This is the "default" function signature, used in case of error.
2245 // In that case, we check each argument against "error" in order to
2246 // set up all the node type bindings.
2247 let error_fn_sig = FnSig {
2248 binder_id: ast::CRATE_NODE_ID,
2249 inputs: err_args(args.len()),
2250 output: ty::mk_err(),
2254 let fn_sig = match *fn_sty {
2255 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
2256 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
2258 fcx.type_error_message(call_expr.span, |actual| {
2259 format!("expected function but found `{}`", actual)
2265 // Replace any bound regions that appear in the function
2266 // signature with region variables
2267 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
2268 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
2271 // Call the generic checker.
2272 check_argument_types(fcx,
2274 fn_sig.inputs.as_slice(),
2279 DontTupleArguments);
2281 write_call(fcx, call_expr, fn_sig.output);
2284 // Checks a method call.
2285 fn check_method_call(fcx: &FnCtxt,
2287 method_name: ast::SpannedIdent,
2288 args: &[Gc<ast::Expr>],
2289 tps: &[ast::P<ast::Ty>]) {
2290 let rcvr = args[0].clone();
2291 // We can't know if we need &mut self before we look up the method,
2292 // so treat the receiver as mutable just in case - only explicit
2293 // overloaded dereferences care about the distinction.
2294 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
2296 // no need to check for bot/err -- callee does that
2297 let expr_t = structurally_resolved_type(fcx,
2299 fcx.expr_ty(&*rcvr));
2301 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
2302 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
2303 method_name.node.name,
2304 expr_t, tps.as_slice(),
2306 CheckTraitsAndInherentMethods,
2307 AutoderefReceiver, IgnoreStaticMethods) {
2309 let method_ty = method.ty;
2310 let method_call = MethodCall::expr(expr.id);
2311 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2315 debug!("(checking method call) failing expr is {}", expr.id);
2317 fcx.type_error_message(method_name.span,
2319 format!("type `{}` does not implement any \
2320 method in scope named `{}`",
2322 token::get_ident(method_name.node))
2327 // Add error type for the result
2328 fcx.write_error(expr.id);
2330 // Check for potential static matches (missing self parameters)
2334 method_name.node.name,
2338 CheckTraitsAndInherentMethods,
2339 DontAutoderefReceiver,
2340 ReportStaticMethods);
2346 // Call the generic checker.
2347 let ret_ty = check_method_argument_types(fcx,
2353 DontTupleArguments);
2355 write_call(fcx, expr, ret_ty);
2358 // A generic function for checking the then and else in an if
2360 fn check_then_else(fcx: &FnCtxt,
2361 cond_expr: &ast::Expr,
2362 then_blk: &ast::Block,
2363 opt_else_expr: Option<Gc<ast::Expr>>,
2366 expected: Expectation) {
2367 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2369 let branches_ty = match opt_else_expr {
2370 Some(ref else_expr) => {
2371 // Disregard "castable to" expectations because they
2372 // can lead us astray. Consider for example `if cond
2373 // {22} else {c} as u8` -- if we propagate the
2374 // "castable to u8" constraint to 22, it will pick the
2375 // type 22u8, which is overly constrained (c might not
2376 // be a u8). In effect, the problem is that the
2377 // "castable to" expectation is not the tightest thing
2378 // we can say, so we want to drop it in this case.
2379 // The tightest thing we can say is "must unify with
2380 // else branch". Note that in the case of a "has type"
2381 // constraint, this limitation does not hold.
2382 let expected = expected.only_has_type();
2384 check_block_with_expected(fcx, then_blk, expected);
2385 let then_ty = fcx.node_ty(then_blk.id);
2386 check_expr_with_expectation(fcx, &**else_expr, expected);
2387 let else_ty = fcx.expr_ty(&**else_expr);
2388 infer::common_supertype(fcx.infcx(),
2389 infer::IfExpression(sp),
2395 check_block_no_value(fcx, then_blk);
2400 let cond_ty = fcx.expr_ty(cond_expr);
2401 let if_ty = if ty::type_is_error(cond_ty) {
2403 } else if ty::type_is_bot(cond_ty) {
2409 fcx.write_ty(id, if_ty);
2412 fn lookup_op_method(fcx: &FnCtxt,
2416 trait_did: Option<ast::DefId>,
2417 args: &[Gc<ast::Expr>],
2418 autoderef_receiver: AutoderefReceiverFlag,
2419 unbound_method: ||) -> ty::t {
2420 let method = match trait_did {
2421 Some(trait_did) => {
2422 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2423 trait_did, self_t, [], autoderef_receiver,
2424 IgnoreStaticMethods)
2430 let method_ty = method.ty;
2431 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2432 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2433 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2434 check_method_argument_types(fcx,
2444 // Check the args anyway
2445 // so we get all the error messages
2446 let expected_ty = ty::mk_err();
2447 check_method_argument_types(fcx,
2453 DontTupleArguments);
2459 // could be either an expr_binop or an expr_assign_binop
2460 fn check_binop(fcx: &FnCtxt,
2465 is_binop_assignment: IsBinopAssignment) {
2466 let tcx = fcx.ccx.tcx;
2468 let lvalue_pref = match is_binop_assignment {
2469 BinopAssignment => PreferMutLvalue,
2470 SimpleBinop => NoPreference
2472 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2474 // Callee does bot / err checking
2475 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2476 fcx.expr_ty(&*lhs));
2478 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2479 // Shift is a special case: rhs must be uint, no matter what lhs is
2480 check_expr_has_type(fcx, &*rhs, ty::mk_uint());
2481 fcx.write_ty(expr.id, lhs_t);
2485 if ty::is_binopable(tcx, lhs_t, op) {
2486 let tvar = fcx.infcx().next_ty_var();
2487 demand::suptype(fcx, expr.span, tvar, lhs_t);
2488 check_expr_has_type(fcx, &*rhs, tvar);
2490 let result_t = match op {
2491 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2493 if ty::type_is_simd(tcx, lhs_t) {
2494 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2495 fcx.type_error_message(expr.span,
2497 format!("binary comparison \
2498 operation `{}` not \
2499 supported for floating \
2500 point SIMD vector `{}`",
2501 ast_util::binop_to_string(op),
2518 fcx.write_ty(expr.id, result_t);
2522 if op == ast::BiOr || op == ast::BiAnd {
2523 // This is an error; one of the operands must have the wrong
2525 fcx.write_error(expr.id);
2526 fcx.write_error(rhs.id);
2527 fcx.type_error_message(expr.span,
2529 format!("binary operation `{}` cannot be applied \
2531 ast_util::binop_to_string(op),
2538 // Check for overloaded operators if not an assignment.
2539 let result_t = if is_binop_assignment == SimpleBinop {
2540 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2542 fcx.type_error_message(expr.span,
2544 format!("binary assignment \
2546 cannot be applied to \
2548 ast_util::binop_to_string(op),
2553 check_expr(fcx, &*rhs);
2557 fcx.write_ty(expr.id, result_t);
2558 if ty::type_is_error(result_t) {
2559 fcx.write_ty(rhs.id, result_t);
2563 fn check_user_binop(fcx: &FnCtxt,
2565 lhs_expr: Gc<ast::Expr>,
2566 lhs_resolved_t: ty::t,
2568 rhs: Gc<ast::Expr>) -> ty::t {
2569 let tcx = fcx.ccx.tcx;
2570 let lang = &tcx.lang_items;
2571 let (name, trait_did) = match op {
2572 ast::BiAdd => ("add", lang.add_trait()),
2573 ast::BiSub => ("sub", lang.sub_trait()),
2574 ast::BiMul => ("mul", lang.mul_trait()),
2575 ast::BiDiv => ("div", lang.div_trait()),
2576 ast::BiRem => ("rem", lang.rem_trait()),
2577 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2578 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2579 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2580 ast::BiShl => ("shl", lang.shl_trait()),
2581 ast::BiShr => ("shr", lang.shr_trait()),
2582 ast::BiLt => ("lt", lang.ord_trait()),
2583 ast::BiLe => ("le", lang.ord_trait()),
2584 ast::BiGe => ("ge", lang.ord_trait()),
2585 ast::BiGt => ("gt", lang.ord_trait()),
2586 ast::BiEq => ("eq", lang.eq_trait()),
2587 ast::BiNe => ("ne", lang.eq_trait()),
2588 ast::BiAnd | ast::BiOr => {
2589 check_expr(fcx, &*rhs);
2590 return ty::mk_err();
2593 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2594 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2595 fcx.type_error_message(ex.span, |actual| {
2596 format!("binary operation `{}` cannot be applied to type `{}`",
2597 ast_util::binop_to_string(op),
2599 }, lhs_resolved_t, None)
2603 fn check_user_unop(fcx: &FnCtxt,
2606 trait_did: Option<ast::DefId>,
2608 rhs_expr: Gc<ast::Expr>,
2609 rhs_t: ty::t) -> ty::t {
2610 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2611 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2612 fcx.type_error_message(ex.span, |actual| {
2613 format!("cannot apply unary operator `{}` to type `{}`",
2619 fn check_unboxed_closure(fcx: &FnCtxt,
2622 body: ast::P<ast::Block>) {
2623 // The `RegionTraitStore` is a lie, but we ignore it so it doesn't
2626 // FIXME(pcwalton): Refactor this API.
2627 let mut fn_ty = astconv::ty_of_closure(
2632 ty::empty_builtin_bounds(),
2633 ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
2638 let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
2639 local_def(expr.id));
2640 fcx.write_ty(expr.id, closure_type);
2650 // Tuple up the arguments and insert the resulting function type into
2651 // the `unboxed_closure_types` table.
2652 fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
2655 .unboxed_closure_types
2657 .insert(local_def(expr.id), fn_ty);
2660 fn check_expr_fn(fcx: &FnCtxt,
2662 store: ty::TraitStore,
2664 body: ast::P<ast::Block>,
2665 expected: Expectation) {
2666 let tcx = fcx.ccx.tcx;
2668 // Find the expected input/output types (if any). Substitute
2669 // fresh bound regions for any bound regions we find in the
2670 // expected types so as to avoid capture.
2671 let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
2674 expected_bounds) = {
2675 match expected_sty {
2676 Some(ty::ty_closure(ref cenv)) => {
2678 replace_late_bound_regions_in_fn_sig(
2680 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2681 let onceness = match (&store, &cenv.store) {
2682 // As the closure type and onceness go, only three
2683 // combinations are legit:
2687 // If the actual and expected closure type disagree with
2688 // each other, set expected onceness to be always Once or
2689 // Many according to the actual type. Otherwise, it will
2690 // yield either an illegal "many proc" or a less known
2691 // "once closure" in the error message.
2692 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2693 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2695 (&ty::UniqTraitStore, _) => ast::Once,
2696 (&ty::RegionTraitStore(..), _) => ast::Many,
2698 (Some(sig), onceness, cenv.bounds)
2701 // Not an error! Means we're inferring the closure type
2702 let mut bounds = ty::empty_builtin_bounds();
2703 let onceness = match expr.node {
2704 ast::ExprProc(..) => {
2705 bounds.add(ty::BoundSend);
2710 (None, onceness, bounds)
2715 // construct the function type
2716 let fn_ty = astconv::ty_of_closure(fcx,
2725 let fty_sig = fn_ty.sig.clone();
2726 let fty = ty::mk_closure(tcx, fn_ty);
2727 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
2729 fcx.write_ty(expr.id, fty);
2731 // If the closure is a stack closure and hasn't had some non-standard
2732 // style inferred for it, then check it under its parent's style.
2733 // Otherwise, use its own
2734 let (inherited_style, id) = match store {
2735 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2736 fcx.ps.borrow().def),
2737 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2750 // Check field access expressions
2751 fn check_field(fcx: &FnCtxt,
2753 lvalue_pref: LvaluePreference,
2755 field: &ast::SpannedIdent,
2756 tys: &[ast::P<ast::Ty>]) {
2757 let tcx = fcx.ccx.tcx;
2758 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2759 let expr_t = structurally_resolved_type(fcx, expr.span,
2761 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2762 let (_, autoderefs, field_ty) =
2763 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2764 match ty::get(base_t).sty {
2765 ty::ty_struct(base_id, ref substs) => {
2766 debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
2767 let fields = ty::lookup_struct_fields(tcx, base_id);
2768 lookup_field_ty(tcx, base_id, fields.as_slice(),
2769 field.node.name, &(*substs))
2776 fcx.write_ty(expr.id, field_ty);
2777 fcx.write_autoderef_adjustment(base.id, autoderefs);
2783 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2784 match method::lookup(fcx,
2791 CheckTraitsAndInherentMethods,
2793 IgnoreStaticMethods) {
2795 fcx.type_error_message(
2798 format!("attempted to take value of method `{}` on type \
2799 `{}`", token::get_ident(field.node), actual)
2803 tcx.sess.span_note(field.span,
2804 "maybe a missing `()` to call it? If not, try an anonymous function.");
2808 fcx.type_error_message(
2811 format!("attempted access of field `{}` on \
2812 type `{}`, but no field with that \
2814 token::get_ident(field.node),
2821 fcx.write_error(expr.id);
2824 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2827 class_id: ast::DefId,
2828 node_id: ast::NodeId,
2829 substitutions: subst::Substs,
2830 field_types: &[ty::field_ty],
2831 ast_fields: &[ast::Field],
2832 check_completeness: bool) {
2833 let tcx = fcx.ccx.tcx;
2835 let mut class_field_map = HashMap::new();
2836 let mut fields_found = 0;
2837 for field in field_types.iter() {
2838 class_field_map.insert(field.name, (field.id, false));
2841 let mut error_happened = false;
2843 // Typecheck each field.
2844 for field in ast_fields.iter() {
2845 let mut expected_field_type = ty::mk_err();
2847 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2850 fcx.type_error_message(
2853 format!("structure `{}` has no field named `{}`",
2854 actual, token::get_ident(field.ident.node))
2858 error_happened = true;
2860 Some((_, true)) => {
2861 span_err!(fcx.tcx().sess, field.ident.span, E0062,
2862 "field `{}` specified more than once",
2863 token::get_ident(field.ident.node));
2864 error_happened = true;
2866 Some((field_id, false)) => {
2867 expected_field_type =
2868 ty::lookup_field_type(
2869 tcx, class_id, field_id, &substitutions);
2870 class_field_map.insert(
2871 field.ident.node.name, (field_id, true));
2875 // Make sure to give a type to the field even if there's
2876 // an error, so we can continue typechecking
2877 check_expr_coercable_to_type(
2880 expected_field_type);
2884 fcx.write_error(node_id);
2887 if check_completeness && !error_happened {
2888 // Make sure the programmer specified all the fields.
2889 assert!(fields_found <= field_types.len());
2890 if fields_found < field_types.len() {
2891 let mut missing_fields = Vec::new();
2892 for class_field in field_types.iter() {
2893 let name = class_field.name;
2894 let (_, seen) = *class_field_map.get(&name);
2896 missing_fields.push(
2897 format!("`{}`", token::get_name(name).get()))
2901 span_err!(tcx.sess, span, E0063,
2902 "missing field{}: {}",
2903 if missing_fields.len() == 1 {""} else {"s"},
2904 missing_fields.connect(", "));
2908 if !error_happened {
2909 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2910 class_id, substitutions));
2914 fn check_struct_constructor(fcx: &FnCtxt,
2916 span: codemap::Span,
2917 class_id: ast::DefId,
2918 fields: &[ast::Field],
2919 base_expr: Option<Gc<ast::Expr>>) {
2920 let tcx = fcx.ccx.tcx;
2922 // Look up the number of type parameters and the raw type, and
2923 // determine whether the class is region-parameterized.
2924 let item_type = ty::lookup_item_type(tcx, class_id);
2925 let raw_type = item_type.ty;
2927 // Generate the struct type.
2928 let substitutions = fcx.infcx().fresh_substs_for_type(
2929 span, &item_type.generics);
2930 let mut struct_type = raw_type.subst(tcx, &substitutions);
2932 // Look up and check the fields.
2933 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2934 check_struct_or_variant_fields(fcx,
2940 class_fields.as_slice(),
2942 base_expr.is_none());
2943 if ty::type_is_error(fcx.node_ty(id)) {
2944 struct_type = ty::mk_err();
2947 // Check the base expression if necessary.
2950 Some(base_expr) => {
2951 check_expr_has_type(fcx, &*base_expr, struct_type);
2952 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2953 struct_type = ty::mk_bot();
2958 // Write in the resulting type.
2959 fcx.write_ty(id, struct_type);
2962 fn check_struct_enum_variant(fcx: &FnCtxt,
2964 span: codemap::Span,
2965 enum_id: ast::DefId,
2966 variant_id: ast::DefId,
2967 fields: &[ast::Field]) {
2968 let tcx = fcx.ccx.tcx;
2970 // Look up the number of type parameters and the raw type, and
2971 // determine whether the enum is region-parameterized.
2972 let item_type = ty::lookup_item_type(tcx, enum_id);
2973 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2974 let enum_type = item_type.ty.subst(tcx, &substitutions);
2976 // Look up and check the enum variant fields.
2977 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2978 check_struct_or_variant_fields(fcx,
2984 variant_fields.as_slice(),
2987 fcx.write_ty(id, enum_type);
2990 type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2992 fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2993 expected: Expectation)
2994 -> (ExprCheckerWithTy, ty::t) {
2995 let tcx = fcx.ccx.tcx;
2996 let (coerce, t) = match expected {
2997 // If we're given an expected type, we can try to coerce to it
2998 ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2999 // Otherwise we just leave the type to be resolved later
3000 _ => (false, fcx.infcx().next_ty_var())
3003 (check_expr_coercable_to_type, t)
3005 (check_expr_has_type, t)
3009 let tcx = fcx.ccx.tcx;
3012 ast::ExprVstore(ev, vst) => {
3013 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3014 let typ = match ev.node {
3015 ast::ExprVec(ref args) => {
3016 let mutability = match vst {
3017 ast::ExprVstoreMutSlice => ast::MutMutable,
3018 _ => ast::MutImmutable,
3020 let mut any_error = false;
3021 let mut any_bot = false;
3022 for e in args.iter() {
3023 check(fcx, &**e, t);
3024 let arg_t = fcx.expr_ty(&**e);
3025 if ty::type_is_error(arg_t) {
3028 else if ty::type_is_bot(arg_t) {
3037 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
3038 ty::mt{ ty: ty::mk_vec(tcx,
3039 ty::mt {ty: t, mutbl: mutability},
3041 mutbl: mutability })
3044 ast::ExprRepeat(ref element, ref count_expr) => {
3045 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3046 let _ = ty::eval_repeat_count(fcx, &**count_expr);
3047 let mutability = match vst {
3048 ast::ExprVstoreMutSlice => ast::MutMutable,
3049 _ => ast::MutImmutable,
3051 check(fcx, &**element, t);
3052 let arg_t = fcx.expr_ty(&**element);
3053 if ty::type_is_error(arg_t) {
3055 } else if ty::type_is_bot(arg_t) {
3058 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
3059 ty::mt{ ty: ty::mk_vec(tcx,
3060 ty::mt {ty: t, mutbl: mutability},
3065 ast::ExprLit(_) => {
3066 if vst == ast::ExprVstoreSlice {
3067 span_err!(tcx.sess, expr.span, E0064,
3068 "`&\"string\"` has been removed; use `\"string\"` instead");
3070 span_err!(tcx.sess, expr.span, E0065,
3071 "`box \"string\"` has been removed; use \
3072 `\"string\".to_string()` instead");
3076 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
3078 fcx.write_ty(ev.id, typ);
3079 fcx.write_ty(id, typ);
3082 ast::ExprBox(ref place, ref subexpr) => {
3083 check_expr(fcx, &**place);
3084 check_expr(fcx, &**subexpr);
3086 let mut checked = false;
3088 ast::ExprPath(ref path) => {
3089 // FIXME(pcwalton): For now we hardcode the two permissible
3090 // places: the exchange heap and the managed heap.
3091 let definition = lookup_def(fcx, path.span, place.id);
3092 let def_id = definition.def_id();
3093 if tcx.lang_items.exchange_heap() == Some(def_id) {
3094 fcx.write_ty(id, ty::mk_uniq(tcx,
3095 fcx.expr_ty(&**subexpr)));
3097 } else if tcx.lang_items.managed_heap() == Some(def_id) {
3098 fcx.write_ty(id, ty::mk_box(tcx,
3099 fcx.expr_ty(&**subexpr)));
3107 span_err!(tcx.sess, expr.span, E0066,
3108 "only the managed heap and exchange heap are currently supported");
3109 fcx.write_ty(id, ty::mk_err());
3113 ast::ExprLit(lit) => {
3114 let typ = check_lit(fcx, &*lit, expected);
3115 fcx.write_ty(id, typ);
3117 ast::ExprBinary(op, ref lhs, ref rhs) => {
3118 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
3120 let lhs_ty = fcx.expr_ty(&**lhs);
3121 let rhs_ty = fcx.expr_ty(&**rhs);
3122 if ty::type_is_error(lhs_ty) ||
3123 ty::type_is_error(rhs_ty) {
3124 fcx.write_error(id);
3126 else if ty::type_is_bot(lhs_ty) ||
3127 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
3131 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
3132 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
3134 let lhs_t = fcx.expr_ty(&**lhs);
3135 let result_t = fcx.expr_ty(expr);
3136 demand::suptype(fcx, expr.span, result_t, lhs_t);
3138 let tcx = fcx.tcx();
3139 if !ty::expr_is_lval(tcx, &**lhs) {
3140 span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression");
3143 // Overwrite result of check_binop...this preserves existing behavior
3144 // but seems quite dubious with regard to user-defined methods
3145 // and so forth. - Niko
3146 if !ty::type_is_error(result_t)
3147 && !ty::type_is_bot(result_t) {
3148 fcx.write_nil(expr.id);
3151 ast::ExprUnary(unop, ref oprnd) => {
3152 let expected = expected.only_has_type();
3153 let expected_inner = expected.map(fcx, |sty| {
3155 ast::UnBox | ast::UnUniq => match *sty {
3156 ty::ty_box(ty) | ty::ty_uniq(ty) => {
3163 ast::UnNot | ast::UnNeg => {
3171 let lvalue_pref = match unop {
3172 ast::UnDeref => lvalue_pref,
3175 check_expr_with_expectation_and_lvalue_pref(
3176 fcx, &**oprnd, expected_inner, lvalue_pref);
3177 let mut oprnd_t = fcx.expr_ty(&**oprnd);
3178 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
3181 oprnd_t = ty::mk_box(tcx, oprnd_t)
3184 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
3187 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
3188 oprnd_t = match ty::deref(oprnd_t, true) {
3190 None => match try_overloaded_deref(fcx, expr.span,
3191 Some(MethodCall::expr(expr.id)),
3192 Some(&**oprnd), oprnd_t, lvalue_pref) {
3195 let is_newtype = match ty::get(oprnd_t).sty {
3196 ty::ty_struct(did, ref substs) => {
3197 let fields = ty::struct_fields(fcx.tcx(), did, substs);
3199 && fields.get(0).ident ==
3200 token::special_idents::unnamed_field
3205 // This is an obsolete struct deref
3206 span_err!(tcx.sess, expr.span, E0068,
3207 "single-field tuple-structs can \
3208 no longer be dereferenced");
3210 fcx.type_error_message(expr.span, |actual| {
3211 format!("type `{}` cannot be \
3212 dereferenced", actual)
3221 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3223 if !(ty::type_is_integral(oprnd_t) ||
3224 ty::get(oprnd_t).sty == ty::ty_bool) {
3225 oprnd_t = check_user_unop(fcx, "!", "not",
3226 tcx.lang_items.not_trait(),
3227 expr, oprnd.clone(), oprnd_t);
3231 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
3233 if !(ty::type_is_integral(oprnd_t) ||
3234 ty::type_is_fp(oprnd_t)) {
3235 oprnd_t = check_user_unop(fcx, "-", "neg",
3236 tcx.lang_items.neg_trait(),
3237 expr, oprnd.clone(), oprnd_t);
3242 fcx.write_ty(id, oprnd_t);
3244 ast::ExprAddrOf(mutbl, ref oprnd) => {
3245 let expected = expected.only_has_type();
3246 let hint = expected.map(fcx, |sty| {
3247 match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
3248 _ => NoExpectation }
3250 let lvalue_pref = match mutbl {
3251 ast::MutMutable => PreferMutLvalue,
3252 ast::MutImmutable => NoPreference
3254 check_expr_with_expectation_and_lvalue_pref(fcx,
3259 // Note: at this point, we cannot say what the best lifetime
3260 // is to use for resulting pointer. We want to use the
3261 // shortest lifetime possible so as to avoid spurious borrowck
3262 // errors. Moreover, the longest lifetime will depend on the
3263 // precise details of the value whose address is being taken
3264 // (and how long it is valid), which we don't know yet until type
3265 // inference is complete.
3267 // Therefore, here we simply generate a region variable. The
3268 // region inferencer will then select the ultimate value.
3269 // Finally, borrowck is charged with guaranteeing that the
3270 // value whose address was taken can actually be made to live
3271 // as long as it needs to live.
3272 let region = fcx.infcx().next_region_var(
3273 infer::AddrOfRegion(expr.span));
3275 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
3276 let oprnd_t = if ty::type_is_error(tm.ty) {
3278 } else if ty::type_is_bot(tm.ty) {
3282 ty::mk_rptr(tcx, region, tm)
3284 fcx.write_ty(id, oprnd_t);
3286 ast::ExprPath(ref pth) => {
3287 let defn = lookup_def(fcx, pth.span, id);
3288 let pty = polytype_for_def(fcx, expr.span, defn);
3289 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
3291 ast::ExprInlineAsm(ref ia) => {
3292 for &(_, ref input) in ia.inputs.iter() {
3293 check_expr(fcx, &**input);
3295 for &(_, ref out) in ia.outputs.iter() {
3296 check_expr(fcx, &**out);
3300 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
3301 ast::ExprBreak(_) => { fcx.write_bot(id); }
3302 ast::ExprAgain(_) => { fcx.write_bot(id); }
3303 ast::ExprRet(ref expr_opt) => {
3304 let ret_ty = fcx.ret_ty;
3306 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
3307 ret_ty, ty::mk_nil()) {
3308 Ok(_) => { /* fall through */ }
3310 span_err!(tcx.sess, expr.span, E0069,
3311 "`return;` in function returning non-nil");
3315 check_expr_has_type(fcx, &**e, ret_ty);
3320 ast::ExprParen(a) => {
3321 check_expr_with_expectation_and_lvalue_pref(fcx,
3325 fcx.write_ty(id, fcx.expr_ty(&*a));
3327 ast::ExprAssign(ref lhs, ref rhs) => {
3328 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
3330 let tcx = fcx.tcx();
3331 if !ty::expr_is_lval(tcx, &**lhs) {
3332 span_err!(tcx.sess, expr.span, E0070,
3333 "illegal left-hand side expression");
3336 let lhs_ty = fcx.expr_ty(&**lhs);
3337 check_expr_has_type(fcx, &**rhs, lhs_ty);
3338 let rhs_ty = fcx.expr_ty(&**rhs);
3340 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
3341 fcx.write_error(id);
3342 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
3348 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
3349 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
3350 id, expr.span, expected);
3352 ast::ExprWhile(ref cond, ref body) => {
3353 check_expr_has_type(fcx, &**cond, ty::mk_bool());
3354 check_block_no_value(fcx, &**body);
3355 let cond_ty = fcx.expr_ty(&**cond);
3356 let body_ty = fcx.node_ty(body.id);
3357 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
3358 fcx.write_error(id);
3360 else if ty::type_is_bot(cond_ty) {
3367 ast::ExprForLoop(ref pat, ref head, ref block, _) => {
3368 check_expr(fcx, &**head);
3369 let typ = lookup_method_for_for_loop(fcx, *head, expr.id);
3370 vtable::early_resolve_expr(expr, fcx, true);
3372 let pcx = pat_ctxt {
3374 map: pat_id_map(&tcx.def_map, &**pat),
3376 _match::check_pat(&pcx, &**pat, typ);
3378 check_block_no_value(fcx, &**block);
3381 ast::ExprLoop(ref body, _) => {
3382 check_block_no_value(fcx, &**body);
3383 if !may_break(tcx, expr.id, body.clone()) {
3390 ast::ExprMatch(ref discrim, ref arms) => {
3391 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
3393 ast::ExprFnBlock(ref decl, ref body) => {
3394 let region = astconv::opt_ast_region_to_region(fcx,
3400 ty::RegionTraitStore(region, ast::MutMutable),
3405 ast::ExprUnboxedFn(ref decl, ref body) => {
3406 check_unboxed_closure(fcx,
3411 ast::ExprProc(ref decl, ref body) => {
3419 ast::ExprBlock(ref b) => {
3420 check_block_with_expected(fcx, &**b, expected);
3421 fcx.write_ty(id, fcx.node_ty(b.id));
3423 ast::ExprCall(ref f, ref args) => {
3424 // Index expressions need to be handled separately, to inform them
3425 // that they appear in call position.
3426 check_expr(fcx, &**f);
3427 let f_ty = fcx.expr_ty(&**f);
3429 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
3430 check_call(fcx, expr, &**f, args.as_slice());
3431 let (args_bot, args_err) = args.iter().fold((false, false),
3432 |(rest_bot, rest_err), a| {
3433 // is this not working?
3434 let a_ty = fcx.expr_ty(&**a);
3435 (rest_bot || ty::type_is_bot(a_ty),
3436 rest_err || ty::type_is_error(a_ty))});
3437 if ty::type_is_error(f_ty) || args_err {
3438 fcx.write_error(id);
3440 else if ty::type_is_bot(f_ty) || args_bot {
3445 ast::ExprMethodCall(ident, ref tps, ref args) => {
3446 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3447 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
3448 let (args_bot, args_err) = arg_tys.fold((false, false),
3449 |(rest_bot, rest_err), a| {
3450 (rest_bot || ty::type_is_bot(a),
3451 rest_err || ty::type_is_error(a))});
3453 fcx.write_error(id);
3454 } else if args_bot {
3458 ast::ExprCast(ref e, ref t) => {
3460 ast::TyFixedLengthVec(_, ref count_expr) => {
3461 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3465 check_cast(fcx, &**e, &**t, id, expr.span);
3467 ast::ExprVec(ref args) => {
3468 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3469 for e in args.iter() {
3470 check(fcx, &**e, t);
3472 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3474 fcx.write_ty(id, typ);
3476 ast::ExprRepeat(ref element, ref count_expr) => {
3477 check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
3478 let count = ty::eval_repeat_count(fcx, &**count_expr);
3479 let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3480 check(fcx, &**element, t);
3481 let element_ty = fcx.expr_ty(&**element);
3482 if ty::type_is_error(element_ty) {
3483 fcx.write_error(id);
3485 else if ty::type_is_bot(element_ty) {
3489 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3491 fcx.write_ty(id, t);
3494 ast::ExprTup(ref elts) => {
3495 let expected = expected.only_has_type();
3496 let flds = expected.map_to_option(fcx, |sty| {
3498 ty::ty_tup(ref flds) => Some((*flds).clone()),
3502 let mut bot_field = false;
3503 let mut err_field = false;
3505 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3506 let opt_hint = match flds {
3507 Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
3510 check_expr_with_expectation(fcx, &**e, opt_hint);
3511 let t = fcx.expr_ty(&**e);
3512 err_field = err_field || ty::type_is_error(t);
3513 bot_field = bot_field || ty::type_is_bot(t);
3518 } else if err_field {
3519 fcx.write_error(id);
3521 let typ = ty::mk_tup(tcx, elt_ts);
3522 fcx.write_ty(id, typ);
3525 ast::ExprStruct(ref path, ref fields, base_expr) => {
3526 // Resolve the path.
3527 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3528 let struct_id = match def {
3529 Some(def::DefVariant(enum_id, variant_id, _)) => {
3530 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3531 variant_id, fields.as_slice());
3535 // Verify that this was actually a struct.
3536 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3537 match ty::get(typ.ty).sty {
3538 ty::ty_struct(struct_did, _) => {
3539 check_struct_constructor(fcx,
3547 span_err!(tcx.sess, path.span, E0071,
3548 "`{}` does not name a structure",
3549 pprust::path_to_string(path));
3556 tcx.sess.span_bug(path.span,
3557 "structure constructor wasn't resolved")
3561 // Turn the path into a type and verify that that type unifies with
3562 // the resulting structure type. This is needed to handle type
3563 // parameters correctly.
3564 let actual_structure_type = fcx.expr_ty(&*expr);
3565 if !ty::type_is_error(actual_structure_type) {
3566 let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
3570 match fcx.mk_subty(false,
3571 infer::Misc(path.span),
3572 actual_structure_type,
3573 type_and_substs.ty) {
3575 Err(type_error) => {
3576 let type_error_description =
3577 ty::type_err_to_str(tcx, &type_error);
3580 .span_err(path.span,
3581 format!("structure constructor specifies a \
3582 structure of type `{}`, but this \
3583 structure has type `{}`: {}",
3585 .ty_to_string(type_and_substs.ty),
3588 actual_structure_type),
3589 type_error_description).as_slice());
3590 ty::note_and_explain_type_err(tcx, &type_error);
3595 ast::ExprField(ref base, ref field, ref tys) => {
3596 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3598 ast::ExprIndex(ref base, ref idx) => {
3599 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3600 check_expr(fcx, &**idx);
3601 let raw_base_t = fcx.expr_ty(&**base);
3602 let idx_t = fcx.expr_ty(&**idx);
3603 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3604 fcx.write_ty(id, raw_base_t);
3605 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3606 fcx.write_ty(id, idx_t);
3608 let (_, autoderefs, field_ty) =
3609 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3610 lvalue_pref, |base_t, _| ty::index(base_t));
3613 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3614 fcx.write_ty(id, mt.ty);
3615 fcx.write_autoderef_adjustment(base.id, autoderefs);
3618 // This is an overloaded method.
3619 let base_t = structurally_resolved_type(fcx,
3622 let method_call = MethodCall::expr(expr.id);
3623 match try_overloaded_index(fcx,
3630 Some(mt) => fcx.write_ty(id, mt.ty),
3632 fcx.type_error_message(expr.span,
3642 fcx.write_ty(id, ty::mk_err())
3651 debug!("type of expr({}) {} is...", expr.id,
3652 syntax::print::pprust::expr_to_string(expr));
3653 debug!("... {}, expected is {}",
3654 ppaux::ty_to_string(tcx, fcx.expr_ty(expr)),
3655 expected.repr(tcx));
3661 fn only_has_type(self) -> Expectation {
3663 NoExpectation | ExpectCastableToType(..) => NoExpectation,
3664 ExpectHasType(t) => ExpectHasType(t)
3668 // Resolves `expected` by a single level if it is a variable. If
3669 // there is no expected type or resolution is not possible (e.g.,
3670 // no constraints yet present), just returns `None`.
3671 fn resolve(self, fcx: &FnCtxt) -> Expectation {
3676 ExpectCastableToType(t) => {
3677 ExpectCastableToType(
3678 fcx.infcx().resolve_type_vars_if_possible(t))
3680 ExpectHasType(t) => {
3682 fcx.infcx().resolve_type_vars_if_possible(t))
3687 fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
3688 match self.resolve(fcx) {
3689 NoExpectation => NoExpectation,
3690 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3694 fn map_to_option<O>(self,
3696 unpack: |&ty::sty| -> Option<O>)
3699 match self.resolve(fcx) {
3700 NoExpectation => None,
3701 ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
3706 impl Repr for Expectation {
3707 fn repr(&self, tcx: &ty::ctxt) -> String {
3709 NoExpectation => format!("NoExpectation"),
3710 ExpectHasType(t) => format!("ExpectHasType({})",
3712 ExpectCastableToType(t) => format!("ExpectCastableToType({})",
3718 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3719 if !type_is_uint(fcx, sp, t) {
3720 fcx.type_error_message(sp, |actual| {
3721 format!("mismatched types: expected `uint` type but found `{}`",
3727 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3728 if !type_is_integral(fcx, sp, t) {
3729 fcx.type_error_message(sp, |actual| {
3730 format!("mismatched types: expected integral type but found `{}`",
3736 pub fn check_decl_initializer(fcx: &FnCtxt,
3740 let local_ty = fcx.local_ty(init.span, nid);
3741 check_expr_coercable_to_type(fcx, init, local_ty)
3744 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3745 let tcx = fcx.ccx.tcx;
3747 let t = fcx.local_ty(local.span, local.id);
3748 fcx.write_ty(local.id, t);
3752 check_decl_initializer(fcx, local.id, &**init);
3753 let init_ty = fcx.expr_ty(&**init);
3754 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3755 fcx.write_ty(local.id, init_ty);
3761 let pcx = pat_ctxt {
3763 map: pat_id_map(&tcx.def_map, &*local.pat),
3765 _match::check_pat(&pcx, &*local.pat, t);
3766 let pat_ty = fcx.node_ty(local.pat.id);
3767 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3768 fcx.write_ty(local.id, pat_ty);
3772 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3774 let mut saw_bot = false;
3775 let mut saw_err = false;
3777 ast::StmtDecl(decl, id) => {
3780 ast::DeclLocal(ref l) => {
3781 check_decl_local(fcx, &**l);
3782 let l_t = fcx.node_ty(l.id);
3783 saw_bot = saw_bot || ty::type_is_bot(l_t);
3784 saw_err = saw_err || ty::type_is_error(l_t);
3786 ast::DeclItem(_) => {/* ignore for now */ }
3789 ast::StmtExpr(ref expr, id) => {
3791 // Check with expected type of ()
3792 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3793 let expr_ty = fcx.expr_ty(&**expr);
3794 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3795 saw_err = saw_err || ty::type_is_error(expr_ty);
3797 ast::StmtSemi(ref expr, id) => {
3799 check_expr(fcx, &**expr);
3800 let expr_ty = fcx.expr_ty(&**expr);
3801 saw_bot |= ty::type_is_bot(expr_ty);
3802 saw_err |= ty::type_is_error(expr_ty);
3804 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3807 fcx.write_bot(node_id);
3810 fcx.write_error(node_id);
3813 fcx.write_nil(node_id)
3817 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3818 check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
3819 let blkty = fcx.node_ty(blk.id);
3820 if ty::type_is_error(blkty) {
3821 fcx.write_error(blk.id);
3823 else if ty::type_is_bot(blkty) {
3824 fcx.write_bot(blk.id);
3827 let nilty = ty::mk_nil();
3828 demand::suptype(fcx, blk.span, nilty, blkty);
3832 fn check_block_with_expected(fcx: &FnCtxt,
3834 expected: Expectation) {
3836 let mut fcx_ps = fcx.ps.borrow_mut();
3837 let fn_style_state = fcx_ps.recurse(blk);
3838 replace(&mut *fcx_ps, fn_style_state)
3841 fcx.with_region_lb(blk.id, || {
3842 let mut warned = false;
3843 let mut last_was_bot = false;
3844 let mut any_bot = false;
3845 let mut any_err = false;
3846 for s in blk.stmts.iter() {
3847 check_stmt(fcx, &**s);
3848 let s_id = ast_util::stmt_id(&**s);
3849 let s_ty = fcx.node_ty(s_id);
3850 if last_was_bot && !warned && match s.node {
3851 ast::StmtDecl(decl, _) => {
3853 ast::DeclLocal(_) => true,
3857 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3863 .add_lint(lint::builtin::UNREACHABLE_CODE,
3866 "unreachable statement".to_string());
3869 if ty::type_is_bot(s_ty) {
3870 last_was_bot = true;
3872 any_bot = any_bot || ty::type_is_bot(s_ty);
3873 any_err = any_err || ty::type_is_error(s_ty);
3876 None => if any_err {
3877 fcx.write_error(blk.id);
3880 fcx.write_bot(blk.id);
3883 fcx.write_nil(blk.id);
3886 if any_bot && !warned {
3890 .add_lint(lint::builtin::UNREACHABLE_CODE,
3893 "unreachable expression".to_string());
3895 check_expr_with_expectation(fcx, &*e, expected);
3896 let ety = fcx.expr_ty(&*e);
3897 fcx.write_ty(blk.id, ety);
3899 fcx.write_error(blk.id);
3902 fcx.write_bot(blk.id);
3908 *fcx.ps.borrow_mut() = prev;
3911 pub fn check_const(ccx: &CrateCtxt,
3915 let inh = blank_inherited_fields(ccx);
3916 let rty = ty::node_id_to_type(ccx.tcx, id);
3917 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3918 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3919 check_const_with_ty(&fcx, sp, e, declty);
3922 pub fn check_const_with_ty(fcx: &FnCtxt,
3926 // Gather locals in statics (because of block expressions).
3927 // This is technically unnecessary because locals in static items are forbidden,
3928 // but prevents type checking from blowing up before const checking can properly
3930 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3933 let cty = fcx.expr_ty(e);
3934 demand::suptype(fcx, e.span, declty, cty);
3935 regionck::regionck_expr(fcx, e);
3936 writeback::resolve_type_vars_in_expr(fcx, e);
3939 /// Checks whether a type can be represented in memory. In particular, it
3940 /// identifies types that contain themselves without indirection through a
3941 /// pointer, which would mean their size is unbounded. This is different from
3942 /// the question of whether a type can be instantiated. See the definition of
3943 /// `check_instantiable`.
3944 pub fn check_representable(tcx: &ty::ctxt,
3946 item_id: ast::NodeId,
3947 designation: &str) -> bool {
3948 let rty = ty::node_id_to_type(tcx, item_id);
3950 // Check that it is possible to represent this type. This call identifies
3951 // (1) types that contain themselves and (2) types that contain a different
3952 // recursive type. It is only necessary to throw an error on those that
3953 // contain themselves. For case 2, there must be an inner type that will be
3954 // caught by case 1.
3955 match ty::is_type_representable(tcx, sp, rty) {
3956 ty::SelfRecursive => {
3957 span_err!(tcx.sess, sp, E0072,
3958 "illegal recursive {} type; \
3959 wrap the inner value in a box to make it representable",
3963 ty::Representable | ty::ContainsRecursive => (),
3968 /// Checks whether a type can be created without an instance of itself.
3969 /// This is similar but different from the question of whether a type
3970 /// can be represented. For example, the following type:
3972 /// enum foo { None, Some(foo) }
3974 /// is instantiable but is not representable. Similarly, the type
3976 /// enum foo { Some(@foo) }
3978 /// is representable, but not instantiable.
3979 pub fn check_instantiable(tcx: &ty::ctxt,
3981 item_id: ast::NodeId)
3983 let item_ty = ty::node_id_to_type(tcx, item_id);
3984 if !ty::is_instantiable(tcx, item_ty) {
3985 span_err!(tcx.sess, sp, E0073,
3986 "this type cannot be instantiated without an \
3987 instance of itself; consider using `Option<{}>`",
3988 ppaux::ty_to_string(tcx, item_ty));
3995 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3996 let t = ty::node_id_to_type(tcx, id);
3997 if ty::type_needs_subst(t) {
3998 span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
4001 match ty::get(t).sty {
4002 ty::ty_struct(did, ref substs) => {
4003 let fields = ty::lookup_struct_fields(tcx, did);
4004 if fields.is_empty() {
4005 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
4008 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
4009 if !fields.iter().all(
4010 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
4011 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
4014 if !ty::type_is_machine(e) {
4015 span_err!(tcx.sess, sp, E0077,
4016 "SIMD vector element type should be machine type");
4024 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
4025 vs: &[ast::P<ast::Variant>]) {
4026 for &v in vs.iter() {
4028 ast::TupleVariantKind(ref args) if args.len() > 0 => {
4029 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
4030 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
4031 let len = arg_tys.len();
4035 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
4036 // Allow the last field in an enum to be unsized.
4037 // We want to do this so that we can support smart pointers.
4038 // A struct value with an unsized final field is itself
4039 // unsized and we must track this in the type system.
4040 if !ty::type_is_sized(ccx.tcx, *t) {
4041 span_err!(ccx.tcx.sess, args.get(i).ty.span, E0078,
4042 "type `{}` is dynamically sized. dynamically sized types may only \
4043 appear as the final type in a variant",
4044 ppaux::ty_to_string(ccx.tcx, *t));
4048 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
4054 pub fn check_enum_variants(ccx: &CrateCtxt,
4056 vs: &[ast::P<ast::Variant>],
4059 fn disr_in_range(ccx: &CrateCtxt,
4061 disr: ty::Disr) -> bool {
4062 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
4064 ast::TyU8 => disr as u8 as Disr == disr,
4065 ast::TyU16 => disr as u16 as Disr == disr,
4066 ast::TyU32 => disr as u32 as Disr == disr,
4067 ast::TyU64 => disr as u64 as Disr == disr,
4068 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
4071 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
4073 ast::TyI8 => disr as i8 as Disr == disr,
4074 ast::TyI16 => disr as i16 as Disr == disr,
4075 ast::TyI32 => disr as i32 as Disr == disr,
4076 ast::TyI64 => disr as i64 as Disr == disr,
4077 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
4081 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
4082 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
4086 fn do_check(ccx: &CrateCtxt,
4087 vs: &[ast::P<ast::Variant>],
4089 hint: attr::ReprAttr)
4090 -> Vec<Rc<ty::VariantInfo>> {
4092 let rty = ty::node_id_to_type(ccx.tcx, id);
4093 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
4094 let mut disr_vals: Vec<ty::Disr> = Vec::new();
4095 let mut prev_disr_val: Option<ty::Disr> = None;
4097 for &v in vs.iter() {
4099 // If the discriminant value is specified explicitly in the enum check whether the
4100 // initialization expression is valid, otherwise use the last value plus one.
4101 let mut current_disr_val = match prev_disr_val {
4102 Some(prev_disr_val) => prev_disr_val + 1,
4103 None => ty::INITIAL_DISCRIMINANT_VALUE
4106 match v.node.disr_expr {
4108 debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
4110 let inh = blank_inherited_fields(ccx);
4111 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
4112 let declty = match hint {
4113 attr::ReprAny | attr::ReprExtern => ty::mk_int(),
4114 attr::ReprInt(_, attr::SignedInt(ity)) => {
4115 ty::mk_mach_int(ity)
4117 attr::ReprInt(_, attr::UnsignedInt(ity)) => {
4118 ty::mk_mach_uint(ity)
4121 check_const_with_ty(&fcx, e.span, &*e, declty);
4122 // check_expr (from check_const pass) doesn't guarantee
4123 // that the expression is in a form that eval_const_expr can
4124 // handle, so we may still get an internal compiler error
4126 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
4127 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
4128 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
4130 span_err!(ccx.tcx.sess, e.span, E0079,
4131 "expected signed integer constant");
4134 span_err!(ccx.tcx.sess, e.span, E0080,
4135 "expected constant: {}", *err);
4142 // Check for duplicate discriminant values
4143 if disr_vals.contains(¤t_disr_val) {
4144 span_err!(ccx.tcx.sess, v.span, E0081,
4145 "discriminant value already exists");
4147 // Check for unrepresentable discriminant values
4149 attr::ReprAny | attr::ReprExtern => (),
4150 attr::ReprInt(sp, ity) => {
4151 if !disr_in_range(ccx, ity, current_disr_val) {
4152 span_err!(ccx.tcx.sess, v.span, E0082,
4153 "discriminant value outside specified type");
4154 span_note!(ccx.tcx.sess, sp,
4155 "discriminant type specified here");
4159 disr_vals.push(current_disr_val);
4161 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
4163 prev_disr_val = Some(current_disr_val);
4165 variants.push(variant_info);
4171 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
4172 if hint != attr::ReprAny && vs.len() <= 1 {
4174 span_err!(ccx.tcx.sess, sp, E0083,
4175 "unsupported representation for univariant enum");
4177 span_err!(ccx.tcx.sess, sp, E0084,
4178 "unsupported representation for zero-variant enum");
4182 let variants = do_check(ccx, vs, id, hint);
4184 // cache so that ty::enum_variants won't repeat this work
4185 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
4187 check_representable(ccx.tcx, sp, id, "enum");
4189 // Check that it is possible to instantiate this enum:
4191 // This *sounds* like the same that as representable, but it's
4192 // not. See def'n of `check_instantiable()` for details.
4193 check_instantiable(ccx.tcx, sp, id);
4196 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
4197 lookup_def_ccx(fcx.ccx, sp, id)
4200 // Returns the type parameter count and the type for the given definition.
4201 pub fn polytype_for_def(fcx: &FnCtxt,
4206 def::DefArg(nid, _) | def::DefLocal(nid, _) |
4207 def::DefBinding(nid, _) => {
4208 let typ = fcx.local_ty(sp, nid);
4209 return no_params(typ);
4211 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
4212 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
4213 def::DefStruct(id) => {
4214 return ty::lookup_item_type(fcx.ccx.tcx, id);
4216 def::DefUpvar(_, inner, _, _) => {
4217 return polytype_for_def(fcx, sp, *inner);
4222 def::DefTyParam(..)=> {
4223 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
4225 def::DefMod(..) | def::DefForeignMod(..) => {
4226 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
4228 def::DefUse(..) => {
4229 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
4231 def::DefRegion(..) => {
4232 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
4234 def::DefTyParamBinder(..) => {
4235 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
4237 def::DefLabel(..) => {
4238 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
4240 def::DefSelfTy(..) => {
4241 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
4243 def::DefMethod(..) => {
4244 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
4249 // Instantiates the given path, which must refer to an item with the given
4250 // number of type parameters and type.
4251 pub fn instantiate_path(fcx: &FnCtxt,
4256 node_id: ast::NodeId) {
4257 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
4258 path.repr(fcx.tcx()),
4259 def.repr(fcx.tcx()),
4261 polytype.repr(fcx.tcx()));
4263 // We need to extract the type parameters supplied by the user in
4264 // the path `path`. Due to the current setup, this is a bit of a
4265 // tricky-process; the problem is that resolve only tells us the
4266 // end-point of the path resolution, and not the intermediate steps.
4267 // Luckily, we can (at least for now) deduce the intermediate steps
4268 // just from the end-point.
4270 // There are basically three cases to consider:
4272 // 1. Reference to a *type*, such as a struct or enum:
4274 // mod a { struct Foo<T> { ... } }
4276 // Because we don't allow types to be declared within one
4277 // another, a path that leads to a type will always look like
4278 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
4279 // that only the final segment can have type parameters, and
4280 // they are located in the TypeSpace.
4282 // *Note:* Generally speaking, references to types don't
4283 // actually pass through this function, but rather the
4284 // `ast_ty_to_ty` function in `astconv`. However, in the case
4285 // of struct patterns (and maybe literals) we do invoke
4286 // `instantiate_path` to get the general type of an instance of
4287 // a struct. (In these cases, there are actually no type
4288 // parameters permitted at present, but perhaps we will allow
4289 // them in the future.)
4291 // 1b. Reference to a enum variant or tuple-like struct:
4293 // struct foo<T>(...)
4294 // enum E<T> { foo(...) }
4296 // In these cases, the parameters are declared in the type
4299 // 2. Reference to a *fn item*:
4303 // In this case, the path will again always have the form
4304 // `a::b::foo::<T>` where only the final segment should have
4305 // type parameters. However, in this case, those parameters are
4306 // declared on a value, and hence are in the `FnSpace`.
4308 // 3. Reference to a *method*:
4310 // impl<A> SomeStruct<A> {
4314 // Here we can have a path like
4315 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
4316 // may appear in two places. The penultimate segment,
4317 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
4318 // final segment, `foo::<B>` contains parameters in fn space.
4320 // The first step then is to categorize the segments appropriately.
4322 assert!(path.segments.len() >= 1);
4323 let mut segment_spaces;
4325 // Case 1 and 1b. Reference to a *type* or *enum variant*.
4326 def::DefSelfTy(..) |
4327 def::DefStruct(..) |
4328 def::DefVariant(..) |
4329 def::DefTyParamBinder(..) |
4332 def::DefPrimTy(..) |
4333 def::DefTyParam(..) => {
4334 // Everything but the final segment should have no
4335 // parameters at all.
4336 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4337 segment_spaces.push(Some(subst::TypeSpace));
4340 // Case 2. Reference to a top-level value.
4342 def::DefStatic(..) => {
4343 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
4344 segment_spaces.push(Some(subst::FnSpace));
4347 // Case 3. Reference to a method.
4348 def::DefStaticMethod(..) => {
4349 assert!(path.segments.len() >= 2);
4350 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
4351 segment_spaces.push(Some(subst::TypeSpace));
4352 segment_spaces.push(Some(subst::FnSpace));
4355 // Other cases. Various nonsense that really shouldn't show up
4356 // here. If they do, an error will have been reported
4357 // elsewhere. (I hope)
4359 def::DefForeignMod(..) |
4362 def::DefMethod(..) |
4363 def::DefBinding(..) |
4365 def::DefRegion(..) |
4367 def::DefUpvar(..) => {
4368 segment_spaces = Vec::from_elem(path.segments.len(), None);
4371 assert_eq!(segment_spaces.len(), path.segments.len());
4373 debug!("segment_spaces={}", segment_spaces);
4375 // Next, examine the definition, and determine how many type
4376 // parameters we expect from each space.
4377 let type_defs = &polytype.generics.types;
4378 let region_defs = &polytype.generics.regions;
4380 // Now that we have categorized what space the parameters for each
4381 // segment belong to, let's sort out the parameters that the user
4382 // provided (if any) into their appropriate spaces. We'll also report
4383 // errors if type parameters are provided in an inappropriate place.
4384 let mut substs = Substs::empty();
4385 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
4388 report_error_if_segment_contains_type_parameters(fcx, segment);
4392 push_explicit_parameters_from_segment_to_substs(fcx,
4402 // Now we have to compare the types that the user *actually*
4403 // provided against the types that were *expected*. If the user
4404 // did not provide any types, then we want to substitute inference
4405 // variables. If the user provided some types, we may still need
4406 // to add defaults. If the user provided *too many* types, that's
4408 for &space in ParamSpace::all().iter() {
4409 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
4410 assert_eq!(substs.types.len(space), type_defs.len(space));
4412 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
4413 assert_eq!(substs.regions().len(space), region_defs.len(space));
4416 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
4420 fn report_error_if_segment_contains_type_parameters(
4422 segment: &ast::PathSegment)
4424 for typ in segment.types.iter() {
4425 span_err!(fcx.tcx().sess, typ.span, E0085,
4426 "type parameters may not appear here");
4430 for lifetime in segment.lifetimes.iter() {
4431 span_err!(fcx.tcx().sess, lifetime.span, E0086,
4432 "lifetime parameters may not appear here");
4437 fn push_explicit_parameters_from_segment_to_substs(
4439 space: subst::ParamSpace,
4440 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4441 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4442 segment: &ast::PathSegment,
4443 substs: &mut Substs)
4446 * Finds the parameters that the user provided and adds them
4447 * to `substs`. If too many parameters are provided, then
4448 * reports an error and clears the output vector.
4450 * We clear the output vector because that will cause the
4451 * `adjust_XXX_parameters()` later to use inference
4452 * variables. This seems less likely to lead to derived
4455 * Note that we *do not* check for *too few* parameters here.
4456 * Due to the presence of defaults etc that is more
4457 * complicated. I wanted however to do the reporting of *too
4458 * many* parameters here because we can easily use the precise
4459 * span of the N+1'th parameter.
4463 let type_count = type_defs.len(space);
4464 assert_eq!(substs.types.len(space), 0);
4465 for (i, &typ) in segment.types.iter().enumerate() {
4466 let t = fcx.to_ty(&*typ);
4468 substs.types.push(space, t);
4469 } else if i == type_count {
4470 span_err!(fcx.tcx().sess, typ.span, E0087,
4471 "too many type parameters provided: \
4472 expected at most {} parameter(s) \
4473 but found {} parameter(s)",
4474 type_count, segment.types.len());
4475 substs.types.truncate(space, 0);
4481 let region_count = region_defs.len(space);
4482 assert_eq!(substs.regions().len(space), 0);
4483 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4484 let r = ast_region_to_region(fcx.tcx(), lifetime);
4485 if i < region_count {
4486 substs.mut_regions().push(space, r);
4487 } else if i == region_count {
4488 span_err!(fcx.tcx().sess, lifetime.span, E0088,
4489 "too many lifetime parameters provided: \
4490 expected {} parameter(s) but found {} parameter(s)",
4492 segment.lifetimes.len());
4493 substs.mut_regions().truncate(space, 0);
4499 fn adjust_type_parameters(
4503 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4504 substs: &mut Substs)
4506 let provided_len = substs.types.len(space);
4507 let desired = defs.get_slice(space);
4508 let required_len = desired.iter()
4509 .take_while(|d| d.default.is_none())
4512 debug!("adjust_type_parameters(space={}, \
4521 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4522 assert!(provided_len <= desired.len());
4524 // Nothing specified at all: supply inference variables for
4526 if provided_len == 0 {
4527 substs.types.replace(space,
4528 fcx.infcx().next_ty_vars(desired.len()));
4532 // Too few parameters specified: report an error and use Err
4534 if provided_len < required_len {
4536 if desired.len() != required_len { "at least " } else { "" };
4537 span_err!(fcx.tcx().sess, span, E0089,
4538 "too few type parameters provided: expected {}{} parameter(s) \
4539 but found {} parameter(s)",
4540 qualifier, required_len, provided_len);
4541 substs.types.replace(space,
4542 Vec::from_elem(desired.len(), ty::mk_err()));
4546 // Otherwise, add in any optional parameters that the user
4547 // omitted. The case of *too many* parameters is handled
4549 // push_explicit_parameters_from_segment_to_substs(). Note
4550 // that the *default* type are expressed in terms of all prior
4551 // parameters, so we have to substitute as we go with the
4552 // partial substitution that we have built up.
4553 for i in range(provided_len, desired.len()) {
4554 let default = desired[i].default.unwrap();
4555 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4556 substs.types.push(space, default);
4558 assert_eq!(substs.types.len(space), desired.len());
4560 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4563 fn adjust_region_parameters(
4567 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4568 substs: &mut Substs)
4570 let provided_len = substs.mut_regions().len(space);
4571 let desired = defs.get_slice(space);
4573 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4574 assert!(provided_len <= desired.len());
4576 // If nothing was provided, just use inference variables.
4577 if provided_len == 0 {
4578 substs.mut_regions().replace(
4580 fcx.infcx().region_vars_for_defs(span, desired));
4584 // If just the right number were provided, everybody is happy.
4585 if provided_len == desired.len() {
4589 // Otherwise, too few were provided. Report an error and then
4590 // use inference variables.
4591 span_err!(fcx.tcx().sess, span, E0090,
4592 "too few lifetime parameters provided: expected {} parameter(s) \
4593 but found {} parameter(s)",
4594 desired.len(), provided_len);
4596 substs.mut_regions().replace(
4598 fcx.infcx().region_vars_for_defs(span, desired));
4602 // Resolves `typ` by a single level if `typ` is a type variable. If no
4603 // resolution is possible, then an error is reported.
4604 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4605 match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
4606 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4608 fcx.type_error_message(sp, |_actual| {
4609 "the type of this value must be known in this \
4610 context".to_string()
4612 demand::suptype(fcx, sp, ty::mk_err(), tp);
4618 // Returns the one-level-deep structure of the given type.
4619 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4621 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4624 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4625 let typ_s = structurally_resolved_type(fcx, sp, typ);
4626 return ty::type_is_integral(typ_s);
4629 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4630 let typ_s = structurally_resolved_type(fcx, sp, typ);
4631 return ty::type_is_uint(typ_s);
4634 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4637 mk_inner: || -> ty::mt)
4640 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4641 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4643 ast::ExprLit(..) => {
4644 // string literals and *empty slices* live in static memory
4645 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4647 ast::ExprVec(ref elements) if elements.len() == 0 => {
4648 // string literals and *empty slices* live in static memory
4649 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4651 ast::ExprRepeat(..) |
4652 ast::ExprVec(..) => {
4653 // vector literals are temporaries on the stack
4654 match fcx.tcx().region_maps.temporary_scope(e.id) {
4655 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4656 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4660 fcx.ccx.tcx.sess.span_bug(e.span,
4661 "vstore with unexpected \
4669 // Returns true if b contains a break that can exit from b
4670 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4671 // First: is there an unlabeled break immediately
4673 (loop_query(&*b, |e| {
4675 ast::ExprBreak(_) => true,
4679 // Second: is there a labeled break with label
4680 // <id> nested anywhere inside the loop?
4681 (block_query(b, |e| {
4683 ast::ExprBreak(Some(_)) => {
4684 match cx.def_map.borrow().find(&e.id) {
4685 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4693 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4695 tps: &OwnedSlice<ast::TyParam>,
4697 debug!("check_bounds_are_used(n_tps={}, ty={})",
4698 tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
4700 // make a vector of booleans initially false, set to true when used
4701 if tps.len() == 0u { return; }
4702 let mut tps_used = Vec::from_elem(tps.len(), false);
4704 ty::walk_ty(ty, |t| {
4705 match ty::get(t).sty {
4706 ty::ty_param(ParamTy {idx, ..}) => {
4707 debug!("Found use of ty param num {}", idx);
4708 *tps_used.get_mut(idx) = true;
4714 for (i, b) in tps_used.iter().enumerate() {
4716 span_err!(ccx.tcx.sess, span, E0091,
4717 "type parameter `{}` is unused",
4718 token::get_ident(tps.get(i).ident));
4723 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4724 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4725 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4729 let name = token::get_ident(it.ident);
4730 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4731 let split : Vec<&str> = name.get().split('_').collect();
4732 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4734 //We only care about the operation here
4735 match *split.get(1) {
4736 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4740 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4742 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4745 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4746 "min" | "umax" | "umin" => {
4747 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4751 (0, Vec::new(), ty::mk_nil())
4754 span_err!(tcx.sess, it.span, E0092,
4755 "unrecognized atomic operation function: `{}`", op);
4762 "abort" => (0, Vec::new(), ty::mk_bot()),
4763 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4765 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4766 "init" => (1u, Vec::new(), param(ccx, 0u)),
4767 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4768 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4769 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4770 "move_val_init" => {
4773 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4778 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4779 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4782 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4784 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4786 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4788 mutbl: ast::MutImmutable
4790 (1u, Vec::new(), td_ptr)
4793 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4797 ty::mk_struct(ccx.tcx, did,
4798 subst::Substs::empty())),
4800 tcx.sess.span_fatal(it.span, msg.as_slice());
4805 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4807 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4809 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4810 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4811 Ok((_, vot)) => vot,
4812 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4815 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4817 mutbl: ast::MutImmutable
4819 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4824 ty::mk_ptr(tcx, ty::mt {
4826 mutbl: ast::MutImmutable
4830 ty::mk_ptr(tcx, ty::mt {
4832 mutbl: ast::MutImmutable
4835 "copy_memory" | "copy_nonoverlapping_memory" |
4836 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4839 ty::mk_ptr(tcx, ty::mt {
4841 mutbl: ast::MutMutable
4843 ty::mk_ptr(tcx, ty::mt {
4845 mutbl: ast::MutImmutable
4851 "set_memory" | "volatile_set_memory" => {
4854 ty::mk_ptr(tcx, ty::mt {
4856 mutbl: ast::MutMutable
4863 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4864 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4867 vec!( ty::mk_f32(), ty::mk_i32() ),
4872 vec!( ty::mk_f64(), ty::mk_i32() ),
4875 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4876 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4877 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4878 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4881 vec!( ty::mk_f32(), ty::mk_f32() ),
4886 vec!( ty::mk_f64(), ty::mk_f64() ),
4889 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4890 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4891 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4892 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4893 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4894 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4895 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4896 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4897 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4898 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4901 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4906 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4909 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4910 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4911 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4912 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4913 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4914 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4915 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4916 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4917 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4918 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4919 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4920 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4921 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4922 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4923 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4924 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4925 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4926 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4927 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4928 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4929 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4930 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4931 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4932 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4933 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4934 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4935 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4936 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4937 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4938 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4939 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4942 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4944 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4946 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4947 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4948 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4950 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4951 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4952 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4954 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4955 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4956 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4958 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4959 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4960 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4962 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4963 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4964 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4966 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4967 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4968 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4970 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4971 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4972 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4974 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4975 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4976 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4979 span_err!(tcx.sess, it.span, E0093,
4980 "unrecognized intrinsic function: `{}`", *other);
4985 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4986 fn_style: ast::UnsafeFn,
4987 abi: abi::RustIntrinsic,
4995 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4996 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4997 if i_n_tps != n_tps {
4998 span_err!(tcx.sess, it.span, E0094,
4999 "intrinsic has wrong number of type \
5000 parameters: found {}, expected {}",
5003 require_same_types(tcx,
5010 format!("intrinsic has wrong type: expected `{}`",
5011 ppaux::ty_to_string(ccx.tcx, fty))