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::lint::UnreachableCode;
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::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
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::lang_items::TypeIdLangItem;
113 use util::common::{block_query, indenter, loop_query};
115 use util::ppaux::{UserString, Repr};
116 use util::nodemap::{FnvHashMap, NodeMap};
118 use std::cell::{Cell, RefCell};
119 use std::collections::HashMap;
120 use std::mem::replace;
124 use syntax::ast::{Provided, Required};
127 use syntax::ast_util::local_def;
128 use syntax::ast_util;
130 use syntax::codemap::Span;
132 use syntax::owned_slice::OwnedSlice;
133 use syntax::parse::token;
134 use syntax::print::pprust;
136 use syntax::visit::Visitor;
147 /// Fields that are part of a `FnCtxt` which are inherited by
148 /// closures defined within the function. For example:
151 /// bar(proc() { ... })
154 /// Here, the function `foo()` and the closure passed to
155 /// `bar()` will each have their own `FnCtxt`, but they will
156 /// share the inherited fields.
157 pub struct Inherited<'a> {
158 infcx: infer::InferCtxt<'a>,
159 locals: RefCell<NodeMap<ty::t>>,
160 param_env: ty::ParameterEnvironment,
163 node_types: RefCell<NodeMap<ty::t>>,
164 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
165 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
166 method_map: MethodMap,
167 vtable_map: vtable_map,
168 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 pub struct FnStyleState {
173 pub def: ast::NodeId,
174 pub fn_style: ast::FnStyle,
179 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
180 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
183 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
184 match self.fn_style {
185 // If this unsafe, then if the outer function was already marked as
186 // unsafe we shouldn't attribute the unsafe'ness to the block. This
187 // way the block can be warned about instead of ignoring this
188 // extraneous block (functions are never warned about).
189 ast::UnsafeFn if self.from_fn => *self,
192 let (fn_style, def) = match blk.rules {
193 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
194 ast::DefaultBlock => (fn_style, self.def),
196 FnStyleState{ def: def,
204 /// Whether `check_binop` is part of an assignment or not.
205 /// Used to know whether we allow user overloads and to print
206 /// better messages on error.
207 #[deriving(PartialEq)]
208 enum IsBinopAssignment{
214 pub struct FnCtxt<'a> {
215 // This flag is set to true if, during the writeback phase, we encounter
216 // a type error in this function.
217 writeback_errors: Cell<bool>,
219 // Number of errors that had been reported when we started
220 // checking this function. On exit, if we find that *more* errors
221 // have been reported, we will skip regionck and other work that
222 // expects the types within the function to be consistent.
223 err_count_on_creation: uint,
226 ps: RefCell<FnStyleState>,
228 // Sometimes we generate region pointers where the precise region
229 // to use is not known. For example, an expression like `&x.f`
230 // where `x` is of type `@T`: in this case, we will be rooting
231 // `x` onto the stack frame, and we could choose to root it until
232 // the end of (almost) any enclosing block or expression. We
233 // want to pick the narrowest block that encompasses all uses.
235 // What we do in such cases is to generate a region variable with
236 // `region_lb` as a lower bound. The regionck pass then adds
237 // other constraints based on how the variable is used and region
238 // inference selects the ultimate value. Finally, borrowck is
239 // charged with guaranteeing that the value whose address was taken
240 // can actually be made to live as long as it needs to live.
241 region_lb: Cell<ast::NodeId>,
243 inh: &'a Inherited<'a>,
245 ccx: &'a CrateCtxt<'a>,
248 impl<'a> Inherited<'a> {
249 fn new(tcx: &'a ty::ctxt,
250 param_env: ty::ParameterEnvironment)
253 infcx: infer::new_infer_ctxt(tcx),
254 locals: RefCell::new(NodeMap::new()),
255 param_env: param_env,
256 node_types: RefCell::new(NodeMap::new()),
257 item_substs: RefCell::new(NodeMap::new()),
258 adjustments: RefCell::new(NodeMap::new()),
259 method_map: RefCell::new(FnvHashMap::new()),
260 vtable_map: RefCell::new(FnvHashMap::new()),
261 upvar_borrow_map: RefCell::new(HashMap::new()),
266 // Used by check_const and check_enum_variants
267 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
268 inh: &'a Inherited<'a>,
270 region_bnd: ast::NodeId)
273 writeback_errors: Cell::new(false),
274 err_count_on_creation: ccx.tcx.sess.err_count(),
276 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
277 region_lb: Cell::new(region_bnd),
283 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
284 // It's kind of a kludge to manufacture a fake function context
285 // and statement context, but we might as well do write the code only once
286 let param_env = ty::ParameterEnvironment {
287 free_substs: subst::Substs::empty(),
288 bounds: subst::VecPerParamSpace::empty()
290 Inherited::new(ccx.tcx, param_env)
293 impl<'a> ExprTyProvider for FnCtxt<'a> {
294 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
298 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
303 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
305 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
306 fn visit_item(&mut self, i: &ast::Item, _: ()) {
307 check_item(self.ccx, i);
308 visit::walk_item(self, i, ());
312 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
314 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
315 fn visit_item(&mut self, i: &ast::Item, _: ()) {
316 check_item_sized(self.ccx, i);
317 visit::walk_item(self, i, ());
321 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
322 let mut visit = CheckItemTypesVisitor { ccx: ccx };
323 visit::walk_crate(&mut visit, krate, ());
325 ccx.tcx.sess.abort_if_errors();
327 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
328 visit::walk_crate(&mut visit, krate, ());
331 fn check_bare_fn(ccx: &CrateCtxt,
336 param_env: ty::ParameterEnvironment) {
337 // Compute the fty from point of view of inside fn
338 // (replace any type-scheme with a type)
339 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
341 match ty::get(fty).sty {
342 ty::ty_bare_fn(ref fn_ty) => {
343 let inh = Inherited::new(ccx.tcx, param_env);
344 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
345 decl, id, body, &inh);
347 vtable::resolve_in_block(&fcx, body);
348 regionck::regionck_fn(&fcx, body);
349 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
351 _ => ccx.tcx.sess.impossible_case(body.span,
352 "check_bare_fn: function type expected")
356 struct GatherLocalsVisitor<'a> {
360 impl<'a> GatherLocalsVisitor<'a> {
361 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
364 // infer the variable's type
365 let var_id = self.fcx.infcx().next_ty_var_id();
366 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
367 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
370 // take type that the user specified
371 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
377 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
378 // Add explicitly-declared locals.
379 fn visit_local(&mut self, local: &ast::Local, _: ()) {
380 let o_ty = match local.ty.node {
381 ast::TyInfer => None,
382 _ => Some(self.fcx.to_ty(&*local.ty))
384 self.assign(local.id, o_ty);
385 debug!("Local variable {} is assigned type {}",
386 self.fcx.pat_to_str(&*local.pat),
387 self.fcx.infcx().ty_to_str(
388 self.fcx.inh.locals.borrow().get_copy(&local.id)));
389 visit::walk_local(self, local, ());
392 // Add pattern bindings.
393 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
395 ast::PatIdent(_, ref path, _)
396 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
397 self.assign(p.id, None);
398 debug!("Pattern binding {} is assigned to {}",
399 token::get_ident(path.segments.get(0).identifier),
400 self.fcx.infcx().ty_to_str(
401 self.fcx.inh.locals.borrow().get_copy(&p.id)));
405 visit::walk_pat(self, p, ());
409 fn visit_block(&mut self, b: &ast::Block, _: ()) {
410 // non-obvious: the `blk` variable maps to region lb, so
411 // we have to keep this up-to-date. This
412 // is... unfortunate. It'd be nice to not need this.
413 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
416 // Don't descend into fns and items
417 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
418 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
419 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
423 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
424 fn_style: ast::FnStyle,
429 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
432 * Helper used by check_bare_fn and check_expr_fn. Does the
433 * grungy work of checking a function body and returns the
434 * function context used for that purpose, since in the case of a
435 * fn item there is still a bit more to do.
438 * - inherited: other fields inherited from the enclosing fn (if any)
442 let err_count_on_creation = tcx.sess.err_count();
444 // First, we have to replace any bound regions in the fn type with free ones.
445 // The free region references will be bound the node_id of the body block.
446 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
447 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
450 relate_free_regions(tcx, &fn_sig);
452 let arg_tys = fn_sig.inputs.as_slice();
453 let ret_ty = fn_sig.output;
455 debug!("check_fn(arg_tys={}, ret_ty={})",
459 // Create the function context. This is either derived from scratch or,
460 // in the case of function expressions, based on the outer context.
462 writeback_errors: Cell::new(false),
463 err_count_on_creation: err_count_on_creation,
465 ps: RefCell::new(FnStyleState::function(fn_style, id)),
466 region_lb: Cell::new(body.id),
473 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
474 // Add formal parameters.
475 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
476 // Create type variables for each argument.
477 pat_util::pat_bindings(&tcx.def_map,
479 |_bm, pat_id, _sp, _path| {
480 visit.assign(pat_id, None);
483 // Check the pattern.
486 map: pat_id_map(&tcx.def_map, &*input.pat),
488 _match::check_pat(&pcx, &*input.pat, *arg_ty);
491 visit.visit_block(body, ());
494 check_block_with_expected(&fcx, body, Some(ret_ty));
496 // We unify the tail expr's type with the
497 // function result type, if there is a tail expr.
499 Some(ref tail_expr) => {
500 // Special case: we print a special error if there appears
501 // to be do-block/for-loop confusion
502 demand::suptype_with_fn(&fcx, tail_expr.span, false,
503 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
505 fcx.report_mismatched_return_types(sp, e, a, s);
511 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
512 fcx.write_ty(input.id, *arg);
518 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
519 assert!(field.id.krate == ast::LOCAL_CRATE);
520 let item = match tcx.map.find(struct_id.node) {
521 Some(ast_map::NodeItem(item)) => item,
522 None => fail!("node not in ast map: {}", struct_id.node),
523 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
527 ast::ItemStruct(struct_def, _) => {
528 match struct_def.fields.iter().find(|f| match f.node.kind {
529 ast::NamedField(ident, _) => ident.name == field.name,
535 .bug(format!("Could not find field {}",
536 token::get_name(field.name)).as_slice())
540 _ => tcx.sess.bug("Field found outside of a struct?"),
544 // Check struct fields are uniquely named wrt parents.
545 fn check_for_field_shadowing(tcx: &ty::ctxt,
547 let struct_fields = tcx.struct_fields.borrow();
548 let fields = struct_fields.get(&id);
550 let superstructs = tcx.superstructs.borrow();
551 let super_struct = superstructs.get(&id);
552 match *super_struct {
554 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
555 for f in fields.iter() {
556 match super_fields.iter().find(|sf| f.name == sf.name) {
557 Some(prev_field) => {
558 tcx.sess.span_err(span_for_field(tcx, f, id),
559 format!("field `{}` hides field declared in \
561 token::get_name(f.name)).as_slice());
562 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
563 "previously declared here");
573 fn check_fields_sized(tcx: &ty::ctxt,
574 struct_def: &ast::StructDef) {
575 let len = struct_def.fields.len();
579 for f in struct_def.fields.slice_to(len - 1).iter() {
580 let t = ty::node_id_to_type(tcx, f.node.id);
581 if !ty::type_is_sized(tcx, t) {
583 ast::NamedField(ident, _) => {
586 format!("type `{}` is dynamically sized. \
587 dynamically sized types may only \
588 appear as the type of the final \
590 token::get_ident(ident)).as_slice());
592 ast::UnnamedField(_) => {
593 tcx.sess.span_err(f.span, "dynamically sized type in field");
600 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
603 check_representable(tcx, span, id, "struct");
604 check_instantiable(tcx, span, id);
606 // Check there are no overlapping fields in super-structs
607 check_for_field_shadowing(tcx, local_def(id));
609 if ty::lookup_simd(tcx, local_def(id)) {
610 check_simd(tcx, span, id);
614 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
615 debug!("check_item(it.id={}, it.ident={})",
617 ty::item_path_str(ccx.tcx, local_def(it.id)));
618 let _indenter = indenter();
621 ast::ItemEnum(ref enum_definition, _) => {
622 check_enum_variants_sized(ccx,
623 enum_definition.variants.as_slice());
625 ast::ItemStruct(..) => {
626 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
632 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
633 debug!("check_item(it.id={}, it.ident={})",
635 ty::item_path_str(ccx.tcx, local_def(it.id)));
636 let _indenter = indenter();
639 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
640 ast::ItemEnum(ref enum_definition, _) => {
641 check_enum_variants(ccx,
643 enum_definition.variants.as_slice(),
646 ast::ItemFn(ref decl, _, _, _, ref body) => {
647 let fn_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
649 let param_env = ty::construct_parameter_environment(ccx.tcx,
653 check_bare_fn(ccx, &**decl, &**body, it.id, fn_tpt.ty, param_env);
655 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
656 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
658 let impl_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
660 check_method_body(ccx, &impl_tpt.generics, &**m);
663 match *opt_trait_ref {
664 Some(ref ast_trait_ref) => {
666 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
667 check_impl_methods_against_trait(ccx,
672 vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, &*impl_trait_ref);
678 ast::ItemTrait(_, _, _, ref trait_methods) => {
679 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
680 for trait_method in (*trait_methods).iter() {
681 match *trait_method {
683 // Nothing to do, since required methods don't have
687 check_method_body(ccx, &trait_def.generics, &*m);
692 ast::ItemStruct(..) => {
693 check_struct(ccx, it.id, it.span);
695 ast::ItemTy(ref t, ref generics) => {
696 let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
697 check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty);
699 ast::ItemForeignMod(ref m) => {
700 if m.abi == abi::RustIntrinsic {
701 for item in m.items.iter() {
702 check_intrinsic_type(ccx, &**item);
705 for item in m.items.iter() {
706 let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
707 if !tpt.generics.types.is_empty() {
708 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
712 ast::ForeignItemFn(ref fn_decl, _) => {
713 if fn_decl.variadic && m.abi != abi::C {
714 ccx.tcx.sess.span_err(
715 item.span, "variadic function must have C calling convention");
723 _ => {/* nothing to do */ }
727 fn check_method_body(ccx: &CrateCtxt,
728 item_generics: &ty::Generics,
729 method: &ast::Method) {
731 * Type checks a method body.
734 * - `item_generics`: generics defined on the impl/trait that contains
736 * - `self_bound`: bound for the `Self` type parameter, if any
737 * - `method`: the method definition
740 debug!("check_method_body(item_generics={}, method.id={})",
741 item_generics.repr(ccx.tcx),
743 let method_def_id = local_def(method.id);
744 let method_ty = ty::method(ccx.tcx, method_def_id);
745 let method_generics = &method_ty.generics;
747 let param_env = ty::construct_parameter_environment(ccx.tcx,
751 let fty = ty::node_id_to_type(ccx.tcx, method.id);
753 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
756 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
758 ast_trait_ref: &ast::TraitRef,
759 impl_trait_ref: &ty::TraitRef,
760 impl_methods: &[Gc<ast::Method>]) {
761 // Locate trait methods
763 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
765 // Check existing impl methods to see if they are both present in trait
766 // and compatible with trait signature
767 for impl_method in impl_methods.iter() {
768 let impl_method_def_id = local_def(impl_method.id);
769 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
771 // If this is an impl of a trait method, find the corresponding
772 // method definition in the trait.
773 let opt_trait_method_ty =
774 trait_methods.iter().
775 find(|tm| tm.ident.name == impl_method_ty.ident.name);
776 match opt_trait_method_ty {
777 Some(trait_method_ty) => {
778 compare_impl_method(ccx.tcx,
783 &impl_trait_ref.substs);
789 "method `{}` is not a member of trait `{}`",
790 token::get_ident(impl_method_ty.ident),
791 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
796 // Check for missing methods from trait
797 let provided_methods = ty::provided_trait_methods(tcx,
798 impl_trait_ref.def_id);
799 let mut missing_methods = Vec::new();
800 for trait_method in trait_methods.iter() {
802 impl_methods.iter().any(
803 |m| m.ident.name == trait_method.ident.name);
805 provided_methods.iter().any(
806 |m| m.ident.name == trait_method.ident.name);
807 if !is_implemented && !is_provided {
808 missing_methods.push(
809 format!("`{}`", token::get_ident(trait_method.ident)));
813 if !missing_methods.is_empty() {
816 format!("not all trait methods implemented, missing: {}",
817 missing_methods.connect(", ")).as_slice());
822 * Checks that a method from an impl/class conforms to the signature of
823 * the same method as declared in the trait.
827 * - impl_generics: the generics declared on the impl itself (not the method!)
828 * - impl_m: type of the method we are checking
829 * - impl_m_span: span to use for reporting errors
830 * - impl_m_body_id: id of the method body
831 * - trait_m: the method in the trait
832 * - trait_to_impl_substs: the substitutions used on the type of the trait
834 fn compare_impl_method(tcx: &ty::ctxt,
837 impl_m_body_id: ast::NodeId,
838 trait_m: &ty::Method,
839 trait_to_impl_substs: &subst::Substs) {
840 debug!("compare_impl_method()");
841 let infcx = infer::new_infer_ctxt(tcx);
843 // Try to give more informative error messages about self typing
844 // mismatches. Note that any mismatch will also be detected
845 // below, where we construct a canonical function type that
846 // includes the self parameter as a normal parameter. It's just
847 // that the error messages you get out of this code are a bit more
848 // inscrutable, particularly for cases where one method has no
850 match (&trait_m.explicit_self, &impl_m.explicit_self) {
851 (&ast::SelfStatic, &ast::SelfStatic) => {}
852 (&ast::SelfStatic, _) => {
855 format!("method `{}` has a `{}` declaration in the impl, \
856 but not in the trait",
857 token::get_ident(trait_m.ident),
858 pprust::explicit_self_to_str(
859 impl_m.explicit_self)).as_slice());
862 (_, &ast::SelfStatic) => {
865 format!("method `{}` has a `{}` declaration in the trait, \
866 but not in the impl",
867 token::get_ident(trait_m.ident),
868 pprust::explicit_self_to_str(
869 trait_m.explicit_self)).as_slice());
873 // Let the type checker catch other errors below
877 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
878 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
879 if num_impl_m_type_params != num_trait_m_type_params {
882 format!("method `{}` has {} type parameter{} \
883 but its trait declaration has {} type parameter{}",
884 token::get_ident(trait_m.ident),
885 num_impl_m_type_params,
886 if num_impl_m_type_params == 1 {""} else {"s"},
887 num_trait_m_type_params,
888 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
892 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
895 format!("method `{}` has {} parameter{} \
896 but the declaration in trait `{}` has {}",
897 token::get_ident(trait_m.ident),
898 impl_m.fty.sig.inputs.len(),
899 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
900 ty::item_path_str(tcx, trait_m.def_id),
901 trait_m.fty.sig.inputs.len()).as_slice());
905 let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
906 .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
908 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
909 // Check that the impl does not require any builtin-bounds
910 // that the trait does not guarantee:
912 impl_param_def.bounds.builtin_bounds -
913 trait_param_def.bounds.builtin_bounds;
914 if !extra_bounds.is_empty() {
917 format!("in method `{}`, \
918 type parameter {} requires `{}`, \
919 which is not required by \
920 the corresponding type parameter \
921 in the trait declaration",
922 token::get_ident(trait_m.ident),
924 extra_bounds.user_string(tcx)).as_slice());
928 // FIXME(#2687)---we should be checking that the bounds of the
929 // trait imply the bounds of the subtype, but it appears we
930 // are...not checking this.
931 if impl_param_def.bounds.trait_bounds.len() !=
932 trait_param_def.bounds.trait_bounds.len()
934 let found = impl_param_def.bounds.trait_bounds.len();
935 let expected = trait_param_def.bounds.trait_bounds.len();
938 format!("in method `{}`, type parameter {} has {} trait \
939 bound{}, but the corresponding type parameter in \
940 the trait declaration has {} trait bound{}",
941 token::get_ident(trait_m.ident),
944 if found == 1 {""} else {"s"},
946 if expected == 1 {""} else {"s"}).as_slice());
951 // This code is best explained by example. Consider a trait:
954 // fn method<'a,M>(t: T, m: &'a M) -> Self;
959 // impl<'i, U> Trait<&'i U> for Foo {
960 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
963 // We wish to decide if those two method types are compatible.
965 // We start out with trait_to_impl_substs, that maps the trait type
966 // parameters to impl type parameters:
968 // trait_to_impl_substs = {T => &'i U, Self => Foo}
970 // We create a mapping `dummy_substs` that maps from the impl type
971 // parameters to fresh types and regions. For type parameters,
972 // this is the identity transform, but we could as well use any
973 // skolemized types. For regions, we convert from bound to free
974 // regions (Note: but only early-bound regions, i.e., those
975 // declared on the impl or used in type parameter bounds).
977 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
979 // Now we can apply skol_substs to the type of the impl method
980 // to yield a new function type in terms of our fresh, skolemized
983 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
985 // We now want to extract and substitute the type of the *trait*
986 // method and compare it. To do so, we must create a compound
987 // substitution by combining trait_to_impl_substs and
988 // impl_to_skol_substs, and also adding a mapping for the method
989 // type parameters. We extend the mapping to also include
990 // the method parameters.
992 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
994 // Applying this to the trait method type yields:
996 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
998 // This type is also the same but the name of the bound region ('a
999 // vs 'b). However, the normal subtyping rules on fn types handle
1000 // this kind of equivalency just fine.
1002 // Create mapping from impl to skolemized.
1004 impl_m.generics.types.map(
1005 |d| ty::mk_param_from_def(tcx, d));
1007 impl_m.generics.regions.map(
1008 |l| ty::free_region_from_def(impl_m_body_id, l));
1009 let impl_to_skol_substs =
1010 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1012 // Compute skolemized form of impl method ty.
1013 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1014 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1016 // Compute skolemized form of trait method ty.
1017 let trait_to_skol_substs =
1018 trait_to_impl_substs
1019 .subst(tcx, &impl_to_skol_substs)
1020 .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
1021 skol_regions.get_vec(subst::FnSpace).clone());
1022 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1023 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1025 // Check the impl method type IM is a subtype of the trait method
1026 // type TM. To see why this makes sense, think of a vtable. The
1027 // expected type of the function pointers in the vtable is the
1028 // type TM of the trait method. The actual type will be the type
1029 // IM of the impl method. Because we know that IM <: TM, that
1030 // means that anywhere a TM is expected, a IM will do instead. In
1031 // other words, anyone expecting to call a method with the type
1032 // from the trait, can safely call a method with the type from the
1034 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1035 impl_fty, trait_fty) {
1040 format!("method `{}` has an incompatible type for trait: {}",
1041 token::get_ident(trait_m.ident),
1042 ty::type_err_to_str(tcx, terr)).as_slice());
1043 ty::note_and_explain_type_err(tcx, terr);
1048 impl<'a> AstConv for FnCtxt<'a> {
1049 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1051 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
1052 ty::lookup_item_type(self.tcx(), id)
1055 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1056 ty::lookup_trait_def(self.tcx(), id)
1059 fn ty_infer(&self, _span: Span) -> ty::t {
1060 self.infcx().next_ty_var()
1064 impl<'a> FnCtxt<'a> {
1065 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1069 pub fn err_count_since_creation(&self) -> uint {
1070 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1073 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1075 infcx: self.infcx(),
1076 param_env: &self.inh.param_env
1081 impl<'a> RegionScope for infer::InferCtxt<'a> {
1082 fn anon_regions(&self, span: Span, count: uint)
1083 -> Result<Vec<ty::Region> , ()> {
1084 Ok(Vec::from_fn(count, |_| {
1085 self.next_region_var(infer::MiscVariable(span))
1090 impl<'a> FnCtxt<'a> {
1091 pub fn tag(&self) -> String {
1092 format!("{}", self as *FnCtxt)
1095 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1096 match self.inh.locals.borrow().find(&nid) {
1099 self.tcx().sess.span_bug(
1101 format!("no type for local variable {:?}",
1108 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1109 debug!("write_ty({}, {}) in fcx {}",
1110 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1111 self.inh.node_types.borrow_mut().insert(node_id, ty);
1114 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1115 if !substs.substs.is_noop() {
1116 debug!("write_substs({}, {}) in fcx {}",
1118 substs.repr(self.tcx()),
1121 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1125 pub fn write_ty_substs(&self,
1126 node_id: ast::NodeId,
1128 substs: ty::ItemSubsts) {
1129 let ty = ty.subst(self.tcx(), &substs.substs);
1130 self.write_ty(node_id, ty);
1131 self.write_substs(node_id, substs);
1134 pub fn write_autoderef_adjustment(&self,
1135 node_id: ast::NodeId,
1137 if derefs == 0 { return; }
1138 self.write_adjustment(
1140 ty::AutoDerefRef(ty::AutoDerefRef {
1146 pub fn write_adjustment(&self,
1147 node_id: ast::NodeId,
1148 adj: ty::AutoAdjustment) {
1149 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1150 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1153 pub fn write_nil(&self, node_id: ast::NodeId) {
1154 self.write_ty(node_id, ty::mk_nil());
1156 pub fn write_bot(&self, node_id: ast::NodeId) {
1157 self.write_ty(node_id, ty::mk_bot());
1159 pub fn write_error(&self, node_id: ast::NodeId) {
1160 self.write_ty(node_id, ty::mk_err());
1163 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1164 ast_ty_to_ty(self, self.infcx(), ast_t)
1167 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1168 pat.repr(self.tcx())
1171 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1172 match self.inh.node_types.borrow().find(&ex.id) {
1175 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1176 self.tag()).as_slice());
1181 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1182 match self.inh.node_types.borrow().find(&id) {
1185 self.tcx().sess.bug(
1186 format!("no type for node {}: {} in fcx {}",
1187 id, self.tcx().map.node_to_str(id),
1188 self.tag()).as_slice());
1193 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1194 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1195 Some(method) => method.substs.clone(),
1197 self.tcx().sess.bug(
1198 format!("no method entry for node {}: {} in fcx {}",
1199 id, self.tcx().map.node_to_str(id),
1200 self.tag()).as_slice());
1205 pub fn opt_node_ty_substs(&self,
1207 f: |&ty::ItemSubsts|) {
1208 match self.inh.item_substs.borrow().find(&id) {
1214 pub fn mk_subty(&self,
1215 a_is_expected: bool,
1216 origin: infer::TypeOrigin,
1219 -> Result<(), ty::type_err> {
1220 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1223 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1224 -> Result<(), ty::type_err> {
1225 infer::can_mk_subty(self.infcx(), sub, sup)
1228 pub fn mk_assignty(&self,
1232 -> Result<(), ty::type_err> {
1233 match infer::mk_coercety(self.infcx(),
1235 infer::ExprAssignable(expr.span),
1239 Err(ref e) => Err((*e)),
1240 Ok(Some(adjustment)) => {
1241 self.write_adjustment(expr.id, adjustment);
1247 pub fn mk_eqty(&self,
1248 a_is_expected: bool,
1249 origin: infer::TypeOrigin,
1252 -> Result<(), ty::type_err> {
1253 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1256 pub fn mk_subr(&self,
1257 a_is_expected: bool,
1258 origin: infer::SubregionOrigin,
1261 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1264 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1265 let old_region_lb = self.region_lb.get();
1266 self.region_lb.set(lb);
1268 self.region_lb.set(old_region_lb);
1272 pub fn type_error_message(&self,
1274 mk_msg: |String| -> String,
1276 err: Option<&ty::type_err>) {
1277 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1280 pub fn report_mismatched_return_types(&self,
1284 err: &ty::type_err) {
1286 if ty::type_is_error(e) || ty::type_is_error(a) {
1289 self.infcx().report_mismatched_types(sp, e, a, err)
1292 pub fn report_mismatched_types(&self,
1296 err: &ty::type_err) {
1297 self.infcx().report_mismatched_types(sp, e, a, err)
1301 pub enum LvaluePreference {
1306 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1307 expr_id: Option<ast::NodeId>,
1308 mut lvalue_pref: LvaluePreference,
1309 should_stop: |ty::t, uint| -> Option<T>)
1310 -> (ty::t, uint, Option<T>) {
1312 * Executes an autoderef loop for the type `t`. At each step, invokes
1313 * `should_stop` to decide whether to terminate the loop. Returns
1314 * the final type and number of derefs that it performed.
1316 * Note: this method does not modify the adjustments table. The caller is
1317 * responsible for inserting an AutoAdjustment record into the `fcx`
1318 * using one of the suitable methods.
1321 let mut t = base_ty;
1322 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1323 let resolved_t = structurally_resolved_type(fcx, sp, t);
1325 match should_stop(resolved_t, autoderefs) {
1326 Some(x) => return (resolved_t, autoderefs, Some(x)),
1330 // Otherwise, deref if type is derefable:
1331 let mt = match ty::deref(resolved_t, false) {
1332 Some(mt) => Some(mt),
1335 expr_id.map(|id| MethodCall::autoderef(id, autoderefs as u32));
1336 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1342 if mt.mutbl == ast::MutImmutable {
1343 lvalue_pref = NoPreference;
1346 None => return (resolved_t, autoderefs, None)
1350 // We've reached the recursion limit, error gracefully.
1351 fcx.tcx().sess.span_err(sp,
1352 format!("reached the recursion limit while auto-dereferencing {}",
1353 base_ty.repr(fcx.tcx())).as_slice());
1354 (ty::mk_err(), 0, None)
1357 /// Attempts to resolve a call expression as an overloaded call.
1358 fn try_overloaded_call(fcx: &FnCtxt,
1359 call_expression: &ast::Expr,
1360 callee: Gc<ast::Expr>,
1362 args: &[Gc<ast::Expr>])
1364 // Try `FnOnce`, then `FnMut`, then `Fn`.
1365 for &(maybe_function_trait, method_name) in [
1366 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1367 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1368 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1370 let function_trait = match maybe_function_trait {
1372 Some(function_trait) => function_trait,
1374 let method_callee = match method::lookup_in_trait(
1376 call_expression.span,
1382 DontAutoderefReceiver,
1383 IgnoreStaticMethods) {
1385 Some(method_callee) => method_callee,
1387 let method_call = MethodCall::expr(call_expression.id);
1388 let output_type = check_method_argument_types(fcx,
1389 call_expression.span,
1395 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1396 write_call(fcx, call_expression, output_type);
1398 if !fcx.tcx().sess.features.overloaded_calls.get() {
1399 fcx.tcx().sess.span_err(call_expression.span,
1400 "overloaded calls are experimental");
1401 fcx.tcx().sess.span_note(call_expression.span,
1402 "add `#[feature(overloaded_calls)]` to \
1403 the crate attributes to enable");
1412 fn try_overloaded_deref(fcx: &FnCtxt,
1414 method_call: Option<MethodCall>,
1415 base_expr: Option<&ast::Expr>,
1417 lvalue_pref: LvaluePreference)
1419 // Try DerefMut first, if preferred.
1420 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1421 (PreferMutLvalue, Some(trait_did)) => {
1422 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1423 token::intern("deref_mut"), trait_did,
1424 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1429 // Otherwise, fall back to Deref.
1430 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1431 (None, Some(trait_did)) => {
1432 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1433 token::intern("deref"), trait_did,
1434 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1436 (method, _) => method
1441 let ref_ty = ty::ty_fn_ret(method.ty);
1443 Some(method_call) => {
1444 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1448 ty::deref(ref_ty, true)
1454 fn check_method_argument_types(fcx: &FnCtxt,
1456 method_fn_ty: ty::t,
1457 callee_expr: &ast::Expr,
1458 args: &[Gc<ast::Expr>],
1459 deref_args: DerefArgs,
1460 tuple_arguments: TupleArgumentsFlag)
1462 // HACK(eddyb) ignore provided self (it has special typeck rules).
1463 let args = if tuple_arguments == DontTupleArguments {
1468 if ty::type_is_error(method_fn_ty) {
1469 let err_inputs = err_args(args.len());
1470 check_argument_types(fcx,
1472 err_inputs.as_slice(),
1480 match ty::get(method_fn_ty).sty {
1481 ty::ty_bare_fn(ref fty) => {
1482 // HACK(eddyb) ignore self in the definition (see above).
1483 check_argument_types(fcx,
1485 fty.sig.inputs.slice_from(1),
1494 fcx.tcx().sess.span_bug(callee_expr.span,
1495 "method without bare fn type");
1501 fn check_argument_types(fcx: &FnCtxt,
1503 fn_inputs: &[ty::t],
1504 callee_expr: &ast::Expr,
1505 args: &[Gc<ast::Expr>],
1506 deref_args: DerefArgs,
1508 tuple_arguments: TupleArgumentsFlag) {
1511 * Generic function that factors out common logic from
1512 * function calls, method calls and overloaded operators.
1515 let tcx = fcx.ccx.tcx;
1517 // Grab the argument types, supplying fresh type variables
1518 // if the wrong number of arguments were supplied
1519 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1525 let expected_arg_count = fn_inputs.len();
1526 let formal_tys = if tuple_arguments == TupleArguments {
1527 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1528 match ty::get(tuple_type).sty {
1529 ty::ty_tup(ref arg_types) => {
1530 if arg_types.len() != args.len() {
1532 "this function takes {} parameter{} \
1533 but {} parameter{} supplied",
1535 if arg_types.len() == 1 {""} else {"s"},
1537 if args.len() == 1 {" was"} else {"s were"});
1538 tcx.sess.span_err(sp, msg.as_slice());
1539 err_args(args.len())
1541 (*arg_types).clone()
1545 if args.len() != 0 {
1547 "this function takes 0 parameters \
1548 but {} parameter{} supplied",
1550 if args.len() == 1 {" was"} else {"s were"});
1551 tcx.sess.span_err(sp, msg.as_slice());
1558 "cannot use call notation; the first type \
1559 parameter for the function trait is neither a \
1561 err_args(supplied_arg_count)
1564 } else if expected_arg_count == supplied_arg_count {
1565 fn_inputs.iter().map(|a| *a).collect()
1566 } else if variadic {
1567 if supplied_arg_count >= expected_arg_count {
1568 fn_inputs.iter().map(|a| *a).collect()
1571 "this function takes at least {} parameter{} \
1572 but {} parameter{} supplied",
1574 if expected_arg_count == 1 {""} else {"s"},
1576 if supplied_arg_count == 1 {" was"} else {"s were"});
1578 tcx.sess.span_err(sp, msg.as_slice());
1580 err_args(supplied_arg_count)
1584 "this function takes {} parameter{} \
1585 but {} parameter{} supplied",
1587 if expected_arg_count == 1 {""} else {"s"},
1589 if supplied_arg_count == 1 {" was"} else {"s were"});
1591 tcx.sess.span_err(sp, msg.as_slice());
1593 err_args(supplied_arg_count)
1596 debug!("check_argument_types: formal_tys={:?}",
1597 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1599 // Check the arguments.
1600 // We do this in a pretty awful way: first we typecheck any arguments
1601 // that are not anonymous functions, then we typecheck the anonymous
1602 // functions. This is so that we have more information about the types
1603 // of arguments when we typecheck the functions. This isn't really the
1604 // right way to do this.
1605 let xs = [false, true];
1606 for check_blocks in xs.iter() {
1607 let check_blocks = *check_blocks;
1608 debug!("check_blocks={}", check_blocks);
1610 // More awful hacks: before we check the blocks, try to do
1611 // an "opportunistic" vtable resolution of any trait
1612 // bounds on the call.
1614 vtable::early_resolve_expr(callee_expr, fcx, true);
1617 // For variadic functions, we don't have a declared type for all of
1618 // the arguments hence we only do our usual type checking with
1619 // the arguments who's types we do know.
1620 let t = if variadic {
1622 } else if tuple_arguments == TupleArguments {
1627 for (i, arg) in args.iter().take(t).enumerate() {
1628 let is_block = match arg.node {
1629 ast::ExprFnBlock(..) |
1630 ast::ExprProc(..) => true,
1634 if is_block == check_blocks {
1635 debug!("checking the argument");
1636 let mut formal_ty = *formal_tys.get(i);
1640 match ty::get(formal_ty).sty {
1641 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1644 // So we hit this case when one implements the
1645 // operator traits but leaves an argument as
1646 // just T instead of &T. We'll catch it in the
1647 // mismatch impl/trait method phase no need to
1650 formal_ty = ty::mk_err();
1657 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1663 // We also need to make sure we at least write the ty of the other
1664 // arguments which we skipped above.
1666 for arg in args.iter().skip(expected_arg_count) {
1667 check_expr(fcx, &**arg);
1669 // There are a few types which get autopromoted when passed via varargs
1670 // in C but we just error out instead and require explicit casts.
1671 let arg_ty = structurally_resolved_type(fcx, arg.span,
1672 fcx.expr_ty(&**arg));
1673 match ty::get(arg_ty).sty {
1674 ty::ty_float(ast::TyF32) => {
1675 fcx.type_error_message(arg.span,
1677 format!("can't pass an {} to variadic \
1678 function, cast to c_double", t)
1681 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1682 fcx.type_error_message(arg.span, |t| {
1683 format!("can't pass {} to variadic \
1684 function, cast to c_int",
1688 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1689 fcx.type_error_message(arg.span, |t| {
1690 format!("can't pass {} to variadic \
1691 function, cast to c_uint",
1701 fn err_args(len: uint) -> Vec<ty::t> {
1702 Vec::from_fn(len, |_| ty::mk_err())
1705 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1706 fcx.write_ty(call_expr.id, output);
1709 // AST fragment checking
1710 pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
1711 let tcx = fcx.ccx.tcx;
1714 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1715 ast::LitBinary(..) => {
1716 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1718 ast::LitByte(_) => ty::mk_u8(),
1719 ast::LitChar(_) => ty::mk_char(),
1720 ast::LitInt(_, t) => ty::mk_mach_int(t),
1721 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1722 ast::LitIntUnsuffixed(_) => {
1723 // An unsuffixed integer literal could have any integral type,
1724 // so we create an integral type variable for it.
1725 ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())
1727 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1728 ast::LitFloatUnsuffixed(_) => {
1729 // An unsuffixed floating point literal could have any floating point
1730 // type, so we create a floating point type variable for it.
1731 ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())
1733 ast::LitNil => ty::mk_nil(),
1734 ast::LitBool(_) => ty::mk_bool()
1738 pub fn valid_range_bounds(ccx: &CrateCtxt,
1742 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1743 Some(val) => Some(val <= 0),
1748 pub fn check_expr_has_type(
1749 fcx: &FnCtxt, expr: &ast::Expr,
1751 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1752 demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
1756 fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1757 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1758 demand::coerce(fcx, expr.span, expected, expr)
1762 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1763 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
1766 fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
1767 expected: Option<ty::t>) {
1768 check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
1771 fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
1773 expected: Option<ty::t>,
1774 lvalue_pref: LvaluePreference) {
1775 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1778 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1779 check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
1782 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1783 lvalue_pref: LvaluePreference) {
1784 check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
1788 // determine the `self` type, using fresh variables for all variables
1789 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1790 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1792 pub fn impl_self_ty(vcx: &VtableContext,
1793 span: Span, // (potential) receiver for this impl
1795 -> ty_param_substs_and_ty {
1796 let tcx = vcx.tcx();
1798 let ity = ty::lookup_item_type(tcx, did);
1799 let (n_tps, rps, raw_ty) =
1800 (ity.generics.types.len(subst::TypeSpace),
1801 ity.generics.regions.get_vec(subst::TypeSpace),
1804 let rps = vcx.infcx.region_vars_for_defs(span, rps);
1805 let tps = vcx.infcx.next_ty_vars(n_tps);
1806 let substs = subst::Substs::new_type(tps, rps);
1807 let substd_ty = raw_ty.subst(tcx, &substs);
1809 ty_param_substs_and_ty { substs: substs, ty: substd_ty }
1812 // Only for fields! Returns <none> for methods>
1813 // Indifferent to privacy flags
1814 pub fn lookup_field_ty(tcx: &ty::ctxt,
1815 class_id: ast::DefId,
1816 items: &[ty::field_ty],
1817 fieldname: ast::Name,
1818 substs: &subst::Substs) -> Option<ty::t> {
1820 let o_field = items.iter().find(|f| f.name == fieldname);
1821 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
1824 // Controls whether the arguments are automatically referenced. This is useful
1825 // for overloaded binary and unary operators.
1826 pub enum DerefArgs {
1831 /// Controls whether the arguments are tupled. This is used for the call
1834 /// Tupling means that all call-side arguments are packed into a tuple and
1835 /// passed as a single parameter. For example, if tupling is enabled, this
1838 /// fn f(x: (int, int))
1840 /// Can be called as:
1847 #[deriving(Clone, Eq, PartialEq)]
1848 enum TupleArgumentsFlag {
1854 /// If an expression has any sub-expressions that result in a type error,
1855 /// inspecting that expression's type with `ty::type_is_error` will return
1856 /// true. Likewise, if an expression is known to diverge, inspecting its
1857 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
1858 /// strict, _|_ can appear in the type of an expression that does not,
1859 /// itself, diverge: for example, fn() -> _|_.)
1860 /// Note that inspecting a type's structure *directly* may expose the fact
1861 /// that there are actually multiple representations for both `ty_err` and
1862 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
1863 fn check_expr_with_unifier(fcx: &FnCtxt,
1865 expected: Option<ty::t>,
1866 lvalue_pref: LvaluePreference,
1868 debug!(">> typechecking");
1870 // A generic function for doing all of the checking for call expressions
1871 fn check_call(fcx: &FnCtxt,
1872 call_expr: &ast::Expr,
1874 args: &[Gc<ast::Expr>]) {
1875 // Store the type of `f` as the type of the callee
1876 let fn_ty = fcx.expr_ty(f);
1878 // Extract the function signature from `in_fty`.
1879 let fn_sty = structure_of(fcx, f.span, fn_ty);
1881 // This is the "default" function signature, used in case of error.
1882 // In that case, we check each argument against "error" in order to
1883 // set up all the node type bindings.
1884 let error_fn_sig = FnSig {
1885 binder_id: ast::CRATE_NODE_ID,
1886 inputs: err_args(args.len()),
1887 output: ty::mk_err(),
1891 let fn_sig = match *fn_sty {
1892 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
1893 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
1895 fcx.type_error_message(call_expr.span, |actual| {
1896 format!("expected function but found `{}`", actual)
1902 // Replace any bound regions that appear in the function
1903 // signature with region variables
1904 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
1905 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
1908 // Call the generic checker.
1909 check_argument_types(fcx,
1911 fn_sig.inputs.as_slice(),
1916 DontTupleArguments);
1918 write_call(fcx, call_expr, fn_sig.output);
1921 // Checks a method call.
1922 fn check_method_call(fcx: &FnCtxt,
1924 method_name: ast::SpannedIdent,
1925 args: &[Gc<ast::Expr>],
1926 tps: &[ast::P<ast::Ty>]) {
1927 let rcvr = args[0].clone();
1928 // We can't know if we need &mut self before we look up the method,
1929 // so treat the receiver as mutable just in case - only explicit
1930 // overloaded dereferences care about the distinction.
1931 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
1933 // no need to check for bot/err -- callee does that
1934 let expr_t = structurally_resolved_type(fcx,
1936 fcx.expr_ty(&*rcvr));
1938 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
1939 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
1940 method_name.node.name,
1941 expr_t, tps.as_slice(),
1943 CheckTraitsAndInherentMethods,
1944 AutoderefReceiver, IgnoreStaticMethods) {
1946 let method_ty = method.ty;
1947 let method_call = MethodCall::expr(expr.id);
1948 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1952 debug!("(checking method call) failing expr is {}", expr.id);
1954 fcx.type_error_message(method_name.span,
1956 format!("type `{}` does not implement any \
1957 method in scope named `{}`",
1959 token::get_ident(method_name.node))
1964 // Add error type for the result
1965 fcx.write_error(expr.id);
1967 // Check for potential static matches (missing self parameters)
1971 method_name.node.name,
1975 CheckTraitsAndInherentMethods,
1976 DontAutoderefReceiver,
1977 ReportStaticMethods);
1983 // Call the generic checker.
1984 let ret_ty = check_method_argument_types(fcx,
1990 DontTupleArguments);
1992 write_call(fcx, expr, ret_ty);
1995 // A generic function for checking the then and else in an if
1997 fn check_then_else(fcx: &FnCtxt,
1998 cond_expr: &ast::Expr,
1999 then_blk: &ast::Block,
2000 opt_else_expr: Option<Gc<ast::Expr>>,
2003 expected: Option<ty::t>) {
2004 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2006 let branches_ty = match opt_else_expr {
2007 Some(ref else_expr) => {
2008 check_block_with_expected(fcx, then_blk, expected);
2009 let then_ty = fcx.node_ty(then_blk.id);
2010 check_expr_with_opt_hint(fcx, &**else_expr, expected);
2011 let else_ty = fcx.expr_ty(&**else_expr);
2012 infer::common_supertype(fcx.infcx(),
2013 infer::IfExpression(sp),
2019 check_block_no_value(fcx, then_blk);
2024 let cond_ty = fcx.expr_ty(cond_expr);
2025 let if_ty = if ty::type_is_error(cond_ty) {
2027 } else if ty::type_is_bot(cond_ty) {
2033 fcx.write_ty(id, if_ty);
2036 fn lookup_op_method(fcx: &FnCtxt,
2040 trait_did: Option<ast::DefId>,
2041 args: &[Gc<ast::Expr>],
2042 autoderef_receiver: AutoderefReceiverFlag,
2043 unbound_method: ||) -> ty::t {
2044 let method = match trait_did {
2045 Some(trait_did) => {
2046 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2047 trait_did, self_t, [], autoderef_receiver,
2048 IgnoreStaticMethods)
2054 let method_ty = method.ty;
2055 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2056 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2057 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2058 check_method_argument_types(fcx,
2068 // Check the args anyway
2069 // so we get all the error messages
2070 let expected_ty = ty::mk_err();
2071 check_method_argument_types(fcx,
2077 DontTupleArguments);
2083 // could be either an expr_binop or an expr_assign_binop
2084 fn check_binop(fcx: &FnCtxt,
2089 is_binop_assignment: IsBinopAssignment) {
2090 let tcx = fcx.ccx.tcx;
2092 let lvalue_pref = match is_binop_assignment {
2093 BinopAssignment => PreferMutLvalue,
2094 SimpleBinop => NoPreference
2096 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2098 // Callee does bot / err checking
2099 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2100 fcx.expr_ty(&*lhs));
2102 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2103 // Shift is a special case: rhs can be any integral type
2104 check_expr(fcx, &*rhs);
2105 let rhs_t = fcx.expr_ty(&*rhs);
2106 require_integral(fcx, rhs.span, rhs_t);
2107 fcx.write_ty(expr.id, lhs_t);
2111 if ty::is_binopable(tcx, lhs_t, op) {
2112 let tvar = fcx.infcx().next_ty_var();
2113 demand::suptype(fcx, expr.span, tvar, lhs_t);
2114 check_expr_has_type(fcx, &*rhs, tvar);
2116 let result_t = match op {
2117 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2119 if ty::type_is_simd(tcx, lhs_t) {
2120 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2121 fcx.type_error_message(expr.span,
2123 format!("binary comparison \
2124 operation `{}` not \
2125 supported for floating \
2126 point SIMD vector `{}`",
2127 ast_util::binop_to_str(op),
2144 fcx.write_ty(expr.id, result_t);
2148 if op == ast::BiOr || op == ast::BiAnd {
2149 // This is an error; one of the operands must have the wrong
2151 fcx.write_error(expr.id);
2152 fcx.write_error(rhs.id);
2153 fcx.type_error_message(expr.span,
2155 format!("binary operation `{}` cannot be applied \
2157 ast_util::binop_to_str(op),
2164 // Check for overloaded operators if not an assignment.
2165 let result_t = if is_binop_assignment == SimpleBinop {
2166 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2168 fcx.type_error_message(expr.span,
2170 format!("binary assignment \
2172 cannot be applied to \
2174 ast_util::binop_to_str(op),
2179 check_expr(fcx, &*rhs);
2183 fcx.write_ty(expr.id, result_t);
2184 if ty::type_is_error(result_t) {
2185 fcx.write_ty(rhs.id, result_t);
2189 fn check_user_binop(fcx: &FnCtxt,
2191 lhs_expr: Gc<ast::Expr>,
2192 lhs_resolved_t: ty::t,
2194 rhs: Gc<ast::Expr>) -> ty::t {
2195 let tcx = fcx.ccx.tcx;
2196 let lang = &tcx.lang_items;
2197 let (name, trait_did) = match op {
2198 ast::BiAdd => ("add", lang.add_trait()),
2199 ast::BiSub => ("sub", lang.sub_trait()),
2200 ast::BiMul => ("mul", lang.mul_trait()),
2201 ast::BiDiv => ("div", lang.div_trait()),
2202 ast::BiRem => ("rem", lang.rem_trait()),
2203 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2204 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2205 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2206 ast::BiShl => ("shl", lang.shl_trait()),
2207 ast::BiShr => ("shr", lang.shr_trait()),
2208 ast::BiLt => ("lt", lang.ord_trait()),
2209 ast::BiLe => ("le", lang.ord_trait()),
2210 ast::BiGe => ("ge", lang.ord_trait()),
2211 ast::BiGt => ("gt", lang.ord_trait()),
2212 ast::BiEq => ("eq", lang.eq_trait()),
2213 ast::BiNe => ("ne", lang.eq_trait()),
2214 ast::BiAnd | ast::BiOr => {
2215 check_expr(fcx, &*rhs);
2216 return ty::mk_err();
2219 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2220 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2221 fcx.type_error_message(ex.span, |actual| {
2222 format!("binary operation `{}` cannot be applied to type `{}`",
2223 ast_util::binop_to_str(op),
2225 }, lhs_resolved_t, None)
2229 fn check_user_unop(fcx: &FnCtxt,
2232 trait_did: Option<ast::DefId>,
2234 rhs_expr: Gc<ast::Expr>,
2235 rhs_t: ty::t) -> ty::t {
2236 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2237 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2238 fcx.type_error_message(ex.span, |actual| {
2239 format!("cannot apply unary operator `{}` to type `{}`",
2245 // Resolves `expected` by a single level if it is a variable and passes it
2246 // through the `unpack` function. It there is no expected type or
2247 // resolution is not possible (e.g., no constraints yet present), just
2249 fn unpack_expected<O>(
2251 expected: Option<ty::t>,
2252 unpack: |&ty::sty| -> Option<O>)
2256 match resolve_type(fcx.infcx(), t, force_tvar) {
2257 Ok(t) => unpack(&ty::get(t).sty),
2265 fn check_expr_fn(fcx: &FnCtxt,
2267 store: ty::TraitStore,
2269 body: ast::P<ast::Block>,
2270 expected: Option<ty::t>) {
2271 let tcx = fcx.ccx.tcx;
2273 // Find the expected input/output types (if any). Substitute
2274 // fresh bound regions for any bound regions we find in the
2275 // expected types so as to avoid capture.
2276 let expected_sty = unpack_expected(fcx,
2278 |x| Some((*x).clone()));
2281 expected_bounds) = {
2282 match expected_sty {
2283 Some(ty::ty_closure(ref cenv)) => {
2285 replace_late_bound_regions_in_fn_sig(
2287 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2288 let onceness = match (&store, &cenv.store) {
2289 // As the closure type and onceness go, only three
2290 // combinations are legit:
2294 // If the actual and expected closure type disagree with
2295 // each other, set expected onceness to be always Once or
2296 // Many according to the actual type. Otherwise, it will
2297 // yield either an illegal "many proc" or a less known
2298 // "once closure" in the error message.
2299 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2300 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2302 (&ty::UniqTraitStore, _) => ast::Once,
2303 (&ty::RegionTraitStore(..), _) => ast::Many,
2305 (Some(sig), onceness, cenv.bounds)
2308 // Not an error! Means we're inferring the closure type
2309 let mut bounds = ty::empty_builtin_bounds();
2310 let onceness = match expr.node {
2311 ast::ExprProc(..) => {
2312 bounds.add(ty::BoundSend);
2317 (None, onceness, bounds)
2322 // construct the function type
2323 let fn_ty = astconv::ty_of_closure(fcx,
2331 let fty_sig = fn_ty.sig.clone();
2332 let fty = ty::mk_closure(tcx, fn_ty);
2333 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2335 fcx.write_ty(expr.id, fty);
2337 // If the closure is a stack closure and hasn't had some non-standard
2338 // style inferred for it, then check it under its parent's style.
2339 // Otherwise, use its own
2340 let (inherited_style, id) = match store {
2341 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2342 fcx.ps.borrow().def),
2343 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2346 check_fn(fcx.ccx, inherited_style, &fty_sig,
2347 &*decl, id, &*body, fcx.inh);
2351 // Check field access expressions
2352 fn check_field(fcx: &FnCtxt,
2354 lvalue_pref: LvaluePreference,
2356 field: &ast::SpannedIdent,
2357 tys: &[ast::P<ast::Ty>]) {
2358 let tcx = fcx.ccx.tcx;
2359 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2360 let expr_t = structurally_resolved_type(fcx, expr.span,
2362 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2363 let (_, autoderefs, field_ty) =
2364 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2365 match ty::get(base_t).sty {
2366 ty::ty_struct(base_id, ref substs) => {
2367 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2368 let fields = ty::lookup_struct_fields(tcx, base_id);
2369 lookup_field_ty(tcx, base_id, fields.as_slice(),
2370 field.node.name, &(*substs))
2377 fcx.write_ty(expr.id, field_ty);
2378 fcx.write_autoderef_adjustment(base.id, autoderefs);
2384 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2385 match method::lookup(fcx,
2392 CheckTraitsAndInherentMethods,
2394 IgnoreStaticMethods) {
2396 fcx.type_error_message(
2399 format!("attempted to take value of method `{}` on type \
2400 `{}`", token::get_ident(field.node), actual)
2404 tcx.sess.span_note(field.span,
2405 "maybe a missing `()` to call it? If not, try an anonymous function.");
2409 fcx.type_error_message(
2412 format!("attempted access of field `{}` on \
2413 type `{}`, but no field with that \
2415 token::get_ident(field.node),
2422 fcx.write_error(expr.id);
2425 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2428 class_id: ast::DefId,
2429 node_id: ast::NodeId,
2430 substitutions: subst::Substs,
2431 field_types: &[ty::field_ty],
2432 ast_fields: &[ast::Field],
2433 check_completeness: bool) {
2434 let tcx = fcx.ccx.tcx;
2436 let mut class_field_map = HashMap::new();
2437 let mut fields_found = 0;
2438 for field in field_types.iter() {
2439 class_field_map.insert(field.name, (field.id, false));
2442 let mut error_happened = false;
2444 // Typecheck each field.
2445 for field in ast_fields.iter() {
2446 let mut expected_field_type = ty::mk_err();
2448 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2451 fcx.type_error_message(
2454 format!("structure `{}` has no field named `{}`",
2455 actual, token::get_ident(field.ident.node))
2459 error_happened = true;
2461 Some((_, true)) => {
2464 format!("field `{}` specified more than once",
2465 token::get_ident(field.ident
2466 .node)).as_slice());
2467 error_happened = true;
2469 Some((field_id, false)) => {
2470 expected_field_type =
2471 ty::lookup_field_type(
2472 tcx, class_id, field_id, &substitutions);
2473 class_field_map.insert(
2474 field.ident.node.name, (field_id, true));
2478 // Make sure to give a type to the field even if there's
2479 // an error, so we can continue typechecking
2480 check_expr_coercable_to_type(
2483 expected_field_type);
2487 fcx.write_error(node_id);
2490 if check_completeness && !error_happened {
2491 // Make sure the programmer specified all the fields.
2492 assert!(fields_found <= field_types.len());
2493 if fields_found < field_types.len() {
2494 let mut missing_fields = Vec::new();
2495 for class_field in field_types.iter() {
2496 let name = class_field.name;
2497 let (_, seen) = *class_field_map.get(&name);
2499 missing_fields.push(
2500 format!("`{}`", token::get_name(name).get()))
2504 tcx.sess.span_err(span,
2506 "missing field{}: {fields}",
2507 if missing_fields.len() == 1 {""} else {"s"},
2508 fields = missing_fields.connect(", ")).as_slice());
2512 if !error_happened {
2513 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2514 class_id, substitutions));
2518 fn check_struct_constructor(fcx: &FnCtxt,
2520 span: codemap::Span,
2521 class_id: ast::DefId,
2522 fields: &[ast::Field],
2523 base_expr: Option<Gc<ast::Expr>>) {
2524 let tcx = fcx.ccx.tcx;
2526 // Look up the number of type parameters and the raw type, and
2527 // determine whether the class is region-parameterized.
2528 let item_type = ty::lookup_item_type(tcx, class_id);
2529 let raw_type = item_type.ty;
2531 // Generate the struct type.
2532 let substitutions = fcx.infcx().fresh_substs_for_type(
2533 span, &item_type.generics);
2534 let mut struct_type = raw_type.subst(tcx, &substitutions);
2536 // Look up and check the fields.
2537 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2538 check_struct_or_variant_fields(fcx,
2544 class_fields.as_slice(),
2546 base_expr.is_none());
2547 if ty::type_is_error(fcx.node_ty(id)) {
2548 struct_type = ty::mk_err();
2551 // Check the base expression if necessary.
2554 Some(base_expr) => {
2555 check_expr_has_type(fcx, &*base_expr, struct_type);
2556 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2557 struct_type = ty::mk_bot();
2562 // Write in the resulting type.
2563 fcx.write_ty(id, struct_type);
2566 fn check_struct_enum_variant(fcx: &FnCtxt,
2568 span: codemap::Span,
2569 enum_id: ast::DefId,
2570 variant_id: ast::DefId,
2571 fields: &[ast::Field]) {
2572 let tcx = fcx.ccx.tcx;
2574 // Look up the number of type parameters and the raw type, and
2575 // determine whether the enum is region-parameterized.
2576 let item_type = ty::lookup_item_type(tcx, enum_id);
2577 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2578 let enum_type = item_type.ty.subst(tcx, &substitutions);
2580 // Look up and check the enum variant fields.
2581 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2582 check_struct_or_variant_fields(fcx,
2588 variant_fields.as_slice(),
2591 fcx.write_ty(id, enum_type);
2594 let tcx = fcx.ccx.tcx;
2597 ast::ExprVstore(ev, vst) => {
2598 let typ = match ev.node {
2599 ast::ExprVec(ref args) => {
2600 let mutability = match vst {
2601 ast::ExprVstoreMutSlice => ast::MutMutable,
2602 _ => ast::MutImmutable,
2604 let mut any_error = false;
2605 let mut any_bot = false;
2606 let t: ty::t = fcx.infcx().next_ty_var();
2607 for e in args.iter() {
2608 check_expr_has_type(fcx, &**e, t);
2609 let arg_t = fcx.expr_ty(&**e);
2610 if ty::type_is_error(arg_t) {
2613 else if ty::type_is_bot(arg_t) {
2622 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2623 ty::mt{ ty: ty::mk_vec(tcx,
2624 ty::mt {ty: t, mutbl: mutability},
2626 mutbl: mutability })
2629 ast::ExprRepeat(ref element, ref count_expr) => {
2630 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2631 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2632 let mutability = match vst {
2633 ast::ExprVstoreMutSlice => ast::MutMutable,
2634 _ => ast::MutImmutable,
2636 let t = fcx.infcx().next_ty_var();
2637 check_expr_has_type(fcx, &**element, t);
2638 let arg_t = fcx.expr_ty(&**element);
2639 if ty::type_is_error(arg_t) {
2641 } else if ty::type_is_bot(arg_t) {
2644 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2645 ty::mt{ ty: ty::mk_vec(tcx,
2646 ty::mt {ty: t, mutbl: mutability},
2651 ast::ExprLit(_) => {
2652 let error = if vst == ast::ExprVstoreSlice {
2653 "`&\"string\"` has been removed; use `\"string\"` instead"
2655 "`~\"string\"` has been removed; use `\"string\".to_string()` instead"
2657 tcx.sess.span_err(expr.span, error);
2660 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2662 fcx.write_ty(ev.id, typ);
2663 fcx.write_ty(id, typ);
2666 ast::ExprBox(ref place, ref subexpr) => {
2667 check_expr(fcx, &**place);
2668 check_expr(fcx, &**subexpr);
2670 let mut checked = false;
2672 ast::ExprPath(ref path) => {
2673 // FIXME(pcwalton): For now we hardcode the two permissible
2674 // places: the exchange heap and the managed heap.
2675 let definition = lookup_def(fcx, path.span, place.id);
2676 let def_id = definition.def_id();
2677 if tcx.lang_items.exchange_heap() == Some(def_id) {
2678 fcx.write_ty(id, ty::mk_uniq(tcx,
2679 fcx.expr_ty(&**subexpr)));
2681 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2682 fcx.write_ty(id, ty::mk_box(tcx,
2683 fcx.expr_ty(&**subexpr)));
2691 tcx.sess.span_err(expr.span,
2692 "only the managed heap and exchange heap are \
2693 currently supported");
2694 fcx.write_ty(id, ty::mk_err());
2698 ast::ExprLit(ref lit) => {
2699 let typ = check_lit(fcx, &**lit);
2700 fcx.write_ty(id, typ);
2702 ast::ExprBinary(op, ref lhs, ref rhs) => {
2703 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2705 let lhs_ty = fcx.expr_ty(&**lhs);
2706 let rhs_ty = fcx.expr_ty(&**rhs);
2707 if ty::type_is_error(lhs_ty) ||
2708 ty::type_is_error(rhs_ty) {
2709 fcx.write_error(id);
2711 else if ty::type_is_bot(lhs_ty) ||
2712 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2716 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2717 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
2719 let lhs_t = fcx.expr_ty(&**lhs);
2720 let result_t = fcx.expr_ty(expr);
2721 demand::suptype(fcx, expr.span, result_t, lhs_t);
2723 let tcx = fcx.tcx();
2724 if !ty::expr_is_lval(tcx, &**lhs) {
2725 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2728 // Overwrite result of check_binop...this preserves existing behavior
2729 // but seems quite dubious with regard to user-defined methods
2730 // and so forth. - Niko
2731 if !ty::type_is_error(result_t)
2732 && !ty::type_is_bot(result_t) {
2733 fcx.write_nil(expr.id);
2736 ast::ExprUnary(unop, ref oprnd) => {
2737 let exp_inner = unpack_expected(fcx, expected, |sty| {
2739 ast::UnBox | ast::UnUniq => match *sty {
2740 ty::ty_box(ty) | ty::ty_uniq(ty) => Some(ty),
2743 ast::UnNot | ast::UnNeg => expected,
2744 ast::UnDeref => None
2747 let lvalue_pref = match unop {
2748 ast::UnDeref => lvalue_pref,
2751 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**oprnd, exp_inner, lvalue_pref);
2752 let mut oprnd_t = fcx.expr_ty(&**oprnd);
2753 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2756 oprnd_t = ty::mk_box(tcx, oprnd_t)
2759 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2762 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2763 oprnd_t = match ty::deref(oprnd_t, true) {
2765 None => match try_overloaded_deref(fcx, expr.span,
2766 Some(MethodCall::expr(expr.id)),
2767 Some(&**oprnd), oprnd_t, lvalue_pref) {
2770 let is_newtype = match ty::get(oprnd_t).sty {
2771 ty::ty_struct(did, ref substs) => {
2772 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2774 && fields.get(0).ident ==
2775 token::special_idents::unnamed_field
2780 // This is an obsolete struct deref
2781 tcx.sess.span_err(expr.span,
2782 "single-field tuple-structs can \
2783 no longer be dereferenced");
2785 fcx.type_error_message(expr.span, |actual| {
2786 format!("type `{}` cannot be \
2787 dereferenced", actual)
2796 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2798 if !(ty::type_is_integral(oprnd_t) ||
2799 ty::get(oprnd_t).sty == ty::ty_bool) {
2800 oprnd_t = check_user_unop(fcx, "!", "not",
2801 tcx.lang_items.not_trait(),
2802 expr, oprnd.clone(), oprnd_t);
2806 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2808 if !(ty::type_is_integral(oprnd_t) ||
2809 ty::type_is_fp(oprnd_t)) {
2810 oprnd_t = check_user_unop(fcx, "-", "neg",
2811 tcx.lang_items.neg_trait(),
2812 expr, oprnd.clone(), oprnd_t);
2817 fcx.write_ty(id, oprnd_t);
2819 ast::ExprAddrOf(mutbl, ref oprnd) => {
2820 let hint = unpack_expected(
2822 |sty| match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty),
2824 let lvalue_pref = match mutbl {
2825 ast::MutMutable => PreferMutLvalue,
2826 ast::MutImmutable => NoPreference
2828 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**oprnd, hint, lvalue_pref);
2830 // Note: at this point, we cannot say what the best lifetime
2831 // is to use for resulting pointer. We want to use the
2832 // shortest lifetime possible so as to avoid spurious borrowck
2833 // errors. Moreover, the longest lifetime will depend on the
2834 // precise details of the value whose address is being taken
2835 // (and how long it is valid), which we don't know yet until type
2836 // inference is complete.
2838 // Therefore, here we simply generate a region variable. The
2839 // region inferencer will then select the ultimate value.
2840 // Finally, borrowck is charged with guaranteeing that the
2841 // value whose address was taken can actually be made to live
2842 // as long as it needs to live.
2843 let region = fcx.infcx().next_region_var(
2844 infer::AddrOfRegion(expr.span));
2846 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
2847 let oprnd_t = if ty::type_is_error(tm.ty) {
2849 } else if ty::type_is_bot(tm.ty) {
2853 ty::mk_rptr(tcx, region, tm)
2855 fcx.write_ty(id, oprnd_t);
2857 ast::ExprPath(ref pth) => {
2858 let defn = lookup_def(fcx, pth.span, id);
2859 let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
2860 instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
2862 ast::ExprInlineAsm(ref ia) => {
2863 for &(_, ref input) in ia.inputs.iter() {
2864 check_expr(fcx, &**input);
2866 for &(_, ref out) in ia.outputs.iter() {
2867 check_expr(fcx, &**out);
2871 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
2872 ast::ExprBreak(_) => { fcx.write_bot(id); }
2873 ast::ExprAgain(_) => { fcx.write_bot(id); }
2874 ast::ExprRet(ref expr_opt) => {
2875 let ret_ty = fcx.ret_ty;
2877 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
2878 ret_ty, ty::mk_nil()) {
2879 Ok(_) => { /* fall through */ }
2883 "`return;` in function returning non-nil");
2887 check_expr_has_type(fcx, &**e, ret_ty);
2892 ast::ExprParen(ref a) => {
2893 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**a, expected, lvalue_pref);
2894 fcx.write_ty(id, fcx.expr_ty(&**a));
2896 ast::ExprAssign(ref lhs, ref rhs) => {
2897 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
2899 let tcx = fcx.tcx();
2900 if !ty::expr_is_lval(tcx, &**lhs) {
2901 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2904 let lhs_ty = fcx.expr_ty(&**lhs);
2905 check_expr_has_type(fcx, &**rhs, lhs_ty);
2906 let rhs_ty = fcx.expr_ty(&**rhs);
2908 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
2909 fcx.write_error(id);
2910 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
2916 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
2917 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
2918 id, expr.span, expected);
2920 ast::ExprWhile(ref cond, ref body) => {
2921 check_expr_has_type(fcx, &**cond, ty::mk_bool());
2922 check_block_no_value(fcx, &**body);
2923 let cond_ty = fcx.expr_ty(&**cond);
2924 let body_ty = fcx.node_ty(body.id);
2925 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
2926 fcx.write_error(id);
2928 else if ty::type_is_bot(cond_ty) {
2935 ast::ExprForLoop(..) =>
2936 fail!("non-desugared expr_for_loop"),
2937 ast::ExprLoop(ref body, _) => {
2938 check_block_no_value(fcx, &**body);
2939 if !may_break(tcx, expr.id, body.clone()) {
2946 ast::ExprMatch(ref discrim, ref arms) => {
2947 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
2949 ast::ExprFnBlock(ref decl, ref body) => {
2950 let region = astconv::opt_ast_region_to_region(fcx,
2956 ty::RegionTraitStore(region, ast::MutMutable),
2961 ast::ExprProc(ref decl, ref body) => {
2969 ast::ExprBlock(ref b) => {
2970 check_block_with_expected(fcx, &**b, expected);
2971 fcx.write_ty(id, fcx.node_ty(b.id));
2973 ast::ExprCall(ref f, ref args) => {
2974 // Index expressions need to be handled separately, to inform them
2975 // that they appear in call position.
2976 check_expr(fcx, &**f);
2977 let f_ty = fcx.expr_ty(&**f);
2979 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
2980 check_call(fcx, expr, &**f, args.as_slice());
2981 let (args_bot, args_err) = args.iter().fold((false, false),
2982 |(rest_bot, rest_err), a| {
2983 // is this not working?
2984 let a_ty = fcx.expr_ty(&**a);
2985 (rest_bot || ty::type_is_bot(a_ty),
2986 rest_err || ty::type_is_error(a_ty))});
2987 if ty::type_is_error(f_ty) || args_err {
2988 fcx.write_error(id);
2990 else if ty::type_is_bot(f_ty) || args_bot {
2995 ast::ExprMethodCall(ident, ref tps, ref args) => {
2996 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
2997 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
2998 let (args_bot, args_err) = arg_tys.fold((false, false),
2999 |(rest_bot, rest_err), a| {
3000 (rest_bot || ty::type_is_bot(a),
3001 rest_err || ty::type_is_error(a))});
3003 fcx.write_error(id);
3004 } else if args_bot {
3008 ast::ExprCast(ref e, ref t) => {
3009 check_expr(fcx, &**e);
3010 let t_1 = fcx.to_ty(&**t);
3011 let t_e = fcx.expr_ty(&**e);
3013 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
3014 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
3016 if ty::type_is_error(t_e) {
3017 fcx.write_error(id);
3019 else if ty::type_is_bot(t_e) {
3023 match ty::get(t_1).sty {
3024 // This will be looked up later on
3025 _ if ty::type_is_trait(t_1) => {},
3028 if ty::type_is_nil(t_e) {
3029 fcx.type_error_message(expr.span, |actual| {
3030 format!("cast from nil: `{}` as `{}`",
3032 fcx.infcx().ty_to_str(t_1))
3034 } else if ty::type_is_nil(t_1) {
3035 fcx.type_error_message(expr.span, |actual| {
3036 format!("cast to nil: `{}` as `{}`",
3038 fcx.infcx().ty_to_str(t_1))
3042 let t1 = structurally_resolved_type(fcx, e.span, t_1);
3043 let te = structurally_resolved_type(fcx, e.span, t_e);
3044 let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
3045 let t_1_is_char = type_is_char(fcx, expr.span, t_1);
3046 let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
3047 let t_1_is_float = type_is_floating_point(fcx,
3051 // casts to scalars other than `char` and `bare fn` are trivial
3052 let t_1_is_trivial = t_1_is_scalar &&
3053 !t_1_is_char && !t_1_is_bare_fn;
3055 if type_is_c_like_enum(fcx, expr.span, t_e) &&
3058 fcx.type_error_message(expr.span, |actual| {
3059 format!("illegal cast; cast through an \
3060 integer first: `{}` as `{}`",
3062 fcx.infcx().ty_to_str(t_1))
3065 // casts from C-like enums are allowed
3066 } else if t_1_is_char {
3067 let te = fcx.infcx().resolve_type_vars_if_possible(te);
3068 if ty::get(te).sty != ty::ty_uint(ast::TyU8) {
3069 fcx.type_error_message(expr.span, |actual| {
3070 format!("only `u8` can be cast as \
3071 `char`, not `{}`", actual)
3074 } else if ty::get(t1).sty == ty::ty_bool {
3077 .span_err(expr.span,
3078 "cannot cast as `bool`, compare with \
3080 } else if type_is_region_ptr(fcx, expr.span, t_e) &&
3081 type_is_unsafe_ptr(fcx, expr.span, t_1) {
3083 fn is_vec(t: ty::t) -> bool {
3084 match ty::get(t).sty {
3085 ty::ty_vec(..) => true,
3086 ty::ty_ptr(ty::mt{ty: t, ..}) | ty::ty_rptr(_, ty::mt{ty: t, ..}) |
3087 ty::ty_box(t) | ty::ty_uniq(t) => match ty::get(t).sty {
3088 ty::ty_vec(_, None) => true,
3094 fn types_compatible(fcx: &FnCtxt, sp: Span,
3095 t1: ty::t, t2: ty::t) -> bool {
3099 let el = ty::sequence_element_type(fcx.tcx(),
3101 infer::mk_eqty(fcx.infcx(), false,
3102 infer::Misc(sp), el, t2).is_ok()
3106 // Due to the limitations of LLVM global constants,
3107 // region pointers end up pointing at copies of
3108 // vector elements instead of the original values.
3109 // To allow unsafe pointers to work correctly, we
3110 // need to special-case obtaining an unsafe pointer
3111 // from a region pointer to a vector.
3113 /* this cast is only allowed from &[T] to *T or
3115 match (&ty::get(te).sty, &ty::get(t_1).sty) {
3116 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
3117 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
3118 if types_compatible(fcx, e.span, mt1, mt2) => {
3119 /* this case is allowed */
3122 demand::coerce(fcx, e.span, t_1, &**e);
3125 } else if !(type_is_scalar(fcx,expr.span,t_e)
3126 && t_1_is_trivial) {
3128 If more type combinations should be supported than are
3129 supported here, then file an enhancement issue and
3130 record the issue number in this comment.
3132 fcx.type_error_message(expr.span, |actual| {
3133 format!("non-scalar cast: `{}` as `{}`",
3135 fcx.infcx().ty_to_str(t_1))
3140 fcx.write_ty(id, t_1);
3143 ast::ExprVec(ref args) => {
3144 let t: ty::t = fcx.infcx().next_ty_var();
3145 for e in args.iter() {
3146 check_expr_has_type(fcx, &**e, t);
3148 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3150 fcx.write_ty(id, typ);
3152 ast::ExprRepeat(ref element, ref count_expr) => {
3153 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3154 let count = ty::eval_repeat_count(fcx, &**count_expr);
3155 let t: ty::t = fcx.infcx().next_ty_var();
3156 check_expr_has_type(fcx, &**element, t);
3157 let element_ty = fcx.expr_ty(&**element);
3158 if ty::type_is_error(element_ty) {
3159 fcx.write_error(id);
3161 else if ty::type_is_bot(element_ty) {
3165 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3167 fcx.write_ty(id, t);
3170 ast::ExprTup(ref elts) => {
3171 let flds = unpack_expected(fcx, expected, |sty| {
3173 ty::ty_tup(ref flds) => Some((*flds).clone()),
3177 let mut bot_field = false;
3178 let mut err_field = false;
3180 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3181 let opt_hint = match flds {
3182 Some(ref fs) if i < fs.len() => Some(*fs.get(i)),
3185 check_expr_with_opt_hint(fcx, &**e, opt_hint);
3186 let t = fcx.expr_ty(&**e);
3187 err_field = err_field || ty::type_is_error(t);
3188 bot_field = bot_field || ty::type_is_bot(t);
3193 } else if err_field {
3194 fcx.write_error(id);
3196 let typ = ty::mk_tup(tcx, elt_ts);
3197 fcx.write_ty(id, typ);
3200 ast::ExprStruct(ref path, ref fields, base_expr) => {
3201 // Resolve the path.
3202 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3204 Some(def::DefStruct(type_def_id)) => {
3205 check_struct_constructor(fcx, id, expr.span, type_def_id,
3206 fields.as_slice(), base_expr);
3208 Some(def::DefVariant(enum_id, variant_id, _)) => {
3209 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3210 variant_id, fields.as_slice());
3213 tcx.sess.span_bug(path.span,
3214 "structure constructor does not name a structure type");
3218 ast::ExprField(ref base, ref field, ref tys) => {
3219 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3221 ast::ExprIndex(ref base, ref idx) => {
3222 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3223 check_expr(fcx, &**idx);
3224 let raw_base_t = fcx.expr_ty(&**base);
3225 let idx_t = fcx.expr_ty(&**idx);
3226 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3227 fcx.write_ty(id, raw_base_t);
3228 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3229 fcx.write_ty(id, idx_t);
3231 let (base_t, autoderefs, field_ty) =
3232 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3233 lvalue_pref, |base_t, _| ty::index(base_t));
3236 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3237 fcx.write_ty(id, mt.ty);
3238 fcx.write_autoderef_adjustment(base.id, autoderefs);
3241 let resolved = structurally_resolved_type(fcx,
3244 let ret_ty = lookup_op_method(fcx,
3247 token::intern("index"),
3248 tcx.lang_items.index_trait(),
3249 [base.clone(), idx.clone()],
3252 fcx.type_error_message(expr.span,
3254 format!("cannot index a \
3261 fcx.write_ty(id, ret_ty);
3268 debug!("type of expr({}) {} is...", expr.id,
3269 syntax::print::pprust::expr_to_str(expr));
3270 debug!("... {}, expected is {}",
3271 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3273 Some(t) => ppaux::ty_to_str(tcx, t),
3274 _ => "empty".to_string()
3280 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3281 if !type_is_uint(fcx, sp, t) {
3282 fcx.type_error_message(sp, |actual| {
3283 format!("mismatched types: expected `uint` type but found `{}`",
3289 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3290 if !type_is_integral(fcx, sp, t) {
3291 fcx.type_error_message(sp, |actual| {
3292 format!("mismatched types: expected integral type but found `{}`",
3298 pub fn check_decl_initializer(fcx: &FnCtxt,
3302 let local_ty = fcx.local_ty(init.span, nid);
3303 check_expr_coercable_to_type(fcx, init, local_ty)
3306 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3307 let tcx = fcx.ccx.tcx;
3309 let t = fcx.local_ty(local.span, local.id);
3310 fcx.write_ty(local.id, t);
3314 check_decl_initializer(fcx, local.id, &**init);
3315 let init_ty = fcx.expr_ty(&**init);
3316 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3317 fcx.write_ty(local.id, init_ty);
3323 let pcx = pat_ctxt {
3325 map: pat_id_map(&tcx.def_map, &*local.pat),
3327 _match::check_pat(&pcx, &*local.pat, t);
3328 let pat_ty = fcx.node_ty(local.pat.id);
3329 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3330 fcx.write_ty(local.id, pat_ty);
3334 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3336 let mut saw_bot = false;
3337 let mut saw_err = false;
3339 ast::StmtDecl(decl, id) => {
3342 ast::DeclLocal(ref l) => {
3343 check_decl_local(fcx, &**l);
3344 let l_t = fcx.node_ty(l.id);
3345 saw_bot = saw_bot || ty::type_is_bot(l_t);
3346 saw_err = saw_err || ty::type_is_error(l_t);
3348 ast::DeclItem(_) => {/* ignore for now */ }
3351 ast::StmtExpr(ref expr, id) => {
3353 // Check with expected type of ()
3354 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3355 let expr_ty = fcx.expr_ty(&**expr);
3356 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3357 saw_err = saw_err || ty::type_is_error(expr_ty);
3359 ast::StmtSemi(ref expr, id) => {
3361 check_expr(fcx, &**expr);
3362 let expr_ty = fcx.expr_ty(&**expr);
3363 saw_bot |= ty::type_is_bot(expr_ty);
3364 saw_err |= ty::type_is_error(expr_ty);
3366 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3369 fcx.write_bot(node_id);
3372 fcx.write_error(node_id);
3375 fcx.write_nil(node_id)
3379 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3380 check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
3381 let blkty = fcx.node_ty(blk.id);
3382 if ty::type_is_error(blkty) {
3383 fcx.write_error(blk.id);
3385 else if ty::type_is_bot(blkty) {
3386 fcx.write_bot(blk.id);
3389 let nilty = ty::mk_nil();
3390 demand::suptype(fcx, blk.span, nilty, blkty);
3394 pub fn check_block_with_expected(fcx: &FnCtxt,
3396 expected: Option<ty::t>) {
3398 let mut fcx_ps = fcx.ps.borrow_mut();
3399 let fn_style_state = fcx_ps.recurse(blk);
3400 replace(&mut *fcx_ps, fn_style_state)
3403 fcx.with_region_lb(blk.id, || {
3404 let mut warned = false;
3405 let mut last_was_bot = false;
3406 let mut any_bot = false;
3407 let mut any_err = false;
3408 for s in blk.stmts.iter() {
3409 check_stmt(fcx, &**s);
3410 let s_id = ast_util::stmt_id(&**s);
3411 let s_ty = fcx.node_ty(s_id);
3412 if last_was_bot && !warned && match s.node {
3413 ast::StmtDecl(decl, _) => {
3415 ast::DeclLocal(_) => true,
3419 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3425 .add_lint(UnreachableCode,
3428 "unreachable statement".to_string());
3431 if ty::type_is_bot(s_ty) {
3432 last_was_bot = true;
3434 any_bot = any_bot || ty::type_is_bot(s_ty);
3435 any_err = any_err || ty::type_is_error(s_ty);
3438 None => if any_err {
3439 fcx.write_error(blk.id);
3442 fcx.write_bot(blk.id);
3445 fcx.write_nil(blk.id);
3448 if any_bot && !warned {
3452 .add_lint(UnreachableCode,
3455 "unreachable expression".to_string());
3457 check_expr_with_opt_hint(fcx, &*e, expected);
3458 let ety = fcx.expr_ty(&*e);
3459 fcx.write_ty(blk.id, ety);
3461 fcx.write_error(blk.id);
3464 fcx.write_bot(blk.id);
3470 *fcx.ps.borrow_mut() = prev;
3473 pub fn check_const(ccx: &CrateCtxt,
3477 let inh = blank_inherited_fields(ccx);
3478 let rty = ty::node_id_to_type(ccx.tcx, id);
3479 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3480 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3481 check_const_with_ty(&fcx, sp, e, declty);
3484 pub fn check_const_with_ty(fcx: &FnCtxt,
3488 // Gather locals in statics (because of block expressions).
3489 // This is technically unnecessary because locals in static items are forbidden,
3490 // but prevents type checking from blowing up before const checking can properly
3492 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3495 let cty = fcx.expr_ty(e);
3496 demand::suptype(fcx, e.span, declty, cty);
3497 regionck::regionck_expr(fcx, e);
3498 writeback::resolve_type_vars_in_expr(fcx, e);
3501 /// Checks whether a type can be represented in memory. In particular, it
3502 /// identifies types that contain themselves without indirection through a
3503 /// pointer, which would mean their size is unbounded. This is different from
3504 /// the question of whether a type can be instantiated. See the definition of
3505 /// `check_instantiable`.
3506 pub fn check_representable(tcx: &ty::ctxt,
3508 item_id: ast::NodeId,
3509 designation: &str) -> bool {
3510 let rty = ty::node_id_to_type(tcx, item_id);
3512 // Check that it is possible to represent this type. This call identifies
3513 // (1) types that contain themselves and (2) types that contain a different
3514 // recursive type. It is only necessary to throw an error on those that
3515 // contain themselves. For case 2, there must be an inner type that will be
3516 // caught by case 1.
3517 match ty::is_type_representable(tcx, sp, rty) {
3518 ty::SelfRecursive => {
3520 sp, format!("illegal recursive {} type; \
3521 wrap the inner value in a box to make it representable",
3522 designation).as_slice());
3525 ty::Representable | ty::ContainsRecursive => (),
3530 /// Checks whether a type can be created without an instance of itself.
3531 /// This is similar but different from the question of whether a type
3532 /// can be represented. For example, the following type:
3534 /// enum foo { None, Some(foo) }
3536 /// is instantiable but is not representable. Similarly, the type
3538 /// enum foo { Some(@foo) }
3540 /// is representable, but not instantiable.
3541 pub fn check_instantiable(tcx: &ty::ctxt,
3543 item_id: ast::NodeId)
3545 let item_ty = ty::node_id_to_type(tcx, item_id);
3546 if !ty::is_instantiable(tcx, item_ty) {
3549 format!("this type cannot be instantiated without an \
3550 instance of itself; consider using \
3552 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3559 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3560 let t = ty::node_id_to_type(tcx, id);
3561 if ty::type_needs_subst(t) {
3562 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3565 match ty::get(t).sty {
3566 ty::ty_struct(did, ref substs) => {
3567 let fields = ty::lookup_struct_fields(tcx, did);
3568 if fields.is_empty() {
3569 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3572 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3573 if !fields.iter().all(
3574 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3575 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3578 if !ty::type_is_machine(e) {
3579 tcx.sess.span_err(sp, "SIMD vector element type should be \
3588 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3589 vs: &[ast::P<ast::Variant>]) {
3590 for &v in vs.iter() {
3592 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3593 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3594 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3595 let len = arg_tys.len();
3599 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3600 // Allow the last field in an enum to be unsized.
3601 // We want to do this so that we can support smart pointers.
3602 // A struct value with an unsized final field is itself
3603 // unsized and we must track this in the type system.
3604 if !ty::type_is_sized(ccx.tcx, *t) {
3608 args.get(i).ty.span,
3609 format!("type `{}` is dynamically sized. \
3610 dynamically sized types may only \
3611 appear as the final type in a \
3613 ppaux::ty_to_str(ccx.tcx,
3618 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3624 pub fn check_enum_variants(ccx: &CrateCtxt,
3626 vs: &[ast::P<ast::Variant>],
3629 fn disr_in_range(ccx: &CrateCtxt,
3631 disr: ty::Disr) -> bool {
3632 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3634 ast::TyU8 => disr as u8 as Disr == disr,
3635 ast::TyU16 => disr as u16 as Disr == disr,
3636 ast::TyU32 => disr as u32 as Disr == disr,
3637 ast::TyU64 => disr as u64 as Disr == disr,
3638 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3641 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3643 ast::TyI8 => disr as i8 as Disr == disr,
3644 ast::TyI16 => disr as i16 as Disr == disr,
3645 ast::TyI32 => disr as i32 as Disr == disr,
3646 ast::TyI64 => disr as i64 as Disr == disr,
3647 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3651 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3652 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3656 fn do_check(ccx: &CrateCtxt,
3657 vs: &[ast::P<ast::Variant>],
3659 hint: attr::ReprAttr)
3660 -> Vec<Rc<ty::VariantInfo>> {
3662 let rty = ty::node_id_to_type(ccx.tcx, id);
3663 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3664 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3665 let mut prev_disr_val: Option<ty::Disr> = None;
3667 for &v in vs.iter() {
3669 // If the discriminant value is specified explicitly in the enum check whether the
3670 // initialization expression is valid, otherwise use the last value plus one.
3671 let mut current_disr_val = match prev_disr_val {
3672 Some(prev_disr_val) => prev_disr_val + 1,
3673 None => ty::INITIAL_DISCRIMINANT_VALUE
3676 match v.node.disr_expr {
3678 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3680 let inh = blank_inherited_fields(ccx);
3681 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3682 let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
3683 check_const_with_ty(&fcx, e.span, &*e, declty);
3684 // check_expr (from check_const pass) doesn't guarantee
3685 // that the expression is in a form that eval_const_expr can
3686 // handle, so we may still get an internal compiler error
3688 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3689 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3690 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3692 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3698 format!("expected constant: {}",
3706 // Check for duplicate discriminant values
3707 if disr_vals.contains(¤t_disr_val) {
3708 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3710 // Check for unrepresentable discriminant values
3712 attr::ReprAny | attr::ReprExtern => (),
3713 attr::ReprInt(sp, ity) => {
3714 if !disr_in_range(ccx, ity, current_disr_val) {
3715 ccx.tcx.sess.span_err(v.span,
3716 "discriminant value outside specified type");
3717 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3721 disr_vals.push(current_disr_val);
3723 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3725 prev_disr_val = Some(current_disr_val);
3727 variants.push(variant_info);
3733 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3734 if hint != attr::ReprAny && vs.len() <= 1 {
3735 let msg = if vs.len() == 1 {
3736 "unsupported representation for univariant enum"
3738 "unsupported representation for zero-variant enum"
3740 ccx.tcx.sess.span_err(sp, msg)
3743 let variants = do_check(ccx, vs, id, hint);
3745 // cache so that ty::enum_variants won't repeat this work
3746 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3748 check_representable(ccx.tcx, sp, id, "enum");
3750 // Check that it is possible to instantiate this enum:
3752 // This *sounds* like the same that as representable, but it's
3753 // not. See def'n of `check_instantiable()` for details.
3754 check_instantiable(ccx.tcx, sp, id);
3757 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3758 lookup_def_ccx(fcx.ccx, sp, id)
3761 // Returns the type parameter count and the type for the given definition.
3762 pub fn ty_param_bounds_and_ty_for_def(fcx: &FnCtxt,
3765 -> ty_param_bounds_and_ty {
3767 def::DefArg(nid, _) | def::DefLocal(nid, _) |
3768 def::DefBinding(nid, _) => {
3769 let typ = fcx.local_ty(sp, nid);
3770 return no_params(typ);
3772 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
3773 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
3774 def::DefStruct(id) => {
3775 return ty::lookup_item_type(fcx.ccx.tcx, id);
3777 def::DefUpvar(_, inner, _, _) => {
3778 return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
3783 def::DefTyParam(..)=> {
3784 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3786 def::DefMod(..) | def::DefForeignMod(..) => {
3787 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3789 def::DefUse(..) => {
3790 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3792 def::DefRegion(..) => {
3793 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3795 def::DefTyParamBinder(..) => {
3796 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3798 def::DefLabel(..) => {
3799 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3801 def::DefSelfTy(..) => {
3802 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3804 def::DefMethod(..) => {
3805 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3810 // Instantiates the given path, which must refer to an item with the given
3811 // number of type parameters and type.
3812 pub fn instantiate_path(fcx: &FnCtxt,
3814 polytype: ty_param_bounds_and_ty,
3817 node_id: ast::NodeId) {
3818 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
3819 path.repr(fcx.tcx()),
3820 def.repr(fcx.tcx()),
3822 polytype.repr(fcx.tcx()));
3824 // We need to extract the type parameters supplied by the user in
3825 // the path `path`. Due to the current setup, this is a bit of a
3826 // tricky-process; the problem is that resolve only tells us the
3827 // end-point of the path resolution, and not the intermediate steps.
3828 // Luckily, we can (at least for now) deduce the intermediate steps
3829 // just from the end-point.
3831 // There are basically three cases to consider:
3833 // 1. Reference to a *type*, such as a struct or enum:
3835 // mod a { struct Foo<T> { ... } }
3837 // Because we don't allow types to be declared within one
3838 // another, a path that leads to a type will always look like
3839 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
3840 // that only the final segment can have type parameters, and
3841 // they are located in the TypeSpace.
3843 // *Note:* Generally speaking, references to types don't
3844 // actually pass through this function, but rather the
3845 // `ast_ty_to_ty` function in `astconv`. However, in the case
3846 // of struct patterns (and maybe literals) we do invoke
3847 // `instantiate_path` to get the general type of an instance of
3848 // a struct. (In these cases, there are actually no type
3849 // parameters permitted at present, but perhaps we will allow
3850 // them in the future.)
3852 // 1b. Reference to a enum variant or tuple-like struct:
3854 // struct foo<T>(...)
3855 // enum E<T> { foo(...) }
3857 // In these cases, the parameters are declared in the type
3860 // 2. Reference to a *fn item*:
3864 // In this case, the path will again always have the form
3865 // `a::b::foo::<T>` where only the final segment should have
3866 // type parameters. However, in this case, those parameters are
3867 // declared on a value, and hence are in the `FnSpace`.
3869 // 3. Reference to a *method*:
3871 // impl<A> SomeStruct<A> {
3875 // Here we can have a path like
3876 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
3877 // may appear in two places. The penultimate segment,
3878 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
3879 // final segment, `foo::<B>` contains parameters in fn space.
3881 // The first step then is to categorize the segments appropriately.
3883 assert!(path.segments.len() >= 1);
3884 let mut segment_spaces;
3886 // Case 1 and 1b. Reference to a *type* or *enum variant*.
3887 def::DefSelfTy(..) |
3888 def::DefStruct(..) |
3889 def::DefVariant(..) |
3890 def::DefTyParamBinder(..) |
3893 def::DefPrimTy(..) |
3894 def::DefTyParam(..) => {
3895 // Everything but the final segment should have no
3896 // parameters at all.
3897 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
3898 segment_spaces.push(Some(subst::TypeSpace));
3901 // Case 2. Reference to a top-level value.
3903 def::DefStatic(..) => {
3904 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
3905 segment_spaces.push(Some(subst::FnSpace));
3908 // Case 3. Reference to a method.
3909 def::DefStaticMethod(..) => {
3910 assert!(path.segments.len() >= 2);
3911 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
3912 segment_spaces.push(Some(subst::TypeSpace));
3913 segment_spaces.push(Some(subst::FnSpace));
3916 // Other cases. Various nonsense that really shouldn't show up
3917 // here. If they do, an error will have been reported
3918 // elsewhere. (I hope)
3920 def::DefForeignMod(..) |
3923 def::DefMethod(..) |
3924 def::DefBinding(..) |
3926 def::DefRegion(..) |
3928 def::DefUpvar(..) => {
3929 segment_spaces = Vec::from_elem(path.segments.len(), None);
3932 assert_eq!(segment_spaces.len(), path.segments.len());
3934 debug!("segment_spaces={}", segment_spaces);
3936 // Next, examine the definition, and determine how many type
3937 // parameters we expect from each space.
3938 let type_defs = &polytype.generics.types;
3939 let region_defs = &polytype.generics.regions;
3941 // Now that we have categorized what space the parameters for each
3942 // segment belong to, let's sort out the parameters that the user
3943 // provided (if any) into their appropriate spaces. We'll also report
3944 // errors if type parameters are provided in an inappropriate place.
3945 let mut substs = Substs::empty();
3946 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
3949 report_error_if_segment_contains_type_parameters(fcx, segment);
3953 push_explicit_parameters_from_segment_to_substs(fcx,
3963 // Now we have to compare the types that the user *actually*
3964 // provided against the types that were *expected*. If the user
3965 // did not provide any types, then we want to substitute inference
3966 // variables. If the user provided some types, we may still need
3967 // to add defaults. If the user provided *too many* types, that's
3969 for &space in ParamSpace::all().iter() {
3970 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
3971 assert_eq!(substs.types.get_vec(space).len(),
3972 type_defs.get_vec(space).len());
3974 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
3975 assert_eq!(substs.regions().get_vec(space).len(),
3976 region_defs.get_vec(space).len());
3979 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
3983 fn report_error_if_segment_contains_type_parameters(
3985 segment: &ast::PathSegment)
3987 for typ in segment.types.iter() {
3988 fcx.tcx().sess.span_err(
3990 "type parameters may not appear here");
3994 for lifetime in segment.lifetimes.iter() {
3995 fcx.tcx().sess.span_err(
3997 "lifetime parameters may not appear here");
4002 fn push_explicit_parameters_from_segment_to_substs(
4004 space: subst::ParamSpace,
4005 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4006 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4007 segment: &ast::PathSegment,
4008 substs: &mut Substs)
4011 * Finds the parameters that the user provided and adds them
4012 * to `substs`. If too many parameters are provided, then
4013 * reports an error and clears the output vector.
4015 * We clear the output vector because that will cause the
4016 * `adjust_XXX_parameters()` later to use inference
4017 * variables. This seems less likely to lead to derived
4020 * Note that we *do not* check for *too few* parameters here.
4021 * Due to the presence of defaults etc that is more
4022 * complicated. I wanted however to do the reporting of *too
4023 * many* parameters here because we can easily use the precise
4024 * span of the N+1'th parameter.
4028 let type_count = type_defs.get_vec(space).len();
4029 assert_eq!(substs.types.get_vec(space).len(), 0);
4030 for (i, &typ) in segment.types.iter().enumerate() {
4031 let t = fcx.to_ty(&*typ);
4033 substs.types.push(space, t);
4034 } else if i == type_count {
4035 fcx.tcx().sess.span_err(
4038 "too many type parameters provided: \
4039 expected at most {} parameter(s) \
4040 but found {} parameter(s)",
4042 segment.types.len()).as_slice());
4043 substs.types.get_mut_vec(space).truncate(0);
4049 let region_count = region_defs.get_vec(space).len();
4050 assert_eq!(substs.regions().get_vec(space).len(), 0);
4051 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4052 let r = ast_region_to_region(fcx.tcx(), lifetime);
4053 if i < region_count {
4054 substs.mut_regions().push(space, r);
4055 } else if i == region_count {
4056 fcx.tcx().sess.span_err(
4059 "too many lifetime parameters provided: \
4060 expected {} parameter(s) but found {} parameter(s)",
4062 segment.lifetimes.len()).as_slice());
4063 substs.mut_regions().get_mut_vec(space).truncate(0);
4069 fn adjust_type_parameters(
4073 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4074 substs: &mut Substs)
4076 let provided_len = substs.types.get_vec(space).len();
4077 let desired = defs.get_vec(space).as_slice();
4078 let required_len = desired.iter()
4079 .take_while(|d| d.default.is_none())
4082 debug!("adjust_type_parameters(space={}, \
4091 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4092 assert!(provided_len <= desired.len());
4094 // Nothing specified at all: supply inference variables for
4096 if provided_len == 0 {
4097 let provided = substs.types.get_mut_vec(space);
4098 *provided = fcx.infcx().next_ty_vars(desired.len());
4102 // Too few parameters specified: report an error and use Err
4104 if provided_len < required_len {
4106 if desired.len() != required_len { "at least " } else { "" };
4107 fcx.tcx().sess.span_err(
4109 format!("too few type parameters provided: \
4110 expected {}{} parameter(s) \
4111 but found {} parameter(s)",
4114 provided_len).as_slice());
4115 let provided = substs.types.get_mut_vec(space);
4116 *provided = Vec::from_elem(desired.len(), ty::mk_err());
4120 // Otherwise, add in any optional parameters that the user
4121 // omitted. The case of *too many* parameters is handled
4123 // push_explicit_parameters_from_segment_to_substs(). Note
4124 // that the *default* type are expressed in terms of all prior
4125 // parameters, so we have to substitute as we go with the
4126 // partial substitution that we have built up.
4127 for i in range(provided_len, desired.len()) {
4128 let default = desired[i].default.unwrap();
4129 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4130 substs.types.push(space, default);
4132 assert_eq!(substs.types.get_vec(space).len(), desired.len());
4134 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4137 fn adjust_region_parameters(
4141 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4142 substs: &mut Substs)
4144 let provided = substs.mut_regions().get_mut_vec(space);
4145 let desired = defs.get_vec(space);
4147 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4148 assert!(provided.len() <= desired.len());
4150 // If nothing was provided, just use inference variables.
4151 if provided.len() == 0 {
4152 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4156 // If just the right number were provided, everybody is happy.
4157 if provided.len() == desired.len() {
4161 // Otherwise, too few were provided. Report an error and then
4162 // use inference variables.
4163 fcx.tcx().sess.span_err(
4166 "too few lifetime parameters provided: \
4167 expected {} parameter(s) \
4168 but found {} parameter(s)",
4170 provided.len()).as_slice());
4172 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4176 // Resolves `typ` by a single level if `typ` is a type variable. If no
4177 // resolution is possible, then an error is reported.
4178 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4179 match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
4180 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4182 fcx.type_error_message(sp, |_actual| {
4183 "the type of this value must be known in this \
4184 context".to_string()
4186 demand::suptype(fcx, sp, ty::mk_err(), tp);
4192 // Returns the one-level-deep structure of the given type.
4193 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4195 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4198 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4199 let typ_s = structurally_resolved_type(fcx, sp, typ);
4200 return ty::type_is_integral(typ_s);
4203 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4204 let typ_s = structurally_resolved_type(fcx, sp, typ);
4205 return ty::type_is_uint(typ_s);
4208 pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4209 let typ_s = structurally_resolved_type(fcx, sp, typ);
4210 return ty::type_is_scalar(typ_s);
4213 pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4214 let typ_s = structurally_resolved_type(fcx, sp, typ);
4215 return ty::type_is_char(typ_s);
4218 pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4219 let typ_s = structurally_resolved_type(fcx, sp, typ);
4220 return ty::type_is_bare_fn(typ_s);
4223 pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4224 let typ_s = structurally_resolved_type(fcx, sp, typ);
4225 return ty::type_is_floating_point(typ_s);
4228 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4229 let typ_s = structurally_resolved_type(fcx, sp, typ);
4230 return ty::type_is_unsafe_ptr(typ_s);
4233 pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4234 let typ_s = structurally_resolved_type(fcx, sp, typ);
4235 return ty::type_is_region_ptr(typ_s);
4238 pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4239 let typ_s = structurally_resolved_type(fcx, sp, typ);
4240 return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
4243 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4246 mk_inner: || -> ty::mt)
4249 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4250 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4252 ast::ExprLit(..) => {
4253 // string literals and *empty slices* live in static memory
4254 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4256 ast::ExprVec(ref elements) if elements.len() == 0 => {
4257 // string literals and *empty slices* live in static memory
4258 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4260 ast::ExprRepeat(..) |
4261 ast::ExprVec(..) => {
4262 // vector literals are temporaries on the stack
4263 match fcx.tcx().region_maps.temporary_scope(e.id) {
4264 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4265 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4269 fcx.ccx.tcx.sess.span_bug(e.span,
4270 "vstore with unexpected \
4278 // Returns true if b contains a break that can exit from b
4279 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4280 // First: is there an unlabeled break immediately
4282 (loop_query(&*b, |e| {
4284 ast::ExprBreak(_) => true,
4288 // Second: is there a labeled break with label
4289 // <id> nested anywhere inside the loop?
4290 (block_query(b, |e| {
4292 ast::ExprBreak(Some(_)) => {
4293 match cx.def_map.borrow().find(&e.id) {
4294 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4302 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4304 tps: &OwnedSlice<ast::TyParam>,
4306 debug!("check_bounds_are_used(n_tps={}, ty={})",
4307 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4309 // make a vector of booleans initially false, set to true when used
4310 if tps.len() == 0u { return; }
4311 let mut tps_used = Vec::from_elem(tps.len(), false);
4313 ty::walk_ty(ty, |t| {
4314 match ty::get(t).sty {
4315 ty::ty_param(ParamTy {idx, ..}) => {
4316 debug!("Found use of ty param num {}", idx);
4317 *tps_used.get_mut(idx) = true;
4323 for (i, b) in tps_used.iter().enumerate() {
4325 ccx.tcx.sess.span_err(
4327 format!("type parameter `{}` is unused",
4328 token::get_ident(tps.get(i).ident)).as_slice());
4333 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4334 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4335 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4339 let name = token::get_ident(it.ident);
4340 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4341 let split : Vec<&str> = name.get().split('_').collect();
4342 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4344 //We only care about the operation here
4345 match *split.get(1) {
4346 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4350 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4352 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4355 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4356 "min" | "umax" | "umin" => {
4357 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4361 (0, Vec::new(), ty::mk_nil())
4364 tcx.sess.span_err(it.span,
4365 format!("unrecognized atomic operation \
4374 "abort" => (0, Vec::new(), ty::mk_bot()),
4375 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4377 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4378 "init" => (1u, Vec::new(), param(ccx, 0u)),
4379 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4380 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4381 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4382 "move_val_init" => {
4385 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4390 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4391 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4394 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4396 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4398 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4400 mutbl: ast::MutImmutable
4402 (1u, Vec::new(), td_ptr)
4405 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4409 ty::mk_struct(ccx.tcx, did,
4410 subst::Substs::empty())),
4412 tcx.sess.span_fatal(it.span, msg.as_slice());
4417 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4419 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4421 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4422 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4423 Ok((_, vot)) => vot,
4424 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4427 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4429 mutbl: ast::MutImmutable
4431 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4436 ty::mk_ptr(tcx, ty::mt {
4438 mutbl: ast::MutImmutable
4442 ty::mk_ptr(tcx, ty::mt {
4444 mutbl: ast::MutImmutable
4447 "copy_memory" | "copy_nonoverlapping_memory" |
4448 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4451 ty::mk_ptr(tcx, ty::mt {
4453 mutbl: ast::MutMutable
4455 ty::mk_ptr(tcx, ty::mt {
4457 mutbl: ast::MutImmutable
4463 "set_memory" | "volatile_set_memory" => {
4466 ty::mk_ptr(tcx, ty::mt {
4468 mutbl: ast::MutMutable
4475 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4476 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4479 vec!( ty::mk_f32(), ty::mk_i32() ),
4484 vec!( ty::mk_f64(), ty::mk_i32() ),
4487 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4488 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4489 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4490 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4493 vec!( ty::mk_f32(), ty::mk_f32() ),
4498 vec!( ty::mk_f64(), ty::mk_f64() ),
4501 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4502 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4503 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4504 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4505 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4506 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4507 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4508 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4509 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4510 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4513 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4518 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4521 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4522 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4523 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4524 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4525 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4526 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4527 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4528 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4529 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4530 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4531 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4532 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4533 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4534 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4535 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4536 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4537 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4538 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4539 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4540 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4541 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4542 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4543 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4544 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4545 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4546 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4547 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4548 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4549 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4550 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4551 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4554 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4556 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4558 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4559 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4560 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4562 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4563 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4564 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4566 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4567 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4568 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4570 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4571 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4572 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4574 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4575 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4576 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4578 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4579 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4580 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4582 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4583 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4584 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4586 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4587 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4588 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4591 tcx.sess.span_err(it.span,
4592 format!("unrecognized intrinsic function: `{}`",
4593 *other).as_slice());
4598 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4599 fn_style: ast::UnsafeFn,
4600 abi: abi::RustIntrinsic,
4608 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4609 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4610 if i_n_tps != n_tps {
4611 tcx.sess.span_err(it.span,
4612 format!("intrinsic has wrong number of type \
4613 parameters: found {}, expected {}",
4617 require_same_types(tcx,
4624 format!("intrinsic has wrong type: expected `{}`",
4625 ppaux::ty_to_str(ccx.tcx, fty))