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::{Polytype};
89 use middle::ty::{ParamTy, Disr, ExprTyProvider};
91 use middle::ty_fold::TypeFolder;
92 use middle::typeck::astconv::AstConv;
93 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
94 use middle::typeck::astconv;
95 use middle::typeck::check::_match::pat_ctxt;
96 use middle::typeck::check::method::{AutoderefReceiver};
97 use middle::typeck::check::method::{AutoderefReceiverFlag};
98 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
99 use middle::typeck::check::method::{DontAutoderefReceiver};
100 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
101 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
102 use middle::typeck::check::regionmanip::relate_free_regions;
103 use middle::typeck::check::vtable::VtableContext;
104 use middle::typeck::CrateCtxt;
105 use middle::typeck::infer::{resolve_type, force_tvar};
106 use middle::typeck::infer;
107 use middle::typeck::rscope::RegionScope;
108 use middle::typeck::{lookup_def_ccx};
109 use middle::typeck::no_params;
110 use middle::typeck::{require_same_types, vtable_map};
111 use middle::typeck::{MethodCall, MethodMap};
112 use middle::typeck::{TypeAndSubsts};
113 use middle::lang_items::TypeIdLangItem;
114 use util::common::{block_query, indenter, loop_query};
116 use util::ppaux::{UserString, Repr};
117 use util::nodemap::{FnvHashMap, NodeMap};
119 use std::cell::{Cell, RefCell};
120 use std::collections::HashMap;
121 use std::mem::replace;
125 use syntax::ast::{Provided, Required};
128 use syntax::ast_util::local_def;
129 use syntax::ast_util;
131 use syntax::codemap::Span;
133 use syntax::owned_slice::OwnedSlice;
134 use syntax::parse::token;
135 use syntax::print::pprust;
137 use syntax::visit::Visitor;
148 /// Fields that are part of a `FnCtxt` which are inherited by
149 /// closures defined within the function. For example:
152 /// bar(proc() { ... })
155 /// Here, the function `foo()` and the closure passed to
156 /// `bar()` will each have their own `FnCtxt`, but they will
157 /// share the inherited fields.
158 pub struct Inherited<'a> {
159 infcx: infer::InferCtxt<'a>,
160 locals: RefCell<NodeMap<ty::t>>,
161 param_env: ty::ParameterEnvironment,
164 node_types: RefCell<NodeMap<ty::t>>,
165 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
166 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
167 method_map: MethodMap,
168 vtable_map: vtable_map,
169 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
173 pub struct FnStyleState {
174 pub def: ast::NodeId,
175 pub fn_style: ast::FnStyle,
180 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
181 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
184 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
185 match self.fn_style {
186 // If this unsafe, then if the outer function was already marked as
187 // unsafe we shouldn't attribute the unsafe'ness to the block. This
188 // way the block can be warned about instead of ignoring this
189 // extraneous block (functions are never warned about).
190 ast::UnsafeFn if self.from_fn => *self,
193 let (fn_style, def) = match blk.rules {
194 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
195 ast::DefaultBlock => (fn_style, self.def),
197 FnStyleState{ def: def,
205 /// Whether `check_binop` is part of an assignment or not.
206 /// Used to know whether we allow user overloads and to print
207 /// better messages on error.
208 #[deriving(PartialEq)]
209 enum IsBinopAssignment{
215 pub struct FnCtxt<'a> {
216 // This flag is set to true if, during the writeback phase, we encounter
217 // a type error in this function.
218 writeback_errors: Cell<bool>,
220 // Number of errors that had been reported when we started
221 // checking this function. On exit, if we find that *more* errors
222 // have been reported, we will skip regionck and other work that
223 // expects the types within the function to be consistent.
224 err_count_on_creation: uint,
227 ps: RefCell<FnStyleState>,
229 // Sometimes we generate region pointers where the precise region
230 // to use is not known. For example, an expression like `&x.f`
231 // where `x` is of type `@T`: in this case, we will be rooting
232 // `x` onto the stack frame, and we could choose to root it until
233 // the end of (almost) any enclosing block or expression. We
234 // want to pick the narrowest block that encompasses all uses.
236 // What we do in such cases is to generate a region variable with
237 // `region_lb` as a lower bound. The regionck pass then adds
238 // other constraints based on how the variable is used and region
239 // inference selects the ultimate value. Finally, borrowck is
240 // charged with guaranteeing that the value whose address was taken
241 // can actually be made to live as long as it needs to live.
242 region_lb: Cell<ast::NodeId>,
244 inh: &'a Inherited<'a>,
246 ccx: &'a CrateCtxt<'a>,
249 impl<'a> Inherited<'a> {
250 fn new(tcx: &'a ty::ctxt,
251 param_env: ty::ParameterEnvironment)
254 infcx: infer::new_infer_ctxt(tcx),
255 locals: RefCell::new(NodeMap::new()),
256 param_env: param_env,
257 node_types: RefCell::new(NodeMap::new()),
258 item_substs: RefCell::new(NodeMap::new()),
259 adjustments: RefCell::new(NodeMap::new()),
260 method_map: RefCell::new(FnvHashMap::new()),
261 vtable_map: RefCell::new(FnvHashMap::new()),
262 upvar_borrow_map: RefCell::new(HashMap::new()),
267 // Used by check_const and check_enum_variants
268 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
269 inh: &'a Inherited<'a>,
271 region_bnd: ast::NodeId)
274 writeback_errors: Cell::new(false),
275 err_count_on_creation: ccx.tcx.sess.err_count(),
277 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
278 region_lb: Cell::new(region_bnd),
284 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
285 // It's kind of a kludge to manufacture a fake function context
286 // and statement context, but we might as well do write the code only once
287 let param_env = ty::ParameterEnvironment {
288 free_substs: subst::Substs::empty(),
289 bounds: subst::VecPerParamSpace::empty()
291 Inherited::new(ccx.tcx, param_env)
294 impl<'a> ExprTyProvider for FnCtxt<'a> {
295 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
299 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
304 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
306 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
307 fn visit_item(&mut self, i: &ast::Item, _: ()) {
308 check_item(self.ccx, i);
309 visit::walk_item(self, i, ());
313 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
315 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
316 fn visit_item(&mut self, i: &ast::Item, _: ()) {
317 check_item_sized(self.ccx, i);
318 visit::walk_item(self, i, ());
322 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
323 let mut visit = CheckItemTypesVisitor { ccx: ccx };
324 visit::walk_crate(&mut visit, krate, ());
326 ccx.tcx.sess.abort_if_errors();
328 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
329 visit::walk_crate(&mut visit, krate, ());
332 fn check_bare_fn(ccx: &CrateCtxt,
337 param_env: ty::ParameterEnvironment) {
338 // Compute the fty from point of view of inside fn
339 // (replace any type-scheme with a type)
340 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
342 match ty::get(fty).sty {
343 ty::ty_bare_fn(ref fn_ty) => {
344 let inh = Inherited::new(ccx.tcx, param_env);
345 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
346 decl, id, body, &inh);
348 vtable::resolve_in_block(&fcx, body);
349 regionck::regionck_fn(&fcx, body);
350 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
352 _ => ccx.tcx.sess.impossible_case(body.span,
353 "check_bare_fn: function type expected")
357 struct GatherLocalsVisitor<'a> {
361 impl<'a> GatherLocalsVisitor<'a> {
362 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
365 // infer the variable's type
366 let var_id = self.fcx.infcx().next_ty_var_id();
367 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
368 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
371 // take type that the user specified
372 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
378 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
379 // Add explicitly-declared locals.
380 fn visit_local(&mut self, local: &ast::Local, _: ()) {
381 let o_ty = match local.ty.node {
382 ast::TyInfer => None,
383 _ => Some(self.fcx.to_ty(&*local.ty))
385 self.assign(local.id, o_ty);
386 debug!("Local variable {} is assigned type {}",
387 self.fcx.pat_to_str(&*local.pat),
388 self.fcx.infcx().ty_to_str(
389 self.fcx.inh.locals.borrow().get_copy(&local.id)));
390 visit::walk_local(self, local, ());
393 // Add pattern bindings.
394 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
396 ast::PatIdent(_, ref path, _)
397 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
398 self.assign(p.id, None);
399 debug!("Pattern binding {} is assigned to {}",
400 token::get_ident(path.segments.get(0).identifier),
401 self.fcx.infcx().ty_to_str(
402 self.fcx.inh.locals.borrow().get_copy(&p.id)));
406 visit::walk_pat(self, p, ());
410 fn visit_block(&mut self, b: &ast::Block, _: ()) {
411 // non-obvious: the `blk` variable maps to region lb, so
412 // we have to keep this up-to-date. This
413 // is... unfortunate. It'd be nice to not need this.
414 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
417 // Don't descend into fns and items
418 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
419 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
420 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
424 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
425 fn_style: ast::FnStyle,
430 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
433 * Helper used by check_bare_fn and check_expr_fn. Does the
434 * grungy work of checking a function body and returns the
435 * function context used for that purpose, since in the case of a
436 * fn item there is still a bit more to do.
439 * - inherited: other fields inherited from the enclosing fn (if any)
443 let err_count_on_creation = tcx.sess.err_count();
445 // First, we have to replace any bound regions in the fn type with free ones.
446 // The free region references will be bound the node_id of the body block.
447 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
448 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
451 relate_free_regions(tcx, &fn_sig);
453 let arg_tys = fn_sig.inputs.as_slice();
454 let ret_ty = fn_sig.output;
456 debug!("check_fn(arg_tys={}, ret_ty={})",
460 // Create the function context. This is either derived from scratch or,
461 // in the case of function expressions, based on the outer context.
463 writeback_errors: Cell::new(false),
464 err_count_on_creation: err_count_on_creation,
466 ps: RefCell::new(FnStyleState::function(fn_style, id)),
467 region_lb: Cell::new(body.id),
474 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
475 // Add formal parameters.
476 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
477 // Create type variables for each argument.
478 pat_util::pat_bindings(&tcx.def_map,
480 |_bm, pat_id, _sp, _path| {
481 visit.assign(pat_id, None);
484 // Check the pattern.
487 map: pat_id_map(&tcx.def_map, &*input.pat),
489 _match::check_pat(&pcx, &*input.pat, *arg_ty);
492 visit.visit_block(body, ());
495 check_block_with_expected(&fcx, body, Some(ret_ty));
497 // We unify the tail expr's type with the
498 // function result type, if there is a tail expr.
500 Some(ref tail_expr) => {
501 // Special case: we print a special error if there appears
502 // to be do-block/for-loop confusion
503 demand::suptype_with_fn(&fcx, tail_expr.span, false,
504 fcx.ret_ty, fcx.expr_ty(&**tail_expr),
506 fcx.report_mismatched_return_types(sp, e, a, s);
512 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
513 fcx.write_ty(input.id, *arg);
519 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
520 assert!(field.id.krate == ast::LOCAL_CRATE);
521 let item = match tcx.map.find(struct_id.node) {
522 Some(ast_map::NodeItem(item)) => item,
523 None => fail!("node not in ast map: {}", struct_id.node),
524 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
528 ast::ItemStruct(struct_def, _) => {
529 match struct_def.fields.iter().find(|f| match f.node.kind {
530 ast::NamedField(ident, _) => ident.name == field.name,
536 .bug(format!("Could not find field {}",
537 token::get_name(field.name)).as_slice())
541 _ => tcx.sess.bug("Field found outside of a struct?"),
545 // Check struct fields are uniquely named wrt parents.
546 fn check_for_field_shadowing(tcx: &ty::ctxt,
548 let struct_fields = tcx.struct_fields.borrow();
549 let fields = struct_fields.get(&id);
551 let superstructs = tcx.superstructs.borrow();
552 let super_struct = superstructs.get(&id);
553 match *super_struct {
555 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
556 for f in fields.iter() {
557 match super_fields.iter().find(|sf| f.name == sf.name) {
558 Some(prev_field) => {
559 tcx.sess.span_err(span_for_field(tcx, f, id),
560 format!("field `{}` hides field declared in \
562 token::get_name(f.name)).as_slice());
563 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
564 "previously declared here");
574 fn check_fields_sized(tcx: &ty::ctxt,
575 struct_def: &ast::StructDef) {
576 let len = struct_def.fields.len();
580 for f in struct_def.fields.slice_to(len - 1).iter() {
581 let t = ty::node_id_to_type(tcx, f.node.id);
582 if !ty::type_is_sized(tcx, t) {
584 ast::NamedField(ident, _) => {
587 format!("type `{}` is dynamically sized. \
588 dynamically sized types may only \
589 appear as the type of the final \
591 token::get_ident(ident)).as_slice());
593 ast::UnnamedField(_) => {
594 tcx.sess.span_err(f.span, "dynamically sized type in field");
601 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
604 check_representable(tcx, span, id, "struct");
605 check_instantiable(tcx, span, id);
607 // Check there are no overlapping fields in super-structs
608 check_for_field_shadowing(tcx, local_def(id));
610 if ty::lookup_simd(tcx, local_def(id)) {
611 check_simd(tcx, span, id);
615 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
616 debug!("check_item(it.id={}, it.ident={})",
618 ty::item_path_str(ccx.tcx, local_def(it.id)));
619 let _indenter = indenter();
622 ast::ItemEnum(ref enum_definition, _) => {
623 check_enum_variants_sized(ccx,
624 enum_definition.variants.as_slice());
626 ast::ItemStruct(..) => {
627 check_fields_sized(ccx.tcx, &*ccx.tcx.map.expect_struct(it.id));
633 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
634 debug!("check_item(it.id={}, it.ident={})",
636 ty::item_path_str(ccx.tcx, local_def(it.id)));
637 let _indenter = indenter();
640 ast::ItemStatic(_, _, ref e) => check_const(ccx, it.span, &**e, it.id),
641 ast::ItemEnum(ref enum_definition, _) => {
642 check_enum_variants(ccx,
644 enum_definition.variants.as_slice(),
647 ast::ItemFn(ref decl, _, _, _, ref body) => {
648 let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
650 let param_env = ty::construct_parameter_environment(ccx.tcx,
654 check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
656 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
657 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
659 let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
661 check_method_body(ccx, &impl_pty.generics, &**m);
664 match *opt_trait_ref {
665 Some(ref ast_trait_ref) => {
667 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
668 check_impl_methods_against_trait(ccx,
673 vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
679 ast::ItemTrait(_, _, _, ref trait_methods) => {
680 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
681 for trait_method in (*trait_methods).iter() {
682 match *trait_method {
684 // Nothing to do, since required methods don't have
688 check_method_body(ccx, &trait_def.generics, &*m);
693 ast::ItemStruct(..) => {
694 check_struct(ccx, it.id, it.span);
696 ast::ItemTy(ref t, ref generics) => {
697 let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
698 check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
700 ast::ItemForeignMod(ref m) => {
701 if m.abi == abi::RustIntrinsic {
702 for item in m.items.iter() {
703 check_intrinsic_type(ccx, &**item);
706 for item in m.items.iter() {
707 let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
708 if !pty.generics.types.is_empty() {
709 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
713 ast::ForeignItemFn(ref fn_decl, _) => {
714 if fn_decl.variadic && m.abi != abi::C {
715 ccx.tcx.sess.span_err(
716 item.span, "variadic function must have C calling convention");
724 _ => {/* nothing to do */ }
728 fn check_method_body(ccx: &CrateCtxt,
729 item_generics: &ty::Generics,
730 method: &ast::Method) {
732 * Type checks a method body.
735 * - `item_generics`: generics defined on the impl/trait that contains
737 * - `self_bound`: bound for the `Self` type parameter, if any
738 * - `method`: the method definition
741 debug!("check_method_body(item_generics={}, method.id={})",
742 item_generics.repr(ccx.tcx),
744 let method_def_id = local_def(method.id);
745 let method_ty = ty::method(ccx.tcx, method_def_id);
746 let method_generics = &method_ty.generics;
748 let param_env = ty::construct_parameter_environment(ccx.tcx,
752 let fty = ty::node_id_to_type(ccx.tcx, method.id);
754 check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
757 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
759 ast_trait_ref: &ast::TraitRef,
760 impl_trait_ref: &ty::TraitRef,
761 impl_methods: &[Gc<ast::Method>]) {
762 // Locate trait methods
764 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
766 // Check existing impl methods to see if they are both present in trait
767 // and compatible with trait signature
768 for impl_method in impl_methods.iter() {
769 let impl_method_def_id = local_def(impl_method.id);
770 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
772 // If this is an impl of a trait method, find the corresponding
773 // method definition in the trait.
774 let opt_trait_method_ty =
775 trait_methods.iter().
776 find(|tm| tm.ident.name == impl_method_ty.ident.name);
777 match opt_trait_method_ty {
778 Some(trait_method_ty) => {
779 compare_impl_method(ccx.tcx,
784 &impl_trait_ref.substs);
787 // This is span_bug as it should have already been caught in resolve.
791 "method `{}` is not a member of trait `{}`",
792 token::get_ident(impl_method_ty.ident),
793 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
798 // Check for missing methods from trait
799 let provided_methods = ty::provided_trait_methods(tcx,
800 impl_trait_ref.def_id);
801 let mut missing_methods = Vec::new();
802 for trait_method in trait_methods.iter() {
804 impl_methods.iter().any(
805 |m| m.ident.name == trait_method.ident.name);
807 provided_methods.iter().any(
808 |m| m.ident.name == trait_method.ident.name);
809 if !is_implemented && !is_provided {
810 missing_methods.push(
811 format!("`{}`", token::get_ident(trait_method.ident)));
815 if !missing_methods.is_empty() {
818 format!("not all trait methods implemented, missing: {}",
819 missing_methods.connect(", ")).as_slice());
824 * Checks that a method from an impl/class conforms to the signature of
825 * the same method as declared in the trait.
829 * - impl_generics: the generics declared on the impl itself (not the method!)
830 * - impl_m: type of the method we are checking
831 * - impl_m_span: span to use for reporting errors
832 * - impl_m_body_id: id of the method body
833 * - trait_m: the method in the trait
834 * - trait_to_impl_substs: the substitutions used on the type of the trait
836 fn compare_impl_method(tcx: &ty::ctxt,
839 impl_m_body_id: ast::NodeId,
840 trait_m: &ty::Method,
841 trait_to_impl_substs: &subst::Substs) {
842 debug!("compare_impl_method()");
843 let infcx = infer::new_infer_ctxt(tcx);
845 // Try to give more informative error messages about self typing
846 // mismatches. Note that any mismatch will also be detected
847 // below, where we construct a canonical function type that
848 // includes the self parameter as a normal parameter. It's just
849 // that the error messages you get out of this code are a bit more
850 // inscrutable, particularly for cases where one method has no
852 match (&trait_m.explicit_self, &impl_m.explicit_self) {
853 (&ast::SelfStatic, &ast::SelfStatic) => {}
854 (&ast::SelfStatic, _) => {
857 format!("method `{}` has a `{}` declaration in the impl, \
858 but not in the trait",
859 token::get_ident(trait_m.ident),
860 pprust::explicit_self_to_str(
861 impl_m.explicit_self)).as_slice());
864 (_, &ast::SelfStatic) => {
867 format!("method `{}` has a `{}` declaration in the trait, \
868 but not in the impl",
869 token::get_ident(trait_m.ident),
870 pprust::explicit_self_to_str(
871 trait_m.explicit_self)).as_slice());
875 // Let the type checker catch other errors below
879 let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
880 let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
881 if num_impl_m_type_params != num_trait_m_type_params {
884 format!("method `{}` has {} type parameter{} \
885 but its trait declaration has {} type parameter{}",
886 token::get_ident(trait_m.ident),
887 num_impl_m_type_params,
888 if num_impl_m_type_params == 1 {""} else {"s"},
889 num_trait_m_type_params,
890 if num_trait_m_type_params == 1 {""} else {"s"}).as_slice());
894 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
897 format!("method `{}` has {} parameter{} \
898 but the declaration in trait `{}` has {}",
899 token::get_ident(trait_m.ident),
900 impl_m.fty.sig.inputs.len(),
901 if impl_m.fty.sig.inputs.len() == 1 {""} else {"s"},
902 ty::item_path_str(tcx, trait_m.def_id),
903 trait_m.fty.sig.inputs.len()).as_slice());
907 let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
908 .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
910 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
911 // Check that the impl does not require any builtin-bounds
912 // that the trait does not guarantee:
914 impl_param_def.bounds.builtin_bounds -
915 trait_param_def.bounds.builtin_bounds;
916 if !extra_bounds.is_empty() {
919 format!("in method `{}`, \
920 type parameter {} requires `{}`, \
921 which is not required by \
922 the corresponding type parameter \
923 in the trait declaration",
924 token::get_ident(trait_m.ident),
926 extra_bounds.user_string(tcx)).as_slice());
930 // FIXME(#2687)---we should be checking that the bounds of the
931 // trait imply the bounds of the subtype, but it appears we
932 // are...not checking this.
933 if impl_param_def.bounds.trait_bounds.len() !=
934 trait_param_def.bounds.trait_bounds.len()
936 let found = impl_param_def.bounds.trait_bounds.len();
937 let expected = trait_param_def.bounds.trait_bounds.len();
940 format!("in method `{}`, type parameter {} has {} trait \
941 bound{}, but the corresponding type parameter in \
942 the trait declaration has {} trait bound{}",
943 token::get_ident(trait_m.ident),
946 if found == 1 {""} else {"s"},
948 if expected == 1 {""} else {"s"}).as_slice());
953 // This code is best explained by example. Consider a trait:
956 // fn method<'a,M>(t: T, m: &'a M) -> Self;
961 // impl<'i, U> Trait<&'i U> for Foo {
962 // fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
965 // We wish to decide if those two method types are compatible.
967 // We start out with trait_to_impl_substs, that maps the trait type
968 // parameters to impl type parameters:
970 // trait_to_impl_substs = {T => &'i U, Self => Foo}
972 // We create a mapping `dummy_substs` that maps from the impl type
973 // parameters to fresh types and regions. For type parameters,
974 // this is the identity transform, but we could as well use any
975 // skolemized types. For regions, we convert from bound to free
976 // regions (Note: but only early-bound regions, i.e., those
977 // declared on the impl or used in type parameter bounds).
979 // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
981 // Now we can apply skol_substs to the type of the impl method
982 // to yield a new function type in terms of our fresh, skolemized
985 // <'b> fn(t: &'i0 U0, m: &'b) -> Foo
987 // We now want to extract and substitute the type of the *trait*
988 // method and compare it. To do so, we must create a compound
989 // substitution by combining trait_to_impl_substs and
990 // impl_to_skol_substs, and also adding a mapping for the method
991 // type parameters. We extend the mapping to also include
992 // the method parameters.
994 // trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
996 // Applying this to the trait method type yields:
998 // <'a> fn(t: &'i0 U0, m: &'a) -> Foo
1000 // This type is also the same but the name of the bound region ('a
1001 // vs 'b). However, the normal subtyping rules on fn types handle
1002 // this kind of equivalency just fine.
1004 // Create mapping from impl to skolemized.
1006 impl_m.generics.types.map(
1007 |d| ty::mk_param_from_def(tcx, d));
1009 impl_m.generics.regions.map(
1010 |l| ty::free_region_from_def(impl_m_body_id, l));
1011 let impl_to_skol_substs =
1012 subst::Substs::new(skol_tps.clone(), skol_regions.clone());
1014 // Compute skolemized form of impl method ty.
1015 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1016 let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
1018 // Compute skolemized form of trait method ty.
1019 let trait_to_skol_substs =
1020 trait_to_impl_substs
1021 .subst(tcx, &impl_to_skol_substs)
1022 .with_method(skol_tps.get_vec(subst::FnSpace).clone(),
1023 skol_regions.get_vec(subst::FnSpace).clone());
1024 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1025 let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
1027 // Check the impl method type IM is a subtype of the trait method
1028 // type TM. To see why this makes sense, think of a vtable. The
1029 // expected type of the function pointers in the vtable is the
1030 // type TM of the trait method. The actual type will be the type
1031 // IM of the impl method. Because we know that IM <: TM, that
1032 // means that anywhere a TM is expected, a IM will do instead. In
1033 // other words, anyone expecting to call a method with the type
1034 // from the trait, can safely call a method with the type from the
1036 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1037 impl_fty, trait_fty) {
1042 format!("method `{}` has an incompatible type for trait: {}",
1043 token::get_ident(trait_m.ident),
1044 ty::type_err_to_str(tcx, terr)).as_slice());
1045 ty::note_and_explain_type_err(tcx, terr);
1050 impl<'a> AstConv for FnCtxt<'a> {
1051 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1053 fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
1054 ty::lookup_item_type(self.tcx(), id)
1057 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1058 ty::lookup_trait_def(self.tcx(), id)
1061 fn ty_infer(&self, _span: Span) -> ty::t {
1062 self.infcx().next_ty_var()
1066 impl<'a> FnCtxt<'a> {
1067 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1071 pub fn err_count_since_creation(&self) -> uint {
1072 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1075 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1077 infcx: self.infcx(),
1078 param_env: &self.inh.param_env
1083 impl<'a> RegionScope for infer::InferCtxt<'a> {
1084 fn anon_regions(&self, span: Span, count: uint)
1085 -> Result<Vec<ty::Region> , ()> {
1086 Ok(Vec::from_fn(count, |_| {
1087 self.next_region_var(infer::MiscVariable(span))
1092 impl<'a> FnCtxt<'a> {
1093 pub fn tag(&self) -> String {
1094 format!("{}", self as *FnCtxt)
1097 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1098 match self.inh.locals.borrow().find(&nid) {
1101 self.tcx().sess.span_bug(
1103 format!("no type for local variable {:?}",
1110 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1111 debug!("write_ty({}, {}) in fcx {}",
1112 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1113 self.inh.node_types.borrow_mut().insert(node_id, ty);
1116 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1117 if !substs.substs.is_noop() {
1118 debug!("write_substs({}, {}) in fcx {}",
1120 substs.repr(self.tcx()),
1123 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1127 pub fn write_ty_substs(&self,
1128 node_id: ast::NodeId,
1130 substs: ty::ItemSubsts) {
1131 let ty = ty.subst(self.tcx(), &substs.substs);
1132 self.write_ty(node_id, ty);
1133 self.write_substs(node_id, substs);
1136 pub fn write_autoderef_adjustment(&self,
1137 node_id: ast::NodeId,
1139 if derefs == 0 { return; }
1140 self.write_adjustment(
1142 ty::AutoDerefRef(ty::AutoDerefRef {
1148 pub fn write_adjustment(&self,
1149 node_id: ast::NodeId,
1150 adj: ty::AutoAdjustment) {
1151 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1152 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1155 pub fn write_nil(&self, node_id: ast::NodeId) {
1156 self.write_ty(node_id, ty::mk_nil());
1158 pub fn write_bot(&self, node_id: ast::NodeId) {
1159 self.write_ty(node_id, ty::mk_bot());
1161 pub fn write_error(&self, node_id: ast::NodeId) {
1162 self.write_ty(node_id, ty::mk_err());
1165 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1166 ast_ty_to_ty(self, self.infcx(), ast_t)
1169 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1170 pat.repr(self.tcx())
1173 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1174 match self.inh.node_types.borrow().find(&ex.id) {
1177 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1178 self.tag()).as_slice());
1183 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1184 match self.inh.node_types.borrow().find(&id) {
1187 self.tcx().sess.bug(
1188 format!("no type for node {}: {} in fcx {}",
1189 id, self.tcx().map.node_to_str(id),
1190 self.tag()).as_slice());
1195 pub fn method_ty_substs(&self, id: ast::NodeId) -> subst::Substs {
1196 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1197 Some(method) => method.substs.clone(),
1199 self.tcx().sess.bug(
1200 format!("no method entry for node {}: {} in fcx {}",
1201 id, self.tcx().map.node_to_str(id),
1202 self.tag()).as_slice());
1207 pub fn opt_node_ty_substs(&self,
1209 f: |&ty::ItemSubsts|) {
1210 match self.inh.item_substs.borrow().find(&id) {
1216 pub fn mk_subty(&self,
1217 a_is_expected: bool,
1218 origin: infer::TypeOrigin,
1221 -> Result<(), ty::type_err> {
1222 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1225 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1226 -> Result<(), ty::type_err> {
1227 infer::can_mk_subty(self.infcx(), sub, sup)
1230 pub fn mk_assignty(&self,
1234 -> Result<(), ty::type_err> {
1235 match infer::mk_coercety(self.infcx(),
1237 infer::ExprAssignable(expr.span),
1241 Err(ref e) => Err((*e)),
1242 Ok(Some(adjustment)) => {
1243 self.write_adjustment(expr.id, adjustment);
1249 pub fn mk_eqty(&self,
1250 a_is_expected: bool,
1251 origin: infer::TypeOrigin,
1254 -> Result<(), ty::type_err> {
1255 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1258 pub fn mk_subr(&self,
1259 a_is_expected: bool,
1260 origin: infer::SubregionOrigin,
1263 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1266 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1267 let old_region_lb = self.region_lb.get();
1268 self.region_lb.set(lb);
1270 self.region_lb.set(old_region_lb);
1274 pub fn type_error_message(&self,
1276 mk_msg: |String| -> String,
1278 err: Option<&ty::type_err>) {
1279 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1282 pub fn report_mismatched_return_types(&self,
1286 err: &ty::type_err) {
1288 if ty::type_is_error(e) || ty::type_is_error(a) {
1291 self.infcx().report_mismatched_types(sp, e, a, err)
1294 pub fn report_mismatched_types(&self,
1298 err: &ty::type_err) {
1299 self.infcx().report_mismatched_types(sp, e, a, err)
1303 pub enum LvaluePreference {
1308 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1309 expr_id: Option<ast::NodeId>,
1310 mut lvalue_pref: LvaluePreference,
1311 should_stop: |ty::t, uint| -> Option<T>)
1312 -> (ty::t, uint, Option<T>) {
1314 * Executes an autoderef loop for the type `t`. At each step, invokes
1315 * `should_stop` to decide whether to terminate the loop. Returns
1316 * the final type and number of derefs that it performed.
1318 * Note: this method does not modify the adjustments table. The caller is
1319 * responsible for inserting an AutoAdjustment record into the `fcx`
1320 * using one of the suitable methods.
1323 let mut t = base_ty;
1324 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1325 let resolved_t = structurally_resolved_type(fcx, sp, t);
1327 match should_stop(resolved_t, autoderefs) {
1328 Some(x) => return (resolved_t, autoderefs, Some(x)),
1332 // Otherwise, deref if type is derefable:
1333 let mt = match ty::deref(resolved_t, false) {
1334 Some(mt) => Some(mt),
1336 let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
1337 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1343 if mt.mutbl == ast::MutImmutable {
1344 lvalue_pref = NoPreference;
1347 None => return (resolved_t, autoderefs, None)
1351 // We've reached the recursion limit, error gracefully.
1352 fcx.tcx().sess.span_err(sp,
1353 format!("reached the recursion limit while auto-dereferencing {}",
1354 base_ty.repr(fcx.tcx())).as_slice());
1355 (ty::mk_err(), 0, None)
1358 /// Attempts to resolve a call expression as an overloaded call.
1359 fn try_overloaded_call(fcx: &FnCtxt,
1360 call_expression: &ast::Expr,
1361 callee: Gc<ast::Expr>,
1363 args: &[Gc<ast::Expr>])
1365 // Try `FnOnce`, then `FnMut`, then `Fn`.
1366 for &(maybe_function_trait, method_name) in [
1367 (fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
1368 (fcx.tcx().lang_items.fn_mut_trait(), token::intern("call_mut")),
1369 (fcx.tcx().lang_items.fn_trait(), token::intern("call"))
1371 let function_trait = match maybe_function_trait {
1373 Some(function_trait) => function_trait,
1375 let method_callee = match method::lookup_in_trait(
1377 call_expression.span,
1383 DontAutoderefReceiver,
1384 IgnoreStaticMethods) {
1386 Some(method_callee) => method_callee,
1388 let method_call = MethodCall::expr(call_expression.id);
1389 let output_type = check_method_argument_types(fcx,
1390 call_expression.span,
1396 fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
1397 write_call(fcx, call_expression, output_type);
1399 if !fcx.tcx().sess.features.overloaded_calls.get() {
1400 fcx.tcx().sess.span_err(call_expression.span,
1401 "overloaded calls are experimental");
1402 fcx.tcx().sess.span_note(call_expression.span,
1403 "add `#[feature(overloaded_calls)]` to \
1404 the crate attributes to enable");
1413 fn try_overloaded_deref(fcx: &FnCtxt,
1415 method_call: Option<MethodCall>,
1416 base_expr: Option<&ast::Expr>,
1418 lvalue_pref: LvaluePreference)
1420 // Try DerefMut first, if preferred.
1421 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1422 (PreferMutLvalue, Some(trait_did)) => {
1423 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1424 token::intern("deref_mut"), trait_did,
1425 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1430 // Otherwise, fall back to Deref.
1431 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1432 (None, Some(trait_did)) => {
1433 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1434 token::intern("deref"), trait_did,
1435 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1437 (method, _) => method
1442 let ref_ty = ty::ty_fn_ret(method.ty);
1444 Some(method_call) => {
1445 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1449 ty::deref(ref_ty, true)
1455 fn check_method_argument_types(fcx: &FnCtxt,
1457 method_fn_ty: ty::t,
1458 callee_expr: &ast::Expr,
1459 args: &[Gc<ast::Expr>],
1460 deref_args: DerefArgs,
1461 tuple_arguments: TupleArgumentsFlag)
1463 // HACK(eddyb) ignore provided self (it has special typeck rules).
1464 let args = if tuple_arguments == DontTupleArguments {
1469 if ty::type_is_error(method_fn_ty) {
1470 let err_inputs = err_args(args.len());
1471 check_argument_types(fcx,
1473 err_inputs.as_slice(),
1481 match ty::get(method_fn_ty).sty {
1482 ty::ty_bare_fn(ref fty) => {
1483 // HACK(eddyb) ignore self in the definition (see above).
1484 check_argument_types(fcx,
1486 fty.sig.inputs.slice_from(1),
1495 fcx.tcx().sess.span_bug(callee_expr.span,
1496 "method without bare fn type");
1502 fn check_argument_types(fcx: &FnCtxt,
1504 fn_inputs: &[ty::t],
1505 callee_expr: &ast::Expr,
1506 args: &[Gc<ast::Expr>],
1507 deref_args: DerefArgs,
1509 tuple_arguments: TupleArgumentsFlag) {
1512 * Generic function that factors out common logic from
1513 * function calls, method calls and overloaded operators.
1516 let tcx = fcx.ccx.tcx;
1518 // Grab the argument types, supplying fresh type variables
1519 // if the wrong number of arguments were supplied
1520 let supplied_arg_count = if tuple_arguments == DontTupleArguments {
1526 let expected_arg_count = fn_inputs.len();
1527 let formal_tys = if tuple_arguments == TupleArguments {
1528 let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
1529 match ty::get(tuple_type).sty {
1530 ty::ty_tup(ref arg_types) => {
1531 if arg_types.len() != args.len() {
1533 "this function takes {} parameter{} \
1534 but {} parameter{} supplied",
1536 if arg_types.len() == 1 {""} else {"s"},
1538 if args.len() == 1 {" was"} else {"s were"});
1539 tcx.sess.span_err(sp, msg.as_slice());
1540 err_args(args.len())
1542 (*arg_types).clone()
1546 if args.len() != 0 {
1548 "this function takes 0 parameters \
1549 but {} parameter{} supplied",
1551 if args.len() == 1 {" was"} else {"s were"});
1552 tcx.sess.span_err(sp, msg.as_slice());
1559 "cannot use call notation; the first type \
1560 parameter for the function trait is neither a \
1562 err_args(supplied_arg_count)
1565 } else if expected_arg_count == supplied_arg_count {
1566 fn_inputs.iter().map(|a| *a).collect()
1567 } else if variadic {
1568 if supplied_arg_count >= expected_arg_count {
1569 fn_inputs.iter().map(|a| *a).collect()
1572 "this function takes at least {} parameter{} \
1573 but {} parameter{} supplied",
1575 if expected_arg_count == 1 {""} else {"s"},
1577 if supplied_arg_count == 1 {" was"} else {"s were"});
1579 tcx.sess.span_err(sp, msg.as_slice());
1581 err_args(supplied_arg_count)
1585 "this function takes {} parameter{} \
1586 but {} parameter{} supplied",
1588 if expected_arg_count == 1 {""} else {"s"},
1590 if supplied_arg_count == 1 {" was"} else {"s were"});
1592 tcx.sess.span_err(sp, msg.as_slice());
1594 err_args(supplied_arg_count)
1597 debug!("check_argument_types: formal_tys={:?}",
1598 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1600 // Check the arguments.
1601 // We do this in a pretty awful way: first we typecheck any arguments
1602 // that are not anonymous functions, then we typecheck the anonymous
1603 // functions. This is so that we have more information about the types
1604 // of arguments when we typecheck the functions. This isn't really the
1605 // right way to do this.
1606 let xs = [false, true];
1607 for check_blocks in xs.iter() {
1608 let check_blocks = *check_blocks;
1609 debug!("check_blocks={}", check_blocks);
1611 // More awful hacks: before we check the blocks, try to do
1612 // an "opportunistic" vtable resolution of any trait
1613 // bounds on the call.
1615 vtable::early_resolve_expr(callee_expr, fcx, true);
1618 // For variadic functions, we don't have a declared type for all of
1619 // the arguments hence we only do our usual type checking with
1620 // the arguments who's types we do know.
1621 let t = if variadic {
1623 } else if tuple_arguments == TupleArguments {
1628 for (i, arg) in args.iter().take(t).enumerate() {
1629 let is_block = match arg.node {
1630 ast::ExprFnBlock(..) |
1631 ast::ExprProc(..) => true,
1635 if is_block == check_blocks {
1636 debug!("checking the argument");
1637 let mut formal_ty = *formal_tys.get(i);
1641 match ty::get(formal_ty).sty {
1642 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1645 // So we hit this case when one implements the
1646 // operator traits but leaves an argument as
1647 // just T instead of &T. We'll catch it in the
1648 // mismatch impl/trait method phase no need to
1651 formal_ty = ty::mk_err();
1658 check_expr_coercable_to_type(fcx, &**arg, formal_ty);
1664 // We also need to make sure we at least write the ty of the other
1665 // arguments which we skipped above.
1667 for arg in args.iter().skip(expected_arg_count) {
1668 check_expr(fcx, &**arg);
1670 // There are a few types which get autopromoted when passed via varargs
1671 // in C but we just error out instead and require explicit casts.
1672 let arg_ty = structurally_resolved_type(fcx, arg.span,
1673 fcx.expr_ty(&**arg));
1674 match ty::get(arg_ty).sty {
1675 ty::ty_float(ast::TyF32) => {
1676 fcx.type_error_message(arg.span,
1678 format!("can't pass an {} to variadic \
1679 function, cast to c_double", t)
1682 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1683 fcx.type_error_message(arg.span, |t| {
1684 format!("can't pass {} to variadic \
1685 function, cast to c_int",
1689 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1690 fcx.type_error_message(arg.span, |t| {
1691 format!("can't pass {} to variadic \
1692 function, cast to c_uint",
1702 fn err_args(len: uint) -> Vec<ty::t> {
1703 Vec::from_fn(len, |_| ty::mk_err())
1706 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1707 fcx.write_ty(call_expr.id, output);
1710 // AST fragment checking
1711 pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
1712 let tcx = fcx.ccx.tcx;
1715 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1716 ast::LitBinary(..) => {
1717 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1719 ast::LitByte(_) => ty::mk_u8(),
1720 ast::LitChar(_) => ty::mk_char(),
1721 ast::LitInt(_, t) => ty::mk_mach_int(t),
1722 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1723 ast::LitIntUnsuffixed(_) => {
1724 // An unsuffixed integer literal could have any integral type,
1725 // so we create an integral type variable for it.
1726 ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())
1728 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1729 ast::LitFloatUnsuffixed(_) => {
1730 // An unsuffixed floating point literal could have any floating point
1731 // type, so we create a floating point type variable for it.
1732 ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())
1734 ast::LitNil => ty::mk_nil(),
1735 ast::LitBool(_) => ty::mk_bool()
1739 pub fn valid_range_bounds(ccx: &CrateCtxt,
1743 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1744 Some(val) => Some(val <= 0),
1749 pub fn check_expr_has_type(
1750 fcx: &FnCtxt, expr: &ast::Expr,
1752 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1753 demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
1757 fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1758 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1759 demand::coerce(fcx, expr.span, expected, expr)
1763 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1764 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
1767 fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
1768 expected: Option<ty::t>) {
1769 check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
1772 fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
1774 expected: Option<ty::t>,
1775 lvalue_pref: LvaluePreference) {
1776 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1779 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1780 check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
1783 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1784 lvalue_pref: LvaluePreference) {
1785 check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
1789 // determine the `self` type, using fresh variables for all variables
1790 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1791 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1793 pub fn impl_self_ty(vcx: &VtableContext,
1794 span: Span, // (potential) receiver for this impl
1797 let tcx = vcx.tcx();
1799 let ity = ty::lookup_item_type(tcx, did);
1800 let (n_tps, rps, raw_ty) =
1801 (ity.generics.types.len(subst::TypeSpace),
1802 ity.generics.regions.get_vec(subst::TypeSpace),
1805 let rps = vcx.infcx.region_vars_for_defs(span, rps);
1806 let tps = vcx.infcx.next_ty_vars(n_tps);
1807 let substs = subst::Substs::new_type(tps, rps);
1808 let substd_ty = raw_ty.subst(tcx, &substs);
1810 TypeAndSubsts { substs: substs, ty: substd_ty }
1813 // Only for fields! Returns <none> for methods>
1814 // Indifferent to privacy flags
1815 pub fn lookup_field_ty(tcx: &ty::ctxt,
1816 class_id: ast::DefId,
1817 items: &[ty::field_ty],
1818 fieldname: ast::Name,
1819 substs: &subst::Substs) -> Option<ty::t> {
1821 let o_field = items.iter().find(|f| f.name == fieldname);
1822 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
1825 // Controls whether the arguments are automatically referenced. This is useful
1826 // for overloaded binary and unary operators.
1827 pub enum DerefArgs {
1832 /// Controls whether the arguments are tupled. This is used for the call
1835 /// Tupling means that all call-side arguments are packed into a tuple and
1836 /// passed as a single parameter. For example, if tupling is enabled, this
1839 /// fn f(x: (int, int))
1841 /// Can be called as:
1848 #[deriving(Clone, Eq, PartialEq)]
1849 enum TupleArgumentsFlag {
1855 /// If an expression has any sub-expressions that result in a type error,
1856 /// inspecting that expression's type with `ty::type_is_error` will return
1857 /// true. Likewise, if an expression is known to diverge, inspecting its
1858 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
1859 /// strict, _|_ can appear in the type of an expression that does not,
1860 /// itself, diverge: for example, fn() -> _|_.)
1861 /// Note that inspecting a type's structure *directly* may expose the fact
1862 /// that there are actually multiple representations for both `ty_err` and
1863 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
1864 fn check_expr_with_unifier(fcx: &FnCtxt,
1866 expected: Option<ty::t>,
1867 lvalue_pref: LvaluePreference,
1869 debug!(">> typechecking");
1871 // A generic function for doing all of the checking for call expressions
1872 fn check_call(fcx: &FnCtxt,
1873 call_expr: &ast::Expr,
1875 args: &[Gc<ast::Expr>]) {
1876 // Store the type of `f` as the type of the callee
1877 let fn_ty = fcx.expr_ty(f);
1879 // Extract the function signature from `in_fty`.
1880 let fn_sty = structure_of(fcx, f.span, fn_ty);
1882 // This is the "default" function signature, used in case of error.
1883 // In that case, we check each argument against "error" in order to
1884 // set up all the node type bindings.
1885 let error_fn_sig = FnSig {
1886 binder_id: ast::CRATE_NODE_ID,
1887 inputs: err_args(args.len()),
1888 output: ty::mk_err(),
1892 let fn_sig = match *fn_sty {
1893 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
1894 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
1896 fcx.type_error_message(call_expr.span, |actual| {
1897 format!("expected function but found `{}`", actual)
1903 // Replace any bound regions that appear in the function
1904 // signature with region variables
1905 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
1906 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
1909 // Call the generic checker.
1910 check_argument_types(fcx,
1912 fn_sig.inputs.as_slice(),
1917 DontTupleArguments);
1919 write_call(fcx, call_expr, fn_sig.output);
1922 // Checks a method call.
1923 fn check_method_call(fcx: &FnCtxt,
1925 method_name: ast::SpannedIdent,
1926 args: &[Gc<ast::Expr>],
1927 tps: &[ast::P<ast::Ty>]) {
1928 let rcvr = args[0].clone();
1929 // We can't know if we need &mut self before we look up the method,
1930 // so treat the receiver as mutable just in case - only explicit
1931 // overloaded dereferences care about the distinction.
1932 check_expr_with_lvalue_pref(fcx, &*rcvr, PreferMutLvalue);
1934 // no need to check for bot/err -- callee does that
1935 let expr_t = structurally_resolved_type(fcx,
1937 fcx.expr_ty(&*rcvr));
1939 let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
1940 let fn_ty = match method::lookup(fcx, expr, &*rcvr,
1941 method_name.node.name,
1942 expr_t, tps.as_slice(),
1944 CheckTraitsAndInherentMethods,
1945 AutoderefReceiver, IgnoreStaticMethods) {
1947 let method_ty = method.ty;
1948 let method_call = MethodCall::expr(expr.id);
1949 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1953 debug!("(checking method call) failing expr is {}", expr.id);
1955 fcx.type_error_message(method_name.span,
1957 format!("type `{}` does not implement any \
1958 method in scope named `{}`",
1960 token::get_ident(method_name.node))
1965 // Add error type for the result
1966 fcx.write_error(expr.id);
1968 // Check for potential static matches (missing self parameters)
1972 method_name.node.name,
1976 CheckTraitsAndInherentMethods,
1977 DontAutoderefReceiver,
1978 ReportStaticMethods);
1984 // Call the generic checker.
1985 let ret_ty = check_method_argument_types(fcx,
1991 DontTupleArguments);
1993 write_call(fcx, expr, ret_ty);
1996 // A generic function for checking the then and else in an if
1998 fn check_then_else(fcx: &FnCtxt,
1999 cond_expr: &ast::Expr,
2000 then_blk: &ast::Block,
2001 opt_else_expr: Option<Gc<ast::Expr>>,
2004 expected: Option<ty::t>) {
2005 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2007 let branches_ty = match opt_else_expr {
2008 Some(ref else_expr) => {
2009 check_block_with_expected(fcx, then_blk, expected);
2010 let then_ty = fcx.node_ty(then_blk.id);
2011 check_expr_with_opt_hint(fcx, &**else_expr, expected);
2012 let else_ty = fcx.expr_ty(&**else_expr);
2013 infer::common_supertype(fcx.infcx(),
2014 infer::IfExpression(sp),
2020 check_block_no_value(fcx, then_blk);
2025 let cond_ty = fcx.expr_ty(cond_expr);
2026 let if_ty = if ty::type_is_error(cond_ty) {
2028 } else if ty::type_is_bot(cond_ty) {
2034 fcx.write_ty(id, if_ty);
2037 fn lookup_op_method(fcx: &FnCtxt,
2041 trait_did: Option<ast::DefId>,
2042 args: &[Gc<ast::Expr>],
2043 autoderef_receiver: AutoderefReceiverFlag,
2044 unbound_method: ||) -> ty::t {
2045 let method = match trait_did {
2046 Some(trait_did) => {
2047 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2048 trait_did, self_t, [], autoderef_receiver,
2049 IgnoreStaticMethods)
2055 let method_ty = method.ty;
2056 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2057 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2058 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2059 check_method_argument_types(fcx,
2069 // Check the args anyway
2070 // so we get all the error messages
2071 let expected_ty = ty::mk_err();
2072 check_method_argument_types(fcx,
2078 DontTupleArguments);
2084 // could be either an expr_binop or an expr_assign_binop
2085 fn check_binop(fcx: &FnCtxt,
2090 is_binop_assignment: IsBinopAssignment) {
2091 let tcx = fcx.ccx.tcx;
2093 let lvalue_pref = match is_binop_assignment {
2094 BinopAssignment => PreferMutLvalue,
2095 SimpleBinop => NoPreference
2097 check_expr_with_lvalue_pref(fcx, &*lhs, lvalue_pref);
2099 // Callee does bot / err checking
2100 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2101 fcx.expr_ty(&*lhs));
2103 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2104 // Shift is a special case: rhs can be any integral type
2105 check_expr(fcx, &*rhs);
2106 let rhs_t = fcx.expr_ty(&*rhs);
2107 require_integral(fcx, rhs.span, rhs_t);
2108 fcx.write_ty(expr.id, lhs_t);
2112 if ty::is_binopable(tcx, lhs_t, op) {
2113 let tvar = fcx.infcx().next_ty_var();
2114 demand::suptype(fcx, expr.span, tvar, lhs_t);
2115 check_expr_has_type(fcx, &*rhs, tvar);
2117 let result_t = match op {
2118 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2120 if ty::type_is_simd(tcx, lhs_t) {
2121 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2122 fcx.type_error_message(expr.span,
2124 format!("binary comparison \
2125 operation `{}` not \
2126 supported for floating \
2127 point SIMD vector `{}`",
2128 ast_util::binop_to_str(op),
2145 fcx.write_ty(expr.id, result_t);
2149 if op == ast::BiOr || op == ast::BiAnd {
2150 // This is an error; one of the operands must have the wrong
2152 fcx.write_error(expr.id);
2153 fcx.write_error(rhs.id);
2154 fcx.type_error_message(expr.span,
2156 format!("binary operation `{}` cannot be applied \
2158 ast_util::binop_to_str(op),
2165 // Check for overloaded operators if not an assignment.
2166 let result_t = if is_binop_assignment == SimpleBinop {
2167 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2169 fcx.type_error_message(expr.span,
2171 format!("binary assignment \
2173 cannot be applied to \
2175 ast_util::binop_to_str(op),
2180 check_expr(fcx, &*rhs);
2184 fcx.write_ty(expr.id, result_t);
2185 if ty::type_is_error(result_t) {
2186 fcx.write_ty(rhs.id, result_t);
2190 fn check_user_binop(fcx: &FnCtxt,
2192 lhs_expr: Gc<ast::Expr>,
2193 lhs_resolved_t: ty::t,
2195 rhs: Gc<ast::Expr>) -> ty::t {
2196 let tcx = fcx.ccx.tcx;
2197 let lang = &tcx.lang_items;
2198 let (name, trait_did) = match op {
2199 ast::BiAdd => ("add", lang.add_trait()),
2200 ast::BiSub => ("sub", lang.sub_trait()),
2201 ast::BiMul => ("mul", lang.mul_trait()),
2202 ast::BiDiv => ("div", lang.div_trait()),
2203 ast::BiRem => ("rem", lang.rem_trait()),
2204 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2205 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2206 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2207 ast::BiShl => ("shl", lang.shl_trait()),
2208 ast::BiShr => ("shr", lang.shr_trait()),
2209 ast::BiLt => ("lt", lang.ord_trait()),
2210 ast::BiLe => ("le", lang.ord_trait()),
2211 ast::BiGe => ("ge", lang.ord_trait()),
2212 ast::BiGt => ("gt", lang.ord_trait()),
2213 ast::BiEq => ("eq", lang.eq_trait()),
2214 ast::BiNe => ("ne", lang.eq_trait()),
2215 ast::BiAnd | ast::BiOr => {
2216 check_expr(fcx, &*rhs);
2217 return ty::mk_err();
2220 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2221 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2222 fcx.type_error_message(ex.span, |actual| {
2223 format!("binary operation `{}` cannot be applied to type `{}`",
2224 ast_util::binop_to_str(op),
2226 }, lhs_resolved_t, None)
2230 fn check_user_unop(fcx: &FnCtxt,
2233 trait_did: Option<ast::DefId>,
2235 rhs_expr: Gc<ast::Expr>,
2236 rhs_t: ty::t) -> ty::t {
2237 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2238 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2239 fcx.type_error_message(ex.span, |actual| {
2240 format!("cannot apply unary operator `{}` to type `{}`",
2246 // Resolves `expected` by a single level if it is a variable and passes it
2247 // through the `unpack` function. It there is no expected type or
2248 // resolution is not possible (e.g., no constraints yet present), just
2250 fn unpack_expected<O>(
2252 expected: Option<ty::t>,
2253 unpack: |&ty::sty| -> Option<O>)
2257 match resolve_type(fcx.infcx(), t, force_tvar) {
2258 Ok(t) => unpack(&ty::get(t).sty),
2266 fn check_expr_fn(fcx: &FnCtxt,
2268 store: ty::TraitStore,
2270 body: ast::P<ast::Block>,
2271 expected: Option<ty::t>) {
2272 let tcx = fcx.ccx.tcx;
2274 // Find the expected input/output types (if any). Substitute
2275 // fresh bound regions for any bound regions we find in the
2276 // expected types so as to avoid capture.
2277 let expected_sty = unpack_expected(fcx,
2279 |x| Some((*x).clone()));
2282 expected_bounds) = {
2283 match expected_sty {
2284 Some(ty::ty_closure(ref cenv)) => {
2286 replace_late_bound_regions_in_fn_sig(
2288 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2289 let onceness = match (&store, &cenv.store) {
2290 // As the closure type and onceness go, only three
2291 // combinations are legit:
2295 // If the actual and expected closure type disagree with
2296 // each other, set expected onceness to be always Once or
2297 // Many according to the actual type. Otherwise, it will
2298 // yield either an illegal "many proc" or a less known
2299 // "once closure" in the error message.
2300 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2301 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2303 (&ty::UniqTraitStore, _) => ast::Once,
2304 (&ty::RegionTraitStore(..), _) => ast::Many,
2306 (Some(sig), onceness, cenv.bounds)
2309 // Not an error! Means we're inferring the closure type
2310 let mut bounds = ty::empty_builtin_bounds();
2311 let onceness = match expr.node {
2312 ast::ExprProc(..) => {
2313 bounds.add(ty::BoundSend);
2318 (None, onceness, bounds)
2323 // construct the function type
2324 let fn_ty = astconv::ty_of_closure(fcx,
2332 let fty_sig = fn_ty.sig.clone();
2333 let fty = ty::mk_closure(tcx, fn_ty);
2334 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2336 fcx.write_ty(expr.id, fty);
2338 // If the closure is a stack closure and hasn't had some non-standard
2339 // style inferred for it, then check it under its parent's style.
2340 // Otherwise, use its own
2341 let (inherited_style, id) = match store {
2342 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2343 fcx.ps.borrow().def),
2344 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2347 check_fn(fcx.ccx, inherited_style, &fty_sig,
2348 &*decl, id, &*body, fcx.inh);
2352 // Check field access expressions
2353 fn check_field(fcx: &FnCtxt,
2355 lvalue_pref: LvaluePreference,
2357 field: &ast::SpannedIdent,
2358 tys: &[ast::P<ast::Ty>]) {
2359 let tcx = fcx.ccx.tcx;
2360 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2361 let expr_t = structurally_resolved_type(fcx, expr.span,
2363 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2364 let (_, autoderefs, field_ty) =
2365 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2366 match ty::get(base_t).sty {
2367 ty::ty_struct(base_id, ref substs) => {
2368 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2369 let fields = ty::lookup_struct_fields(tcx, base_id);
2370 lookup_field_ty(tcx, base_id, fields.as_slice(),
2371 field.node.name, &(*substs))
2378 fcx.write_ty(expr.id, field_ty);
2379 fcx.write_autoderef_adjustment(base.id, autoderefs);
2385 let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
2386 match method::lookup(fcx,
2393 CheckTraitsAndInherentMethods,
2395 IgnoreStaticMethods) {
2397 fcx.type_error_message(
2400 format!("attempted to take value of method `{}` on type \
2401 `{}`", token::get_ident(field.node), actual)
2405 tcx.sess.span_note(field.span,
2406 "maybe a missing `()` to call it? If not, try an anonymous function.");
2410 fcx.type_error_message(
2413 format!("attempted access of field `{}` on \
2414 type `{}`, but no field with that \
2416 token::get_ident(field.node),
2423 fcx.write_error(expr.id);
2426 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2429 class_id: ast::DefId,
2430 node_id: ast::NodeId,
2431 substitutions: subst::Substs,
2432 field_types: &[ty::field_ty],
2433 ast_fields: &[ast::Field],
2434 check_completeness: bool) {
2435 let tcx = fcx.ccx.tcx;
2437 let mut class_field_map = HashMap::new();
2438 let mut fields_found = 0;
2439 for field in field_types.iter() {
2440 class_field_map.insert(field.name, (field.id, false));
2443 let mut error_happened = false;
2445 // Typecheck each field.
2446 for field in ast_fields.iter() {
2447 let mut expected_field_type = ty::mk_err();
2449 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2452 fcx.type_error_message(
2455 format!("structure `{}` has no field named `{}`",
2456 actual, token::get_ident(field.ident.node))
2460 error_happened = true;
2462 Some((_, true)) => {
2465 format!("field `{}` specified more than once",
2466 token::get_ident(field.ident
2467 .node)).as_slice());
2468 error_happened = true;
2470 Some((field_id, false)) => {
2471 expected_field_type =
2472 ty::lookup_field_type(
2473 tcx, class_id, field_id, &substitutions);
2474 class_field_map.insert(
2475 field.ident.node.name, (field_id, true));
2479 // Make sure to give a type to the field even if there's
2480 // an error, so we can continue typechecking
2481 check_expr_coercable_to_type(
2484 expected_field_type);
2488 fcx.write_error(node_id);
2491 if check_completeness && !error_happened {
2492 // Make sure the programmer specified all the fields.
2493 assert!(fields_found <= field_types.len());
2494 if fields_found < field_types.len() {
2495 let mut missing_fields = Vec::new();
2496 for class_field in field_types.iter() {
2497 let name = class_field.name;
2498 let (_, seen) = *class_field_map.get(&name);
2500 missing_fields.push(
2501 format!("`{}`", token::get_name(name).get()))
2505 tcx.sess.span_err(span,
2507 "missing field{}: {fields}",
2508 if missing_fields.len() == 1 {""} else {"s"},
2509 fields = missing_fields.connect(", ")).as_slice());
2513 if !error_happened {
2514 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2515 class_id, substitutions));
2519 fn check_struct_constructor(fcx: &FnCtxt,
2521 span: codemap::Span,
2522 class_id: ast::DefId,
2523 fields: &[ast::Field],
2524 base_expr: Option<Gc<ast::Expr>>) {
2525 let tcx = fcx.ccx.tcx;
2527 // Look up the number of type parameters and the raw type, and
2528 // determine whether the class is region-parameterized.
2529 let item_type = ty::lookup_item_type(tcx, class_id);
2530 let raw_type = item_type.ty;
2532 // Generate the struct type.
2533 let substitutions = fcx.infcx().fresh_substs_for_type(
2534 span, &item_type.generics);
2535 let mut struct_type = raw_type.subst(tcx, &substitutions);
2537 // Look up and check the fields.
2538 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2539 check_struct_or_variant_fields(fcx,
2545 class_fields.as_slice(),
2547 base_expr.is_none());
2548 if ty::type_is_error(fcx.node_ty(id)) {
2549 struct_type = ty::mk_err();
2552 // Check the base expression if necessary.
2555 Some(base_expr) => {
2556 check_expr_has_type(fcx, &*base_expr, struct_type);
2557 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2558 struct_type = ty::mk_bot();
2563 // Write in the resulting type.
2564 fcx.write_ty(id, struct_type);
2567 fn check_struct_enum_variant(fcx: &FnCtxt,
2569 span: codemap::Span,
2570 enum_id: ast::DefId,
2571 variant_id: ast::DefId,
2572 fields: &[ast::Field]) {
2573 let tcx = fcx.ccx.tcx;
2575 // Look up the number of type parameters and the raw type, and
2576 // determine whether the enum is region-parameterized.
2577 let item_type = ty::lookup_item_type(tcx, enum_id);
2578 let substitutions = fcx.infcx().fresh_substs_for_type(span, &item_type.generics);
2579 let enum_type = item_type.ty.subst(tcx, &substitutions);
2581 // Look up and check the enum variant fields.
2582 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2583 check_struct_or_variant_fields(fcx,
2589 variant_fields.as_slice(),
2592 fcx.write_ty(id, enum_type);
2595 let tcx = fcx.ccx.tcx;
2598 ast::ExprVstore(ev, vst) => {
2599 let typ = match ev.node {
2600 ast::ExprVec(ref args) => {
2601 let mutability = match vst {
2602 ast::ExprVstoreMutSlice => ast::MutMutable,
2603 _ => ast::MutImmutable,
2605 let mut any_error = false;
2606 let mut any_bot = false;
2607 let t: ty::t = fcx.infcx().next_ty_var();
2608 for e in args.iter() {
2609 check_expr_has_type(fcx, &**e, t);
2610 let arg_t = fcx.expr_ty(&**e);
2611 if ty::type_is_error(arg_t) {
2614 else if ty::type_is_bot(arg_t) {
2623 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2624 ty::mt{ ty: ty::mk_vec(tcx,
2625 ty::mt {ty: t, mutbl: mutability},
2627 mutbl: mutability })
2630 ast::ExprRepeat(ref element, ref count_expr) => {
2631 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
2632 let _ = ty::eval_repeat_count(fcx, &**count_expr);
2633 let mutability = match vst {
2634 ast::ExprVstoreMutSlice => ast::MutMutable,
2635 _ => ast::MutImmutable,
2637 let t = fcx.infcx().next_ty_var();
2638 check_expr_has_type(fcx, &**element, t);
2639 let arg_t = fcx.expr_ty(&**element);
2640 if ty::type_is_error(arg_t) {
2642 } else if ty::type_is_bot(arg_t) {
2645 ast_expr_vstore_to_ty(fcx, &*ev, vst, ||
2646 ty::mt{ ty: ty::mk_vec(tcx,
2647 ty::mt {ty: t, mutbl: mutability},
2652 ast::ExprLit(_) => {
2653 let error = if vst == ast::ExprVstoreSlice {
2654 "`&\"string\"` has been removed; use `\"string\"` instead"
2656 "`box \"string\"` has been removed; use `\"string\".to_string()` instead"
2658 tcx.sess.span_err(expr.span, error);
2661 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2663 fcx.write_ty(ev.id, typ);
2664 fcx.write_ty(id, typ);
2667 ast::ExprBox(ref place, ref subexpr) => {
2668 check_expr(fcx, &**place);
2669 check_expr(fcx, &**subexpr);
2671 let mut checked = false;
2673 ast::ExprPath(ref path) => {
2674 // FIXME(pcwalton): For now we hardcode the two permissible
2675 // places: the exchange heap and the managed heap.
2676 let definition = lookup_def(fcx, path.span, place.id);
2677 let def_id = definition.def_id();
2678 if tcx.lang_items.exchange_heap() == Some(def_id) {
2679 fcx.write_ty(id, ty::mk_uniq(tcx,
2680 fcx.expr_ty(&**subexpr)));
2682 } else if tcx.lang_items.managed_heap() == Some(def_id) {
2683 fcx.write_ty(id, ty::mk_box(tcx,
2684 fcx.expr_ty(&**subexpr)));
2692 tcx.sess.span_err(expr.span,
2693 "only the managed heap and exchange heap are \
2694 currently supported");
2695 fcx.write_ty(id, ty::mk_err());
2699 ast::ExprLit(ref lit) => {
2700 let typ = check_lit(fcx, &**lit);
2701 fcx.write_ty(id, typ);
2703 ast::ExprBinary(op, ref lhs, ref rhs) => {
2704 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
2706 let lhs_ty = fcx.expr_ty(&**lhs);
2707 let rhs_ty = fcx.expr_ty(&**rhs);
2708 if ty::type_is_error(lhs_ty) ||
2709 ty::type_is_error(rhs_ty) {
2710 fcx.write_error(id);
2712 else if ty::type_is_bot(lhs_ty) ||
2713 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2717 ast::ExprAssignOp(op, ref lhs, ref rhs) => {
2718 check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
2720 let lhs_t = fcx.expr_ty(&**lhs);
2721 let result_t = fcx.expr_ty(expr);
2722 demand::suptype(fcx, expr.span, result_t, lhs_t);
2724 let tcx = fcx.tcx();
2725 if !ty::expr_is_lval(tcx, &**lhs) {
2726 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2729 // Overwrite result of check_binop...this preserves existing behavior
2730 // but seems quite dubious with regard to user-defined methods
2731 // and so forth. - Niko
2732 if !ty::type_is_error(result_t)
2733 && !ty::type_is_bot(result_t) {
2734 fcx.write_nil(expr.id);
2737 ast::ExprUnary(unop, ref oprnd) => {
2738 let exp_inner = unpack_expected(fcx, expected, |sty| {
2740 ast::UnBox | ast::UnUniq => match *sty {
2741 ty::ty_box(ty) | ty::ty_uniq(ty) => Some(ty),
2744 ast::UnNot | ast::UnNeg => expected,
2745 ast::UnDeref => None
2748 let lvalue_pref = match unop {
2749 ast::UnDeref => lvalue_pref,
2752 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**oprnd, exp_inner, lvalue_pref);
2753 let mut oprnd_t = fcx.expr_ty(&**oprnd);
2754 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2757 oprnd_t = ty::mk_box(tcx, oprnd_t)
2760 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2763 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2764 oprnd_t = match ty::deref(oprnd_t, true) {
2766 None => match try_overloaded_deref(fcx, expr.span,
2767 Some(MethodCall::expr(expr.id)),
2768 Some(&**oprnd), oprnd_t, lvalue_pref) {
2771 let is_newtype = match ty::get(oprnd_t).sty {
2772 ty::ty_struct(did, ref substs) => {
2773 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2775 && fields.get(0).ident ==
2776 token::special_idents::unnamed_field
2781 // This is an obsolete struct deref
2782 tcx.sess.span_err(expr.span,
2783 "single-field tuple-structs can \
2784 no longer be dereferenced");
2786 fcx.type_error_message(expr.span, |actual| {
2787 format!("type `{}` cannot be \
2788 dereferenced", actual)
2797 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2799 if !(ty::type_is_integral(oprnd_t) ||
2800 ty::get(oprnd_t).sty == ty::ty_bool) {
2801 oprnd_t = check_user_unop(fcx, "!", "not",
2802 tcx.lang_items.not_trait(),
2803 expr, oprnd.clone(), oprnd_t);
2807 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2809 if !(ty::type_is_integral(oprnd_t) ||
2810 ty::type_is_fp(oprnd_t)) {
2811 oprnd_t = check_user_unop(fcx, "-", "neg",
2812 tcx.lang_items.neg_trait(),
2813 expr, oprnd.clone(), oprnd_t);
2818 fcx.write_ty(id, oprnd_t);
2820 ast::ExprAddrOf(mutbl, ref oprnd) => {
2821 let hint = unpack_expected(
2823 |sty| match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty),
2825 let lvalue_pref = match mutbl {
2826 ast::MutMutable => PreferMutLvalue,
2827 ast::MutImmutable => NoPreference
2829 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**oprnd, hint, lvalue_pref);
2831 // Note: at this point, we cannot say what the best lifetime
2832 // is to use for resulting pointer. We want to use the
2833 // shortest lifetime possible so as to avoid spurious borrowck
2834 // errors. Moreover, the longest lifetime will depend on the
2835 // precise details of the value whose address is being taken
2836 // (and how long it is valid), which we don't know yet until type
2837 // inference is complete.
2839 // Therefore, here we simply generate a region variable. The
2840 // region inferencer will then select the ultimate value.
2841 // Finally, borrowck is charged with guaranteeing that the
2842 // value whose address was taken can actually be made to live
2843 // as long as it needs to live.
2844 let region = fcx.infcx().next_region_var(
2845 infer::AddrOfRegion(expr.span));
2847 let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
2848 let oprnd_t = if ty::type_is_error(tm.ty) {
2850 } else if ty::type_is_bot(tm.ty) {
2854 ty::mk_rptr(tcx, region, tm)
2856 fcx.write_ty(id, oprnd_t);
2858 ast::ExprPath(ref pth) => {
2859 let defn = lookup_def(fcx, pth.span, id);
2860 let pty = polytype_for_def(fcx, expr.span, defn);
2861 instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
2863 ast::ExprInlineAsm(ref ia) => {
2864 for &(_, ref input) in ia.inputs.iter() {
2865 check_expr(fcx, &**input);
2867 for &(_, ref out) in ia.outputs.iter() {
2868 check_expr(fcx, &**out);
2872 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
2873 ast::ExprBreak(_) => { fcx.write_bot(id); }
2874 ast::ExprAgain(_) => { fcx.write_bot(id); }
2875 ast::ExprRet(ref expr_opt) => {
2876 let ret_ty = fcx.ret_ty;
2878 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
2879 ret_ty, ty::mk_nil()) {
2880 Ok(_) => { /* fall through */ }
2884 "`return;` in function returning non-nil");
2888 check_expr_has_type(fcx, &**e, ret_ty);
2893 ast::ExprParen(ref a) => {
2894 check_expr_with_opt_hint_and_lvalue_pref(fcx, &**a, expected, lvalue_pref);
2895 fcx.write_ty(id, fcx.expr_ty(&**a));
2897 ast::ExprAssign(ref lhs, ref rhs) => {
2898 check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
2900 let tcx = fcx.tcx();
2901 if !ty::expr_is_lval(tcx, &**lhs) {
2902 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2905 let lhs_ty = fcx.expr_ty(&**lhs);
2906 check_expr_has_type(fcx, &**rhs, lhs_ty);
2907 let rhs_ty = fcx.expr_ty(&**rhs);
2909 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
2910 fcx.write_error(id);
2911 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
2917 ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
2918 check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
2919 id, expr.span, expected);
2921 ast::ExprWhile(ref cond, ref body) => {
2922 check_expr_has_type(fcx, &**cond, ty::mk_bool());
2923 check_block_no_value(fcx, &**body);
2924 let cond_ty = fcx.expr_ty(&**cond);
2925 let body_ty = fcx.node_ty(body.id);
2926 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
2927 fcx.write_error(id);
2929 else if ty::type_is_bot(cond_ty) {
2936 ast::ExprForLoop(..) =>
2937 fail!("non-desugared expr_for_loop"),
2938 ast::ExprLoop(ref body, _) => {
2939 check_block_no_value(fcx, &**body);
2940 if !may_break(tcx, expr.id, body.clone()) {
2947 ast::ExprMatch(ref discrim, ref arms) => {
2948 _match::check_match(fcx, expr, &**discrim, arms.as_slice());
2950 ast::ExprFnBlock(ref decl, ref body) => {
2951 let region = astconv::opt_ast_region_to_region(fcx,
2957 ty::RegionTraitStore(region, ast::MutMutable),
2962 ast::ExprProc(ref decl, ref body) => {
2970 ast::ExprBlock(ref b) => {
2971 check_block_with_expected(fcx, &**b, expected);
2972 fcx.write_ty(id, fcx.node_ty(b.id));
2974 ast::ExprCall(ref f, ref args) => {
2975 // Index expressions need to be handled separately, to inform them
2976 // that they appear in call position.
2977 check_expr(fcx, &**f);
2978 let f_ty = fcx.expr_ty(&**f);
2980 if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
2981 check_call(fcx, expr, &**f, args.as_slice());
2982 let (args_bot, args_err) = args.iter().fold((false, false),
2983 |(rest_bot, rest_err), a| {
2984 // is this not working?
2985 let a_ty = fcx.expr_ty(&**a);
2986 (rest_bot || ty::type_is_bot(a_ty),
2987 rest_err || ty::type_is_error(a_ty))});
2988 if ty::type_is_error(f_ty) || args_err {
2989 fcx.write_error(id);
2991 else if ty::type_is_bot(f_ty) || args_bot {
2996 ast::ExprMethodCall(ident, ref tps, ref args) => {
2997 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
2998 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
2999 let (args_bot, args_err) = arg_tys.fold((false, false),
3000 |(rest_bot, rest_err), a| {
3001 (rest_bot || ty::type_is_bot(a),
3002 rest_err || ty::type_is_error(a))});
3004 fcx.write_error(id);
3005 } else if args_bot {
3009 ast::ExprCast(ref e, ref t) => {
3010 check_expr(fcx, &**e);
3011 let t_1 = fcx.to_ty(&**t);
3012 let t_e = fcx.expr_ty(&**e);
3014 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
3015 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
3017 if ty::type_is_error(t_e) {
3018 fcx.write_error(id);
3020 else if ty::type_is_bot(t_e) {
3024 match ty::get(t_1).sty {
3025 // This will be looked up later on
3026 _ if ty::type_is_trait(t_1) => {},
3029 let t_1 = structurally_resolved_type(fcx, e.span, t_1);
3030 let t_e = structurally_resolved_type(fcx, e.span, t_e);
3032 if ty::type_is_nil(t_e) {
3033 fcx.type_error_message(expr.span, |actual| {
3034 format!("cast from nil: `{}` as `{}`",
3036 fcx.infcx().ty_to_str(t_1))
3038 } else if ty::type_is_nil(t_1) {
3039 fcx.type_error_message(expr.span, |actual| {
3040 format!("cast to nil: `{}` as `{}`",
3042 fcx.infcx().ty_to_str(t_1))
3046 let t_1_is_scalar = ty::type_is_scalar(t_1);
3047 let t_1_is_char = ty::type_is_char(t_1);
3048 let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
3049 let t_1_is_float = ty::type_is_floating_point(t_1);
3051 // casts to scalars other than `char` and `bare fn` are trivial
3052 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
3053 if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
3055 fcx.type_error_message(expr.span, |actual| {
3056 format!("illegal cast; cast through an \
3057 integer first: `{}` as `{}`",
3059 fcx.infcx().ty_to_str(t_1))
3062 // casts from C-like enums are allowed
3063 } else if t_1_is_char {
3064 let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
3065 if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
3066 fcx.type_error_message(expr.span, |actual| {
3067 format!("only `u8` can be cast as \
3068 `char`, not `{}`", actual)
3071 } else if ty::get(t_1).sty == ty::ty_bool {
3074 .span_err(expr.span,
3075 "cannot cast as `bool`, compare with \
3077 } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
3078 fn is_vec(t: ty::t) -> bool {
3079 match ty::get(t).sty {
3080 ty::ty_vec(..) => true,
3081 ty::ty_ptr(ty::mt{ty: t, ..}) | ty::ty_rptr(_, ty::mt{ty: t, ..}) |
3082 ty::ty_box(t) | ty::ty_uniq(t) => match ty::get(t).sty {
3083 ty::ty_vec(_, None) => true,
3089 fn types_compatible(fcx: &FnCtxt, sp: Span,
3090 t1: ty::t, t2: ty::t) -> bool {
3094 let el = ty::sequence_element_type(fcx.tcx(),
3096 infer::mk_eqty(fcx.infcx(), false,
3097 infer::Misc(sp), el, t2).is_ok()
3101 // Due to the limitations of LLVM global constants,
3102 // region pointers end up pointing at copies of
3103 // vector elements instead of the original values.
3104 // To allow unsafe pointers to work correctly, we
3105 // need to special-case obtaining an unsafe pointer
3106 // from a region pointer to a vector.
3108 /* this cast is only allowed from &[T] to *T or
3110 match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
3111 (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
3112 &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
3113 if types_compatible(fcx, e.span, mt1, mt2) => {
3114 /* this case is allowed */
3117 demand::coerce(fcx, e.span, t_1, &**e);
3120 } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
3122 If more type combinations should be supported than are
3123 supported here, then file an enhancement issue and
3124 record the issue number in this comment.
3126 fcx.type_error_message(expr.span, |actual| {
3127 format!("non-scalar cast: `{}` as `{}`",
3129 fcx.infcx().ty_to_str(t_1))
3134 fcx.write_ty(id, t_1);
3137 ast::ExprVec(ref args) => {
3138 let t: ty::t = fcx.infcx().next_ty_var();
3139 for e in args.iter() {
3140 check_expr_has_type(fcx, &**e, t);
3142 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3144 fcx.write_ty(id, typ);
3146 ast::ExprRepeat(ref element, ref count_expr) => {
3147 check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
3148 let count = ty::eval_repeat_count(fcx, &**count_expr);
3149 let t: ty::t = fcx.infcx().next_ty_var();
3150 check_expr_has_type(fcx, &**element, t);
3151 let element_ty = fcx.expr_ty(&**element);
3152 if ty::type_is_error(element_ty) {
3153 fcx.write_error(id);
3155 else if ty::type_is_bot(element_ty) {
3159 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3161 fcx.write_ty(id, t);
3164 ast::ExprTup(ref elts) => {
3165 let flds = unpack_expected(fcx, expected, |sty| {
3167 ty::ty_tup(ref flds) => Some((*flds).clone()),
3171 let mut bot_field = false;
3172 let mut err_field = false;
3174 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3175 let opt_hint = match flds {
3176 Some(ref fs) if i < fs.len() => Some(*fs.get(i)),
3179 check_expr_with_opt_hint(fcx, &**e, opt_hint);
3180 let t = fcx.expr_ty(&**e);
3181 err_field = err_field || ty::type_is_error(t);
3182 bot_field = bot_field || ty::type_is_bot(t);
3187 } else if err_field {
3188 fcx.write_error(id);
3190 let typ = ty::mk_tup(tcx, elt_ts);
3191 fcx.write_ty(id, typ);
3194 ast::ExprStruct(ref path, ref fields, base_expr) => {
3195 // Resolve the path.
3196 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3198 Some(def::DefStruct(type_def_id)) => {
3199 check_struct_constructor(fcx, id, expr.span, type_def_id,
3200 fields.as_slice(), base_expr);
3202 Some(def::DefVariant(enum_id, variant_id, _)) => {
3203 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3204 variant_id, fields.as_slice());
3207 tcx.sess.span_bug(path.span,
3208 "structure constructor does not name a structure type");
3212 ast::ExprField(ref base, ref field, ref tys) => {
3213 check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
3215 ast::ExprIndex(ref base, ref idx) => {
3216 check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3217 check_expr(fcx, &**idx);
3218 let raw_base_t = fcx.expr_ty(&**base);
3219 let idx_t = fcx.expr_ty(&**idx);
3220 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3221 fcx.write_ty(id, raw_base_t);
3222 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3223 fcx.write_ty(id, idx_t);
3225 let (base_t, autoderefs, field_ty) =
3226 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3227 lvalue_pref, |base_t, _| ty::index(base_t));
3230 check_expr_has_type(fcx, &**idx, ty::mk_uint());
3231 fcx.write_ty(id, mt.ty);
3232 fcx.write_autoderef_adjustment(base.id, autoderefs);
3235 let resolved = structurally_resolved_type(fcx,
3238 let ret_ty = lookup_op_method(fcx,
3241 token::intern("index"),
3242 tcx.lang_items.index_trait(),
3243 [base.clone(), idx.clone()],
3246 fcx.type_error_message(expr.span,
3248 format!("cannot index a \
3255 fcx.write_ty(id, ret_ty);
3262 debug!("type of expr({}) {} is...", expr.id,
3263 syntax::print::pprust::expr_to_str(expr));
3264 debug!("... {}, expected is {}",
3265 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3267 Some(t) => ppaux::ty_to_str(tcx, t),
3268 _ => "empty".to_string()
3274 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3275 if !type_is_uint(fcx, sp, t) {
3276 fcx.type_error_message(sp, |actual| {
3277 format!("mismatched types: expected `uint` type but found `{}`",
3283 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3284 if !type_is_integral(fcx, sp, t) {
3285 fcx.type_error_message(sp, |actual| {
3286 format!("mismatched types: expected integral type but found `{}`",
3292 pub fn check_decl_initializer(fcx: &FnCtxt,
3296 let local_ty = fcx.local_ty(init.span, nid);
3297 check_expr_coercable_to_type(fcx, init, local_ty)
3300 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3301 let tcx = fcx.ccx.tcx;
3303 let t = fcx.local_ty(local.span, local.id);
3304 fcx.write_ty(local.id, t);
3308 check_decl_initializer(fcx, local.id, &**init);
3309 let init_ty = fcx.expr_ty(&**init);
3310 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3311 fcx.write_ty(local.id, init_ty);
3317 let pcx = pat_ctxt {
3319 map: pat_id_map(&tcx.def_map, &*local.pat),
3321 _match::check_pat(&pcx, &*local.pat, t);
3322 let pat_ty = fcx.node_ty(local.pat.id);
3323 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3324 fcx.write_ty(local.id, pat_ty);
3328 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3330 let mut saw_bot = false;
3331 let mut saw_err = false;
3333 ast::StmtDecl(decl, id) => {
3336 ast::DeclLocal(ref l) => {
3337 check_decl_local(fcx, &**l);
3338 let l_t = fcx.node_ty(l.id);
3339 saw_bot = saw_bot || ty::type_is_bot(l_t);
3340 saw_err = saw_err || ty::type_is_error(l_t);
3342 ast::DeclItem(_) => {/* ignore for now */ }
3345 ast::StmtExpr(ref expr, id) => {
3347 // Check with expected type of ()
3348 check_expr_has_type(fcx, &**expr, ty::mk_nil());
3349 let expr_ty = fcx.expr_ty(&**expr);
3350 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3351 saw_err = saw_err || ty::type_is_error(expr_ty);
3353 ast::StmtSemi(ref expr, id) => {
3355 check_expr(fcx, &**expr);
3356 let expr_ty = fcx.expr_ty(&**expr);
3357 saw_bot |= ty::type_is_bot(expr_ty);
3358 saw_err |= ty::type_is_error(expr_ty);
3360 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3363 fcx.write_bot(node_id);
3366 fcx.write_error(node_id);
3369 fcx.write_nil(node_id)
3373 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3374 check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
3375 let blkty = fcx.node_ty(blk.id);
3376 if ty::type_is_error(blkty) {
3377 fcx.write_error(blk.id);
3379 else if ty::type_is_bot(blkty) {
3380 fcx.write_bot(blk.id);
3383 let nilty = ty::mk_nil();
3384 demand::suptype(fcx, blk.span, nilty, blkty);
3388 pub fn check_block_with_expected(fcx: &FnCtxt,
3390 expected: Option<ty::t>) {
3392 let mut fcx_ps = fcx.ps.borrow_mut();
3393 let fn_style_state = fcx_ps.recurse(blk);
3394 replace(&mut *fcx_ps, fn_style_state)
3397 fcx.with_region_lb(blk.id, || {
3398 let mut warned = false;
3399 let mut last_was_bot = false;
3400 let mut any_bot = false;
3401 let mut any_err = false;
3402 for s in blk.stmts.iter() {
3403 check_stmt(fcx, &**s);
3404 let s_id = ast_util::stmt_id(&**s);
3405 let s_ty = fcx.node_ty(s_id);
3406 if last_was_bot && !warned && match s.node {
3407 ast::StmtDecl(decl, _) => {
3409 ast::DeclLocal(_) => true,
3413 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3419 .add_lint(UnreachableCode,
3422 "unreachable statement".to_string());
3425 if ty::type_is_bot(s_ty) {
3426 last_was_bot = true;
3428 any_bot = any_bot || ty::type_is_bot(s_ty);
3429 any_err = any_err || ty::type_is_error(s_ty);
3432 None => if any_err {
3433 fcx.write_error(blk.id);
3436 fcx.write_bot(blk.id);
3439 fcx.write_nil(blk.id);
3442 if any_bot && !warned {
3446 .add_lint(UnreachableCode,
3449 "unreachable expression".to_string());
3451 check_expr_with_opt_hint(fcx, &*e, expected);
3452 let ety = fcx.expr_ty(&*e);
3453 fcx.write_ty(blk.id, ety);
3455 fcx.write_error(blk.id);
3458 fcx.write_bot(blk.id);
3464 *fcx.ps.borrow_mut() = prev;
3467 pub fn check_const(ccx: &CrateCtxt,
3471 let inh = blank_inherited_fields(ccx);
3472 let rty = ty::node_id_to_type(ccx.tcx, id);
3473 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3474 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3475 check_const_with_ty(&fcx, sp, e, declty);
3478 pub fn check_const_with_ty(fcx: &FnCtxt,
3482 // Gather locals in statics (because of block expressions).
3483 // This is technically unnecessary because locals in static items are forbidden,
3484 // but prevents type checking from blowing up before const checking can properly
3486 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3489 let cty = fcx.expr_ty(e);
3490 demand::suptype(fcx, e.span, declty, cty);
3491 regionck::regionck_expr(fcx, e);
3492 writeback::resolve_type_vars_in_expr(fcx, e);
3495 /// Checks whether a type can be represented in memory. In particular, it
3496 /// identifies types that contain themselves without indirection through a
3497 /// pointer, which would mean their size is unbounded. This is different from
3498 /// the question of whether a type can be instantiated. See the definition of
3499 /// `check_instantiable`.
3500 pub fn check_representable(tcx: &ty::ctxt,
3502 item_id: ast::NodeId,
3503 designation: &str) -> bool {
3504 let rty = ty::node_id_to_type(tcx, item_id);
3506 // Check that it is possible to represent this type. This call identifies
3507 // (1) types that contain themselves and (2) types that contain a different
3508 // recursive type. It is only necessary to throw an error on those that
3509 // contain themselves. For case 2, there must be an inner type that will be
3510 // caught by case 1.
3511 match ty::is_type_representable(tcx, sp, rty) {
3512 ty::SelfRecursive => {
3514 sp, format!("illegal recursive {} type; \
3515 wrap the inner value in a box to make it representable",
3516 designation).as_slice());
3519 ty::Representable | ty::ContainsRecursive => (),
3524 /// Checks whether a type can be created without an instance of itself.
3525 /// This is similar but different from the question of whether a type
3526 /// can be represented. For example, the following type:
3528 /// enum foo { None, Some(foo) }
3530 /// is instantiable but is not representable. Similarly, the type
3532 /// enum foo { Some(@foo) }
3534 /// is representable, but not instantiable.
3535 pub fn check_instantiable(tcx: &ty::ctxt,
3537 item_id: ast::NodeId)
3539 let item_ty = ty::node_id_to_type(tcx, item_id);
3540 if !ty::is_instantiable(tcx, item_ty) {
3543 format!("this type cannot be instantiated without an \
3544 instance of itself; consider using \
3546 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3553 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3554 let t = ty::node_id_to_type(tcx, id);
3555 if ty::type_needs_subst(t) {
3556 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3559 match ty::get(t).sty {
3560 ty::ty_struct(did, ref substs) => {
3561 let fields = ty::lookup_struct_fields(tcx, did);
3562 if fields.is_empty() {
3563 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3566 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3567 if !fields.iter().all(
3568 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3569 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3572 if !ty::type_is_machine(e) {
3573 tcx.sess.span_err(sp, "SIMD vector element type should be \
3582 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3583 vs: &[ast::P<ast::Variant>]) {
3584 for &v in vs.iter() {
3586 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3587 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3588 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3589 let len = arg_tys.len();
3593 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3594 // Allow the last field in an enum to be unsized.
3595 // We want to do this so that we can support smart pointers.
3596 // A struct value with an unsized final field is itself
3597 // unsized and we must track this in the type system.
3598 if !ty::type_is_sized(ccx.tcx, *t) {
3602 args.get(i).ty.span,
3603 format!("type `{}` is dynamically sized. \
3604 dynamically sized types may only \
3605 appear as the final type in a \
3607 ppaux::ty_to_str(ccx.tcx,
3612 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
3618 pub fn check_enum_variants(ccx: &CrateCtxt,
3620 vs: &[ast::P<ast::Variant>],
3623 fn disr_in_range(ccx: &CrateCtxt,
3625 disr: ty::Disr) -> bool {
3626 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3628 ast::TyU8 => disr as u8 as Disr == disr,
3629 ast::TyU16 => disr as u16 as Disr == disr,
3630 ast::TyU32 => disr as u32 as Disr == disr,
3631 ast::TyU64 => disr as u64 as Disr == disr,
3632 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3635 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3637 ast::TyI8 => disr as i8 as Disr == disr,
3638 ast::TyI16 => disr as i16 as Disr == disr,
3639 ast::TyI32 => disr as i32 as Disr == disr,
3640 ast::TyI64 => disr as i64 as Disr == disr,
3641 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3645 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3646 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3650 fn do_check(ccx: &CrateCtxt,
3651 vs: &[ast::P<ast::Variant>],
3653 hint: attr::ReprAttr)
3654 -> Vec<Rc<ty::VariantInfo>> {
3656 let rty = ty::node_id_to_type(ccx.tcx, id);
3657 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3658 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3659 let mut prev_disr_val: Option<ty::Disr> = None;
3661 for &v in vs.iter() {
3663 // If the discriminant value is specified explicitly in the enum check whether the
3664 // initialization expression is valid, otherwise use the last value plus one.
3665 let mut current_disr_val = match prev_disr_val {
3666 Some(prev_disr_val) => prev_disr_val + 1,
3667 None => ty::INITIAL_DISCRIMINANT_VALUE
3670 match v.node.disr_expr {
3672 debug!("disr expr, checking {}", pprust::expr_to_str(&*e));
3674 let inh = blank_inherited_fields(ccx);
3675 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3676 let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
3677 check_const_with_ty(&fcx, e.span, &*e, declty);
3678 // check_expr (from check_const pass) doesn't guarantee
3679 // that the expression is in a form that eval_const_expr can
3680 // handle, so we may still get an internal compiler error
3682 match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
3683 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3684 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3686 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3692 format!("expected constant: {}",
3700 // Check for duplicate discriminant values
3701 if disr_vals.contains(¤t_disr_val) {
3702 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3704 // Check for unrepresentable discriminant values
3706 attr::ReprAny | attr::ReprExtern => (),
3707 attr::ReprInt(sp, ity) => {
3708 if !disr_in_range(ccx, ity, current_disr_val) {
3709 ccx.tcx.sess.span_err(v.span,
3710 "discriminant value outside specified type");
3711 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3715 disr_vals.push(current_disr_val);
3717 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
3719 prev_disr_val = Some(current_disr_val);
3721 variants.push(variant_info);
3727 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3728 if hint != attr::ReprAny && vs.len() <= 1 {
3729 let msg = if vs.len() == 1 {
3730 "unsupported representation for univariant enum"
3732 "unsupported representation for zero-variant enum"
3734 ccx.tcx.sess.span_err(sp, msg)
3737 let variants = do_check(ccx, vs, id, hint);
3739 // cache so that ty::enum_variants won't repeat this work
3740 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3742 check_representable(ccx.tcx, sp, id, "enum");
3744 // Check that it is possible to instantiate this enum:
3746 // This *sounds* like the same that as representable, but it's
3747 // not. See def'n of `check_instantiable()` for details.
3748 check_instantiable(ccx.tcx, sp, id);
3751 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
3752 lookup_def_ccx(fcx.ccx, sp, id)
3755 // Returns the type parameter count and the type for the given definition.
3756 pub fn polytype_for_def(fcx: &FnCtxt,
3761 def::DefArg(nid, _) | def::DefLocal(nid, _) |
3762 def::DefBinding(nid, _) => {
3763 let typ = fcx.local_ty(sp, nid);
3764 return no_params(typ);
3766 def::DefFn(id, _) | def::DefStaticMethod(id, _, _) |
3767 def::DefStatic(id, _) | def::DefVariant(_, id, _) |
3768 def::DefStruct(id) => {
3769 return ty::lookup_item_type(fcx.ccx.tcx, id);
3771 def::DefUpvar(_, inner, _, _) => {
3772 return polytype_for_def(fcx, sp, *inner);
3777 def::DefTyParam(..)=> {
3778 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3780 def::DefMod(..) | def::DefForeignMod(..) => {
3781 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3783 def::DefUse(..) => {
3784 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3786 def::DefRegion(..) => {
3787 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3789 def::DefTyParamBinder(..) => {
3790 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3792 def::DefLabel(..) => {
3793 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3795 def::DefSelfTy(..) => {
3796 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3798 def::DefMethod(..) => {
3799 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3804 // Instantiates the given path, which must refer to an item with the given
3805 // number of type parameters and type.
3806 pub fn instantiate_path(fcx: &FnCtxt,
3811 node_id: ast::NodeId) {
3812 debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
3813 path.repr(fcx.tcx()),
3814 def.repr(fcx.tcx()),
3816 polytype.repr(fcx.tcx()));
3818 // We need to extract the type parameters supplied by the user in
3819 // the path `path`. Due to the current setup, this is a bit of a
3820 // tricky-process; the problem is that resolve only tells us the
3821 // end-point of the path resolution, and not the intermediate steps.
3822 // Luckily, we can (at least for now) deduce the intermediate steps
3823 // just from the end-point.
3825 // There are basically three cases to consider:
3827 // 1. Reference to a *type*, such as a struct or enum:
3829 // mod a { struct Foo<T> { ... } }
3831 // Because we don't allow types to be declared within one
3832 // another, a path that leads to a type will always look like
3833 // `a::b::Foo<T>` where `a` and `b` are modules. This implies
3834 // that only the final segment can have type parameters, and
3835 // they are located in the TypeSpace.
3837 // *Note:* Generally speaking, references to types don't
3838 // actually pass through this function, but rather the
3839 // `ast_ty_to_ty` function in `astconv`. However, in the case
3840 // of struct patterns (and maybe literals) we do invoke
3841 // `instantiate_path` to get the general type of an instance of
3842 // a struct. (In these cases, there are actually no type
3843 // parameters permitted at present, but perhaps we will allow
3844 // them in the future.)
3846 // 1b. Reference to a enum variant or tuple-like struct:
3848 // struct foo<T>(...)
3849 // enum E<T> { foo(...) }
3851 // In these cases, the parameters are declared in the type
3854 // 2. Reference to a *fn item*:
3858 // In this case, the path will again always have the form
3859 // `a::b::foo::<T>` where only the final segment should have
3860 // type parameters. However, in this case, those parameters are
3861 // declared on a value, and hence are in the `FnSpace`.
3863 // 3. Reference to a *method*:
3865 // impl<A> SomeStruct<A> {
3869 // Here we can have a path like
3870 // `a::b::SomeStruct::<A>::foo::<B>`, in which case parameters
3871 // may appear in two places. The penultimate segment,
3872 // `SomeStruct::<A>`, contains parameters in TypeSpace, and the
3873 // final segment, `foo::<B>` contains parameters in fn space.
3875 // The first step then is to categorize the segments appropriately.
3877 assert!(path.segments.len() >= 1);
3878 let mut segment_spaces;
3880 // Case 1 and 1b. Reference to a *type* or *enum variant*.
3881 def::DefSelfTy(..) |
3882 def::DefStruct(..) |
3883 def::DefVariant(..) |
3884 def::DefTyParamBinder(..) |
3887 def::DefPrimTy(..) |
3888 def::DefTyParam(..) => {
3889 // Everything but the final segment should have no
3890 // parameters at all.
3891 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
3892 segment_spaces.push(Some(subst::TypeSpace));
3895 // Case 2. Reference to a top-level value.
3897 def::DefStatic(..) => {
3898 segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
3899 segment_spaces.push(Some(subst::FnSpace));
3902 // Case 3. Reference to a method.
3903 def::DefStaticMethod(..) => {
3904 assert!(path.segments.len() >= 2);
3905 segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
3906 segment_spaces.push(Some(subst::TypeSpace));
3907 segment_spaces.push(Some(subst::FnSpace));
3910 // Other cases. Various nonsense that really shouldn't show up
3911 // here. If they do, an error will have been reported
3912 // elsewhere. (I hope)
3914 def::DefForeignMod(..) |
3917 def::DefMethod(..) |
3918 def::DefBinding(..) |
3920 def::DefRegion(..) |
3922 def::DefUpvar(..) => {
3923 segment_spaces = Vec::from_elem(path.segments.len(), None);
3926 assert_eq!(segment_spaces.len(), path.segments.len());
3928 debug!("segment_spaces={}", segment_spaces);
3930 // Next, examine the definition, and determine how many type
3931 // parameters we expect from each space.
3932 let type_defs = &polytype.generics.types;
3933 let region_defs = &polytype.generics.regions;
3935 // Now that we have categorized what space the parameters for each
3936 // segment belong to, let's sort out the parameters that the user
3937 // provided (if any) into their appropriate spaces. We'll also report
3938 // errors if type parameters are provided in an inappropriate place.
3939 let mut substs = Substs::empty();
3940 for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
3943 report_error_if_segment_contains_type_parameters(fcx, segment);
3947 push_explicit_parameters_from_segment_to_substs(fcx,
3957 // Now we have to compare the types that the user *actually*
3958 // provided against the types that were *expected*. If the user
3959 // did not provide any types, then we want to substitute inference
3960 // variables. If the user provided some types, we may still need
3961 // to add defaults. If the user provided *too many* types, that's
3963 for &space in ParamSpace::all().iter() {
3964 adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
3965 assert_eq!(substs.types.get_vec(space).len(),
3966 type_defs.get_vec(space).len());
3968 adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
3969 assert_eq!(substs.regions().get_vec(space).len(),
3970 region_defs.get_vec(space).len());
3973 fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
3977 fn report_error_if_segment_contains_type_parameters(
3979 segment: &ast::PathSegment)
3981 for typ in segment.types.iter() {
3982 fcx.tcx().sess.span_err(
3984 "type parameters may not appear here");
3988 for lifetime in segment.lifetimes.iter() {
3989 fcx.tcx().sess.span_err(
3991 "lifetime parameters may not appear here");
3996 fn push_explicit_parameters_from_segment_to_substs(
3998 space: subst::ParamSpace,
3999 type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
4000 region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
4001 segment: &ast::PathSegment,
4002 substs: &mut Substs)
4005 * Finds the parameters that the user provided and adds them
4006 * to `substs`. If too many parameters are provided, then
4007 * reports an error and clears the output vector.
4009 * We clear the output vector because that will cause the
4010 * `adjust_XXX_parameters()` later to use inference
4011 * variables. This seems less likely to lead to derived
4014 * Note that we *do not* check for *too few* parameters here.
4015 * Due to the presence of defaults etc that is more
4016 * complicated. I wanted however to do the reporting of *too
4017 * many* parameters here because we can easily use the precise
4018 * span of the N+1'th parameter.
4022 let type_count = type_defs.get_vec(space).len();
4023 assert_eq!(substs.types.get_vec(space).len(), 0);
4024 for (i, &typ) in segment.types.iter().enumerate() {
4025 let t = fcx.to_ty(&*typ);
4027 substs.types.push(space, t);
4028 } else if i == type_count {
4029 fcx.tcx().sess.span_err(
4032 "too many type parameters provided: \
4033 expected at most {} parameter(s) \
4034 but found {} parameter(s)",
4036 segment.types.len()).as_slice());
4037 substs.types.get_mut_vec(space).truncate(0);
4043 let region_count = region_defs.get_vec(space).len();
4044 assert_eq!(substs.regions().get_vec(space).len(), 0);
4045 for (i, lifetime) in segment.lifetimes.iter().enumerate() {
4046 let r = ast_region_to_region(fcx.tcx(), lifetime);
4047 if i < region_count {
4048 substs.mut_regions().push(space, r);
4049 } else if i == region_count {
4050 fcx.tcx().sess.span_err(
4053 "too many lifetime parameters provided: \
4054 expected {} parameter(s) but found {} parameter(s)",
4056 segment.lifetimes.len()).as_slice());
4057 substs.mut_regions().get_mut_vec(space).truncate(0);
4063 fn adjust_type_parameters(
4067 defs: &VecPerParamSpace<ty::TypeParameterDef>,
4068 substs: &mut Substs)
4070 let provided_len = substs.types.get_vec(space).len();
4071 let desired = defs.get_vec(space).as_slice();
4072 let required_len = desired.iter()
4073 .take_while(|d| d.default.is_none())
4076 debug!("adjust_type_parameters(space={}, \
4085 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4086 assert!(provided_len <= desired.len());
4088 // Nothing specified at all: supply inference variables for
4090 if provided_len == 0 {
4091 let provided = substs.types.get_mut_vec(space);
4092 *provided = fcx.infcx().next_ty_vars(desired.len());
4096 // Too few parameters specified: report an error and use Err
4098 if provided_len < required_len {
4100 if desired.len() != required_len { "at least " } else { "" };
4101 fcx.tcx().sess.span_err(
4103 format!("too few type parameters provided: \
4104 expected {}{} parameter(s) \
4105 but found {} parameter(s)",
4108 provided_len).as_slice());
4109 let provided = substs.types.get_mut_vec(space);
4110 *provided = Vec::from_elem(desired.len(), ty::mk_err());
4114 // Otherwise, add in any optional parameters that the user
4115 // omitted. The case of *too many* parameters is handled
4117 // push_explicit_parameters_from_segment_to_substs(). Note
4118 // that the *default* type are expressed in terms of all prior
4119 // parameters, so we have to substitute as we go with the
4120 // partial substitution that we have built up.
4121 for i in range(provided_len, desired.len()) {
4122 let default = desired[i].default.unwrap();
4123 let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
4124 substs.types.push(space, default);
4126 assert_eq!(substs.types.get_vec(space).len(), desired.len());
4128 debug!("Final substs: {}", substs.repr(fcx.tcx()));
4131 fn adjust_region_parameters(
4135 defs: &VecPerParamSpace<ty::RegionParameterDef>,
4136 substs: &mut Substs)
4138 let provided = substs.mut_regions().get_mut_vec(space);
4139 let desired = defs.get_vec(space);
4141 // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
4142 assert!(provided.len() <= desired.len());
4144 // If nothing was provided, just use inference variables.
4145 if provided.len() == 0 {
4146 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4150 // If just the right number were provided, everybody is happy.
4151 if provided.len() == desired.len() {
4155 // Otherwise, too few were provided. Report an error and then
4156 // use inference variables.
4157 fcx.tcx().sess.span_err(
4160 "too few lifetime parameters provided: \
4161 expected {} parameter(s) \
4162 but found {} parameter(s)",
4164 provided.len()).as_slice());
4166 *provided = fcx.infcx().region_vars_for_defs(span, desired);
4170 // Resolves `typ` by a single level if `typ` is a type variable. If no
4171 // resolution is possible, then an error is reported.
4172 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4173 match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
4174 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4176 fcx.type_error_message(sp, |_actual| {
4177 "the type of this value must be known in this \
4178 context".to_string()
4180 demand::suptype(fcx, sp, ty::mk_err(), tp);
4186 // Returns the one-level-deep structure of the given type.
4187 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4189 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4192 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4193 let typ_s = structurally_resolved_type(fcx, sp, typ);
4194 return ty::type_is_integral(typ_s);
4197 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4198 let typ_s = structurally_resolved_type(fcx, sp, typ);
4199 return ty::type_is_uint(typ_s);
4202 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4205 mk_inner: || -> ty::mt)
4208 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4209 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4211 ast::ExprLit(..) => {
4212 // string literals and *empty slices* live in static memory
4213 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4215 ast::ExprVec(ref elements) if elements.len() == 0 => {
4216 // string literals and *empty slices* live in static memory
4217 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4219 ast::ExprRepeat(..) |
4220 ast::ExprVec(..) => {
4221 // vector literals are temporaries on the stack
4222 match fcx.tcx().region_maps.temporary_scope(e.id) {
4223 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4224 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4228 fcx.ccx.tcx.sess.span_bug(e.span,
4229 "vstore with unexpected \
4237 // Returns true if b contains a break that can exit from b
4238 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4239 // First: is there an unlabeled break immediately
4241 (loop_query(&*b, |e| {
4243 ast::ExprBreak(_) => true,
4247 // Second: is there a labeled break with label
4248 // <id> nested anywhere inside the loop?
4249 (block_query(b, |e| {
4251 ast::ExprBreak(Some(_)) => {
4252 match cx.def_map.borrow().find(&e.id) {
4253 Some(&def::DefLabel(loop_id)) if id == loop_id => true,
4261 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4263 tps: &OwnedSlice<ast::TyParam>,
4265 debug!("check_bounds_are_used(n_tps={}, ty={})",
4266 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4268 // make a vector of booleans initially false, set to true when used
4269 if tps.len() == 0u { return; }
4270 let mut tps_used = Vec::from_elem(tps.len(), false);
4272 ty::walk_ty(ty, |t| {
4273 match ty::get(t).sty {
4274 ty::ty_param(ParamTy {idx, ..}) => {
4275 debug!("Found use of ty param num {}", idx);
4276 *tps_used.get_mut(idx) = true;
4282 for (i, b) in tps_used.iter().enumerate() {
4284 ccx.tcx.sess.span_err(
4286 format!("type parameter `{}` is unused",
4287 token::get_ident(tps.get(i).ident)).as_slice());
4292 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4293 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4294 ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
4298 let name = token::get_ident(it.ident);
4299 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4300 let split : Vec<&str> = name.get().split('_').collect();
4301 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4303 //We only care about the operation here
4304 match *split.get(1) {
4305 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4309 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4311 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4314 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4315 "min" | "umax" | "umin" => {
4316 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4320 (0, Vec::new(), ty::mk_nil())
4323 tcx.sess.span_err(it.span,
4324 format!("unrecognized atomic operation \
4333 "abort" => (0, Vec::new(), ty::mk_bot()),
4334 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4336 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4337 "init" => (1u, Vec::new(), param(ccx, 0u)),
4338 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4339 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4340 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4341 "move_val_init" => {
4344 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4349 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4350 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4353 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4355 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4357 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4359 mutbl: ast::MutImmutable
4361 (1u, Vec::new(), td_ptr)
4364 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4368 ty::mk_struct(ccx.tcx, did,
4369 subst::Substs::empty())),
4371 tcx.sess.span_fatal(it.span, msg.as_slice());
4376 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4378 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4380 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4381 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4382 Ok((_, vot)) => vot,
4383 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4386 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4388 mutbl: ast::MutImmutable
4390 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4395 ty::mk_ptr(tcx, ty::mt {
4397 mutbl: ast::MutImmutable
4401 ty::mk_ptr(tcx, ty::mt {
4403 mutbl: ast::MutImmutable
4406 "copy_memory" | "copy_nonoverlapping_memory" |
4407 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4410 ty::mk_ptr(tcx, ty::mt {
4412 mutbl: ast::MutMutable
4414 ty::mk_ptr(tcx, ty::mt {
4416 mutbl: ast::MutImmutable
4422 "set_memory" | "volatile_set_memory" => {
4425 ty::mk_ptr(tcx, ty::mt {
4427 mutbl: ast::MutMutable
4434 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4435 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4438 vec!( ty::mk_f32(), ty::mk_i32() ),
4443 vec!( ty::mk_f64(), ty::mk_i32() ),
4446 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4447 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4448 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4449 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4452 vec!( ty::mk_f32(), ty::mk_f32() ),
4457 vec!( ty::mk_f64(), ty::mk_f64() ),
4460 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4461 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4462 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4463 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4464 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4465 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4466 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4467 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4468 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4469 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4472 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4477 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4480 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4481 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4482 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4483 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4484 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4485 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4486 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4487 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4488 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4489 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4490 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4491 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4492 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4493 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4494 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4495 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4496 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4497 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4498 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4499 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4500 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4501 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4502 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4503 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4504 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4505 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4506 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4507 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4508 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4509 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4510 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4513 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4515 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4517 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4518 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4519 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4521 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4522 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4523 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4525 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4526 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4527 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4529 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4530 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4531 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4533 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4534 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4535 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4537 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4538 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4539 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4541 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4542 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4543 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4545 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4546 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4547 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4550 tcx.sess.span_err(it.span,
4551 format!("unrecognized intrinsic function: `{}`",
4552 *other).as_slice());
4557 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4558 fn_style: ast::UnsafeFn,
4559 abi: abi::RustIntrinsic,
4567 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4568 let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
4569 if i_n_tps != n_tps {
4570 tcx.sess.span_err(it.span,
4571 format!("intrinsic has wrong number of type \
4572 parameters: found {}, expected {}",
4576 require_same_types(tcx,
4583 format!("intrinsic has wrong type: expected `{}`",
4584 ppaux::ty_to_str(ccx.tcx, fty))