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;
81 use middle::lang_items::{ExchangeHeapLangItem, GcLangItem};
82 use middle::lang_items::{ManagedHeapLangItem};
83 use middle::lint::UnreachableCode;
84 use middle::pat_util::pat_id_map;
86 use middle::subst::Subst;
87 use middle::ty::{FnSig, VariantInfo};
88 use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
89 use middle::ty::{substs, param_ty, Disr, ExprTyProvider};
91 use middle::ty_fold::TypeFolder;
92 use middle::typeck::astconv::AstConv;
93 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
94 use middle::typeck::astconv;
95 use middle::typeck::check::_match::pat_ctxt;
96 use middle::typeck::check::method::{AutoderefReceiver};
97 use middle::typeck::check::method::{AutoderefReceiverFlag};
98 use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
99 use middle::typeck::check::method::{DontAutoderefReceiver};
100 use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
101 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
102 use middle::typeck::check::regionmanip::relate_free_regions;
103 use middle::typeck::check::vtable::VtableContext;
104 use middle::typeck::CrateCtxt;
105 use middle::typeck::infer::{resolve_type, force_tvar};
106 use middle::typeck::infer;
107 use middle::typeck::rscope::RegionScope;
108 use middle::typeck::{lookup_def_ccx};
109 use middle::typeck::no_params;
110 use middle::typeck::{require_same_types, vtable_map};
111 use middle::typeck::{MethodCall, MethodMap};
112 use middle::lang_items::TypeIdLangItem;
113 use util::common::{block_query, indenter, loop_query};
115 use util::ppaux::{UserString, Repr};
116 use util::nodemap::{FnvHashMap, NodeMap};
118 use std::cell::{Cell, RefCell};
119 use collections::HashMap;
120 use std::mem::replace;
124 use syntax::ast::{Provided, Required};
127 use syntax::ast_util::local_def;
128 use syntax::ast_util;
130 use syntax::codemap::Span;
132 use syntax::owned_slice::OwnedSlice;
133 use syntax::parse::token;
134 use syntax::print::pprust;
136 use syntax::visit::Visitor;
147 /// Fields that are part of a `FnCtxt` which are inherited by
148 /// closures defined within the function. For example:
151 /// bar(proc() { ... })
154 /// Here, the function `foo()` and the closure passed to
155 /// `bar()` will each have their own `FnCtxt`, but they will
156 /// share the inherited fields.
157 pub struct Inherited<'a> {
158 infcx: infer::InferCtxt<'a>,
159 locals: RefCell<NodeMap<ty::t>>,
160 param_env: ty::ParameterEnvironment,
163 node_types: RefCell<NodeMap<ty::t>>,
164 item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
165 adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
166 method_map: MethodMap,
167 vtable_map: vtable_map,
168 upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
172 pub struct FnStyleState {
173 pub def: ast::NodeId,
174 pub fn_style: ast::FnStyle,
179 pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState {
180 FnStyleState { def: def, fn_style: fn_style, from_fn: true }
183 pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState {
184 match self.fn_style {
185 // If this unsafe, then if the outer function was already marked as
186 // unsafe we shouldn't attribute the unsafe'ness to the block. This
187 // way the block can be warned about instead of ignoring this
188 // extraneous block (functions are never warned about).
189 ast::UnsafeFn if self.from_fn => *self,
192 let (fn_style, def) = match blk.rules {
193 ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
194 ast::DefaultBlock => (fn_style, self.def),
196 FnStyleState{ def: def,
204 /// Whether `check_binop` is part of an assignment or not.
205 /// Used to know wether we allow user overloads and to print
206 /// better messages on error.
207 #[deriving(PartialEq)]
208 enum IsBinopAssignment{
214 pub struct FnCtxt<'a> {
215 // This flag is set to true if, during the writeback phase, we encounter
216 // a type error in this function.
217 writeback_errors: Cell<bool>,
219 // Number of errors that had been reported when we started
220 // checking this function. On exit, if we find that *more* errors
221 // have been reported, we will skip regionck and other work that
222 // expects the types within the function to be consistent.
223 err_count_on_creation: uint,
226 ps: RefCell<FnStyleState>,
228 // Sometimes we generate region pointers where the precise region
229 // to use is not known. For example, an expression like `&x.f`
230 // where `x` is of type `@T`: in this case, we will be rooting
231 // `x` onto the stack frame, and we could choose to root it until
232 // the end of (almost) any enclosing block or expression. We
233 // want to pick the narrowest block that encompasses all uses.
235 // What we do in such cases is to generate a region variable with
236 // `region_lb` as a lower bound. The regionck pass then adds
237 // other constraints based on how the variable is used and region
238 // inference selects the ultimate value. Finally, borrowck is
239 // charged with guaranteeing that the value whose address was taken
240 // can actually be made to live as long as it needs to live.
241 region_lb: Cell<ast::NodeId>,
243 inh: &'a Inherited<'a>,
245 ccx: &'a CrateCtxt<'a>,
248 impl<'a> Inherited<'a> {
249 fn new(tcx: &'a ty::ctxt,
250 param_env: ty::ParameterEnvironment)
253 infcx: infer::new_infer_ctxt(tcx),
254 locals: RefCell::new(NodeMap::new()),
255 param_env: param_env,
256 node_types: RefCell::new(NodeMap::new()),
257 item_substs: RefCell::new(NodeMap::new()),
258 adjustments: RefCell::new(NodeMap::new()),
259 method_map: RefCell::new(FnvHashMap::new()),
260 vtable_map: RefCell::new(FnvHashMap::new()),
261 upvar_borrow_map: RefCell::new(HashMap::new()),
266 // Used by check_const and check_enum_variants
267 fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
268 inh: &'a Inherited<'a>,
270 region_bnd: ast::NodeId)
273 writeback_errors: Cell::new(false),
274 err_count_on_creation: ccx.tcx.sess.err_count(),
276 ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
277 region_lb: Cell::new(region_bnd),
283 fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
284 // It's kind of a kludge to manufacture a fake function context
285 // and statement context, but we might as well do write the code only once
286 let param_env = ty::ParameterEnvironment { free_substs: substs::empty(),
287 self_param_bound: None,
288 type_param_bounds: Vec::new() };
289 Inherited::new(ccx.tcx, param_env)
292 impl<'a> ExprTyProvider for FnCtxt<'a> {
293 fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
297 fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
302 struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
304 impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
305 fn visit_item(&mut self, i: &ast::Item, _: ()) {
306 check_item(self.ccx, i);
307 visit::walk_item(self, i, ());
311 struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
313 impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
314 fn visit_item(&mut self, i: &ast::Item, _: ()) {
315 check_item_sized(self.ccx, i);
316 visit::walk_item(self, i, ());
320 pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
321 let mut visit = CheckItemTypesVisitor { ccx: ccx };
322 visit::walk_crate(&mut visit, krate, ());
324 ccx.tcx.sess.abort_if_errors();
326 let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
327 visit::walk_crate(&mut visit, krate, ());
330 fn check_bare_fn(ccx: &CrateCtxt,
335 param_env: ty::ParameterEnvironment) {
336 // Compute the fty from point of view of inside fn
337 // (replace any type-scheme with a type)
338 let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
340 match ty::get(fty).sty {
341 ty::ty_bare_fn(ref fn_ty) => {
342 let inh = Inherited::new(ccx.tcx, param_env);
343 let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
344 decl, id, body, &inh);
346 vtable::resolve_in_block(&fcx, body);
347 regionck::regionck_fn(&fcx, body);
348 writeback::resolve_type_vars_in_fn(&fcx, decl, body);
350 _ => ccx.tcx.sess.impossible_case(body.span,
351 "check_bare_fn: function type expected")
355 struct GatherLocalsVisitor<'a> {
359 impl<'a> GatherLocalsVisitor<'a> {
360 fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
363 // infer the variable's type
364 let var_id = self.fcx.infcx().next_ty_var_id();
365 let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
366 self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
369 // take type that the user specified
370 self.fcx.inh.locals.borrow_mut().insert(nid, typ);
376 impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
377 // Add explicitly-declared locals.
378 fn visit_local(&mut self, local: &ast::Local, _: ()) {
379 let o_ty = match local.ty.node {
380 ast::TyInfer => None,
381 _ => Some(self.fcx.to_ty(local.ty))
383 self.assign(local.id, o_ty);
384 debug!("Local variable {} is assigned type {}",
385 self.fcx.pat_to_str(local.pat),
386 self.fcx.infcx().ty_to_str(
387 self.fcx.inh.locals.borrow().get_copy(&local.id)));
388 visit::walk_local(self, local, ());
391 // Add pattern bindings.
392 fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
394 ast::PatIdent(_, ref path, _)
395 if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
396 self.assign(p.id, None);
397 debug!("Pattern binding {} is assigned to {}",
398 token::get_ident(path.segments.get(0).identifier),
399 self.fcx.infcx().ty_to_str(
400 self.fcx.inh.locals.borrow().get_copy(&p.id)));
404 visit::walk_pat(self, p, ());
408 fn visit_block(&mut self, b: &ast::Block, _: ()) {
409 // non-obvious: the `blk` variable maps to region lb, so
410 // we have to keep this up-to-date. This
411 // is... unfortunate. It'd be nice to not need this.
412 self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
415 // Don't descend into fns and items
416 fn visit_fn(&mut self, _: &visit::FnKind, _: &ast::FnDecl,
417 _: &ast::Block, _: Span, _: ast::NodeId, _: ()) { }
418 fn visit_item(&mut self, _: &ast::Item, _: ()) { }
422 fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
423 fn_style: ast::FnStyle,
428 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
431 * Helper used by check_bare_fn and check_expr_fn. Does the
432 * grungy work of checking a function body and returns the
433 * function context used for that purpose, since in the case of a
434 * fn item there is still a bit more to do.
437 * - inherited: other fields inherited from the enclosing fn (if any)
441 let err_count_on_creation = tcx.sess.err_count();
443 // First, we have to replace any bound regions in the fn type with free ones.
444 // The free region references will be bound the node_id of the body block.
445 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
446 ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
449 relate_free_regions(tcx, &fn_sig);
451 let arg_tys = fn_sig.inputs.as_slice();
452 let ret_ty = fn_sig.output;
454 debug!("check_fn(arg_tys={:?}, ret_ty={:?})",
455 arg_tys.iter().map(|&a| ppaux::ty_to_str(tcx, a)).collect::<Vec<String>>(),
456 ppaux::ty_to_str(tcx, ret_ty));
458 // Create the function context. This is either derived from scratch or,
459 // in the case of function expressions, based on the outer context.
461 writeback_errors: Cell::new(false),
462 err_count_on_creation: err_count_on_creation,
464 ps: RefCell::new(FnStyleState::function(fn_style, id)),
465 region_lb: Cell::new(body.id),
472 let mut visit = GatherLocalsVisitor { fcx: &fcx, };
473 // Add formal parameters.
474 for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
475 // Create type variables for each argument.
476 pat_util::pat_bindings(&tcx.def_map,
478 |_bm, pat_id, _sp, _path| {
479 visit.assign(pat_id, None);
482 // Check the pattern.
485 map: pat_id_map(&tcx.def_map, input.pat),
487 _match::check_pat(&pcx, input.pat, *arg_ty);
490 visit.visit_block(body, ());
493 check_block_with_expected(&fcx, body, Some(ret_ty));
495 // We unify the tail expr's type with the
496 // function result type, if there is a tail expr.
499 // Special case: we print a special error if there appears
500 // to be do-block/for-loop confusion
501 demand::suptype_with_fn(&fcx, tail_expr.span, false,
502 fcx.ret_ty, fcx.expr_ty(tail_expr),
504 fcx.report_mismatched_return_types(sp, e, a, s);
510 for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
511 fcx.write_ty(input.id, *arg);
517 fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
518 assert!(field.id.krate == ast::LOCAL_CRATE);
519 let item = match tcx.map.find(struct_id.node) {
520 Some(ast_map::NodeItem(item)) => item,
521 None => fail!("node not in ast map: {}", struct_id.node),
522 _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
526 ast::ItemStruct(struct_def, _) => {
527 match struct_def.fields.iter().find(|f| match f.node.kind {
528 ast::NamedField(ident, _) => ident.name == field.name,
534 .bug(format!("Could not find field {}",
535 token::get_name(field.name)).as_slice())
539 _ => tcx.sess.bug("Field found outside of a struct?"),
543 // Check struct fields are uniquely named wrt parents.
544 fn check_for_field_shadowing(tcx: &ty::ctxt,
546 let struct_fields = tcx.struct_fields.borrow();
547 let fields = struct_fields.get(&id);
549 let superstructs = tcx.superstructs.borrow();
550 let super_struct = superstructs.get(&id);
551 match *super_struct {
553 let super_fields = ty::lookup_struct_fields(tcx, parent_id);
554 for f in fields.iter() {
555 match super_fields.iter().find(|sf| f.name == sf.name) {
556 Some(prev_field) => {
557 tcx.sess.span_err(span_for_field(tcx, f, id),
558 format!("field `{}` hides field declared in \
560 token::get_name(f.name)).as_slice());
561 tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
562 "previously declared here");
572 fn check_fields_sized(tcx: &ty::ctxt,
573 struct_def: &ast::StructDef) {
574 let len = struct_def.fields.len();
578 for f in struct_def.fields.slice_to(len - 1).iter() {
579 let t = ty::node_id_to_type(tcx, f.node.id);
580 if !ty::type_is_sized(tcx, t) {
582 ast::NamedField(ident, _) => {
585 format!("type `{}` is dynamically sized. \
586 dynamically sized types may only \
587 appear as the type of the final \
589 token::get_ident(ident)).as_slice());
591 ast::UnnamedField(_) => {
592 tcx.sess.span_err(f.span, "dynamically sized type in field");
599 pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
602 check_representable(tcx, span, id, "struct");
603 check_instantiable(tcx, span, id);
605 // Check there are no overlapping fields in super-structs
606 check_for_field_shadowing(tcx, local_def(id));
608 if ty::lookup_simd(tcx, local_def(id)) {
609 check_simd(tcx, span, id);
613 pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
614 debug!("check_item(it.id={}, it.ident={})",
616 ty::item_path_str(ccx.tcx, local_def(it.id)));
617 let _indenter = indenter();
620 ast::ItemEnum(ref enum_definition, _) => {
621 check_enum_variants_sized(ccx,
622 enum_definition.variants.as_slice());
624 ast::ItemStruct(..) => {
625 check_fields_sized(ccx.tcx, ccx.tcx.map.expect_struct(it.id));
631 pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
632 debug!("check_item(it.id={}, it.ident={})",
634 ty::item_path_str(ccx.tcx, local_def(it.id)));
635 let _indenter = indenter();
638 ast::ItemStatic(_, _, e) => check_const(ccx, it.span, e, it.id),
639 ast::ItemEnum(ref enum_definition, _) => {
640 check_enum_variants(ccx,
642 enum_definition.variants.as_slice(),
645 ast::ItemFn(decl, _, _, _, body) => {
646 let fn_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
648 let param_env = ty::construct_parameter_environment(
651 fn_tpt.generics.type_param_defs(),
654 fn_tpt.generics.region_param_defs.as_slice(),
657 check_bare_fn(ccx, decl, body, it.id, fn_tpt.ty, param_env);
659 ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
660 debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
662 let impl_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
664 check_method_body(ccx, &impl_tpt.generics, None, *m);
667 match *opt_trait_ref {
668 Some(ref ast_trait_ref) => {
670 ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
671 check_impl_methods_against_trait(ccx,
677 vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, &*impl_trait_ref);
683 ast::ItemTrait(_, _, _, ref trait_methods) => {
684 let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
685 for trait_method in (*trait_methods).iter() {
686 match *trait_method {
688 // Nothing to do, since required methods don't have
692 check_method_body(ccx, &trait_def.generics,
693 Some(trait_def.trait_ref.clone()), m);
698 ast::ItemStruct(..) => {
699 check_struct(ccx, it.id, it.span);
701 ast::ItemTy(ref t, ref generics) => {
702 let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
703 check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty);
705 ast::ItemForeignMod(ref m) => {
706 if m.abi == abi::RustIntrinsic {
707 for item in m.items.iter() {
708 check_intrinsic_type(ccx, *item);
711 for item in m.items.iter() {
712 let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
713 if tpt.generics.has_type_params() {
714 ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
718 ast::ForeignItemFn(ref fn_decl, _) => {
719 if fn_decl.variadic && m.abi != abi::C {
720 ccx.tcx.sess.span_err(
721 item.span, "variadic function must have C calling convention");
729 _ => {/* nothing to do */ }
733 fn check_method_body(ccx: &CrateCtxt,
734 item_generics: &ty::Generics,
735 self_bound: Option<Rc<ty::TraitRef>>,
736 method: &ast::Method) {
738 * Type checks a method body.
741 * - `item_generics`: generics defined on the impl/trait that contains
743 * - `self_bound`: bound for the `Self` type parameter, if any
744 * - `method`: the method definition
747 debug!("check_method_body(item_generics={}, \
750 item_generics.repr(ccx.tcx),
751 self_bound.repr(ccx.tcx),
753 let method_def_id = local_def(method.id);
754 let method_ty = ty::method(ccx.tcx, method_def_id);
755 let method_generics = &method_ty.generics;
758 ty::construct_parameter_environment(
761 item_generics.type_param_defs(),
762 method_generics.type_param_defs(),
763 item_generics.region_param_defs(),
764 method_generics.region_param_defs(),
767 let fty = ty::node_id_to_type(ccx.tcx, method.id);
769 check_bare_fn(ccx, method.decl, method.body, method.id, fty, param_env);
772 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
774 impl_generics: &ty::Generics,
775 ast_trait_ref: &ast::TraitRef,
776 impl_trait_ref: &ty::TraitRef,
777 impl_methods: &[@ast::Method]) {
778 // Locate trait methods
780 let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
782 // Check existing impl methods to see if they are both present in trait
783 // and compatible with trait signature
784 for impl_method in impl_methods.iter() {
785 let impl_method_def_id = local_def(impl_method.id);
786 let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
788 // If this is an impl of a trait method, find the corresponding
789 // method definition in the trait.
790 let opt_trait_method_ty =
791 trait_methods.iter().
792 find(|tm| tm.ident.name == impl_method_ty.ident.name);
793 match opt_trait_method_ty {
794 Some(trait_method_ty) => {
795 compare_impl_method(ccx.tcx,
801 &impl_trait_ref.substs);
807 "method `{}` is not a member of trait `{}`",
808 token::get_ident(impl_method_ty.ident),
809 pprust::path_to_str(&ast_trait_ref.path)).as_slice());
814 // Check for missing methods from trait
815 let provided_methods = ty::provided_trait_methods(tcx,
816 impl_trait_ref.def_id);
817 let mut missing_methods = Vec::new();
818 for trait_method in trait_methods.iter() {
820 impl_methods.iter().any(
821 |m| m.ident.name == trait_method.ident.name);
823 provided_methods.iter().any(
824 |m| m.ident.name == trait_method.ident.name);
825 if !is_implemented && !is_provided {
826 missing_methods.push(
827 format!("`{}`", token::get_ident(trait_method.ident)));
831 if !missing_methods.is_empty() {
834 format!("not all trait methods implemented, missing: {}",
835 missing_methods.connect(", ")).as_slice());
840 * Checks that a method from an impl/class conforms to the signature of
841 * the same method as declared in the trait.
845 * - impl_generics: the generics declared on the impl itself (not the method!)
846 * - impl_m: type of the method we are checking
847 * - impl_m_span: span to use for reporting errors
848 * - impl_m_body_id: id of the method body
849 * - trait_m: the method in the trait
850 * - trait_substs: the substitutions used on the type of the trait
852 fn compare_impl_method(tcx: &ty::ctxt,
853 impl_generics: &ty::Generics,
856 impl_m_body_id: ast::NodeId,
857 trait_m: &ty::Method,
858 trait_substs: &ty::substs) {
859 debug!("compare_impl_method()");
860 let infcx = infer::new_infer_ctxt(tcx);
862 let impl_tps = impl_generics.type_param_defs().len();
864 // Try to give more informative error messages about self typing
865 // mismatches. Note that any mismatch will also be detected
866 // below, where we construct a canonical function type that
867 // includes the self parameter as a normal parameter. It's just
868 // that the error messages you get out of this code are a bit more
869 // inscrutable, particularly for cases where one method has no
871 match (&trait_m.explicit_self, &impl_m.explicit_self) {
872 (&ast::SelfStatic, &ast::SelfStatic) => {}
873 (&ast::SelfStatic, _) => {
876 format!("method `{}` has a `{}` declaration in the impl, \
877 but not in the trait",
878 token::get_ident(trait_m.ident),
879 pprust::explicit_self_to_str(
880 impl_m.explicit_self)).as_slice());
883 (_, &ast::SelfStatic) => {
886 format!("method `{}` has a `{}` declaration in the trait, \
887 but not in the impl",
888 token::get_ident(trait_m.ident),
889 pprust::explicit_self_to_str(
890 trait_m.explicit_self)).as_slice());
894 // Let the type checker catch other errors below
898 let num_impl_m_type_params = impl_m.generics.type_param_defs().len();
899 let num_trait_m_type_params = trait_m.generics.type_param_defs().len();
900 if num_impl_m_type_params != num_trait_m_type_params {
903 format!("method `{method}` has {nimpl, plural, =1{# type parameter} \
904 other{# type parameters}}, \
905 but its trait declaration has {ntrait, plural, =1{# type parameter} \
906 other{# type parameters}}",
907 method = token::get_ident(trait_m.ident),
908 nimpl = num_impl_m_type_params,
909 ntrait = num_trait_m_type_params).as_slice());
913 if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
916 format!("method `{method}` has {nimpl, plural, =1{# parameter} \
917 other{# parameters}} \
918 but the declaration in trait `{trait}` has {ntrait}",
919 method = token::get_ident(trait_m.ident),
920 nimpl = impl_m.fty.sig.inputs.len(),
921 trait = ty::item_path_str(tcx, trait_m.def_id),
922 ntrait = trait_m.fty.sig.inputs.len()).as_slice());
926 let it = trait_m.generics.type_param_defs().iter()
927 .zip(impl_m.generics.type_param_defs().iter());
929 for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
930 // Check that the impl does not require any builtin-bounds
931 // that the trait does not guarantee:
933 impl_param_def.bounds.builtin_bounds -
934 trait_param_def.bounds.builtin_bounds;
935 if !extra_bounds.is_empty() {
938 format!("in method `{}`, \
939 type parameter {} requires `{}`, \
940 which is not required by \
941 the corresponding type parameter \
942 in the trait declaration",
943 token::get_ident(trait_m.ident),
945 extra_bounds.user_string(tcx)).as_slice());
949 // FIXME(#2687)---we should be checking that the bounds of the
950 // trait imply the bounds of the subtype, but it appears we
951 // are...not checking this.
952 if impl_param_def.bounds.trait_bounds.len() !=
953 trait_param_def.bounds.trait_bounds.len()
957 format!("in method `{method}`, \
958 type parameter {typaram} has \
959 {nimpl, plural, =1{# trait bound} other{# trait bounds}}, \
960 but the corresponding type parameter in \
961 the trait declaration has \
962 {ntrait, plural, =1{# trait bound} other{# trait bounds}}",
963 method = token::get_ident(trait_m.ident),
965 nimpl = impl_param_def.bounds.trait_bounds.len(),
966 ntrait = trait_param_def.bounds
973 // Create a substitution that maps the type parameters on the impl
974 // to themselves and which replace any references to bound regions
975 // in the self type with free regions. So, for example, if the
976 // impl type is "&'a str", then this would replace the self
977 // type with a free region `self`.
978 let dummy_impl_tps: Vec<ty::t> =
979 impl_generics.type_param_defs().iter().enumerate().
980 map(|(i,t)| ty::mk_param(tcx, i, t.def_id)).
982 let dummy_method_tps: Vec<ty::t> =
983 impl_m.generics.type_param_defs().iter().enumerate().
984 map(|(i,t)| ty::mk_param(tcx, i + impl_tps, t.def_id)).
986 let dummy_impl_regions: OwnedSlice<ty::Region> =
987 impl_generics.region_param_defs().iter().
988 map(|l| ty::ReFree(ty::FreeRegion {
989 scope_id: impl_m_body_id,
990 bound_region: ty::BrNamed(l.def_id, l.name)})).
992 let dummy_substs = ty::substs {
993 tps: dummy_impl_tps.append(dummy_method_tps.as_slice()),
994 regions: ty::NonerasedRegions(dummy_impl_regions),
997 // Create a bare fn type for trait/impl
998 // It'd be nice to refactor so as to provide the bare fn types instead.
999 let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
1000 let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
1002 // Perform substitutions so that the trait/impl methods are expressed
1003 // in terms of the same set of type/region parameters:
1004 // - replace trait type parameters with those from `trait_substs`,
1005 // except with any reference to bound self replaced with `dummy_self_r`
1006 // - replace method parameters on the trait with fresh, dummy parameters
1007 // that correspond to the parameters we will find on the impl
1008 // - replace self region with a fresh, dummy region
1010 debug!("impl_fty (pre-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
1011 impl_fty.subst(tcx, &dummy_substs)
1013 debug!("impl_fty (post-subst): {}", ppaux::ty_to_str(tcx, impl_fty));
1015 let substs { regions: trait_regions,
1017 self_ty: self_ty } = trait_substs.subst(tcx, &dummy_substs);
1018 let substs = substs {
1019 regions: trait_regions,
1020 tps: trait_tps.append(dummy_method_tps.as_slice()),
1023 debug!("trait_fty (pre-subst): {} substs={}",
1024 trait_fty.repr(tcx), substs.repr(tcx));
1025 trait_fty.subst(tcx, &substs)
1027 debug!("trait_fty (post-subst): {}", trait_fty.repr(tcx));
1029 match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
1030 impl_fty, trait_fty) {
1035 format!("method `{}` has an incompatible type for trait: {}",
1036 token::get_ident(trait_m.ident),
1037 ty::type_err_to_str(tcx, terr)).as_slice());
1038 ty::note_and_explain_type_err(tcx, terr);
1043 impl<'a> AstConv for FnCtxt<'a> {
1044 fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
1046 fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
1047 ty::lookup_item_type(self.tcx(), id)
1050 fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
1051 ty::lookup_trait_def(self.tcx(), id)
1054 fn ty_infer(&self, _span: Span) -> ty::t {
1055 self.infcx().next_ty_var()
1059 impl<'a> FnCtxt<'a> {
1060 pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
1064 pub fn err_count_since_creation(&self) -> uint {
1065 self.ccx.tcx.sess.err_count() - self.err_count_on_creation
1068 pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
1070 infcx: self.infcx(),
1071 param_env: &self.inh.param_env
1076 impl<'a> RegionScope for infer::InferCtxt<'a> {
1077 fn anon_regions(&self, span: Span, count: uint)
1078 -> Result<Vec<ty::Region> , ()> {
1079 Ok(Vec::from_fn(count, |_| {
1080 self.next_region_var(infer::MiscVariable(span))
1085 impl<'a> FnCtxt<'a> {
1086 pub fn tag(&self) -> String {
1087 format!("{}", self as *FnCtxt)
1090 pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
1091 match self.inh.locals.borrow().find(&nid) {
1094 self.tcx().sess.span_bug(
1096 format!("no type for local variable {:?}",
1103 pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
1104 debug!("write_ty({}, {}) in fcx {}",
1105 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
1106 self.inh.node_types.borrow_mut().insert(node_id, ty);
1109 pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
1110 if !ty::substs_is_noop(&substs.substs) {
1111 debug!("write_substs({}, {}) in fcx {}",
1113 substs.repr(self.tcx()),
1116 self.inh.item_substs.borrow_mut().insert(node_id, substs);
1120 pub fn write_ty_substs(&self,
1121 node_id: ast::NodeId,
1123 substs: ty::ItemSubsts) {
1124 let ty = ty::subst(self.tcx(), &substs.substs, ty);
1125 self.write_ty(node_id, ty);
1126 self.write_substs(node_id, substs);
1129 pub fn write_autoderef_adjustment(&self,
1130 node_id: ast::NodeId,
1132 if derefs == 0 { return; }
1133 self.write_adjustment(
1135 ty::AutoDerefRef(ty::AutoDerefRef {
1141 pub fn write_adjustment(&self,
1142 node_id: ast::NodeId,
1143 adj: ty::AutoAdjustment) {
1144 debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
1145 self.inh.adjustments.borrow_mut().insert(node_id, adj);
1148 pub fn write_nil(&self, node_id: ast::NodeId) {
1149 self.write_ty(node_id, ty::mk_nil());
1151 pub fn write_bot(&self, node_id: ast::NodeId) {
1152 self.write_ty(node_id, ty::mk_bot());
1154 pub fn write_error(&self, node_id: ast::NodeId) {
1155 self.write_ty(node_id, ty::mk_err());
1158 pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
1159 ast_ty_to_ty(self, self.infcx(), ast_t)
1162 pub fn pat_to_str(&self, pat: &ast::Pat) -> String {
1163 pat.repr(self.tcx())
1166 pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
1167 match self.inh.node_types.borrow().find(&ex.id) {
1170 self.tcx().sess.bug(format!("no type for expr in fcx {}",
1171 self.tag()).as_slice());
1176 pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
1177 match self.inh.node_types.borrow().find(&id) {
1180 self.tcx().sess.bug(
1181 format!("no type for node {}: {} in fcx {}",
1182 id, self.tcx().map.node_to_str(id),
1183 self.tag()).as_slice());
1188 pub fn method_ty_substs(&self, id: ast::NodeId) -> ty::substs {
1189 match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
1190 Some(method) => method.substs.clone(),
1192 self.tcx().sess.bug(
1193 format!("no method entry for node {}: {} in fcx {}",
1194 id, self.tcx().map.node_to_str(id),
1195 self.tag()).as_slice());
1200 pub fn opt_node_ty_substs(&self,
1202 f: |&ty::ItemSubsts|) {
1203 match self.inh.item_substs.borrow().find(&id) {
1209 pub fn mk_subty(&self,
1210 a_is_expected: bool,
1211 origin: infer::TypeOrigin,
1214 -> Result<(), ty::type_err> {
1215 infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
1218 pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
1219 -> Result<(), ty::type_err> {
1220 infer::can_mk_subty(self.infcx(), sub, sup)
1223 pub fn mk_assignty(&self,
1227 -> Result<(), ty::type_err> {
1228 match infer::mk_coercety(self.infcx(),
1230 infer::ExprAssignable(expr.span),
1234 Err(ref e) => Err((*e)),
1235 Ok(Some(adjustment)) => {
1236 self.write_adjustment(expr.id, adjustment);
1242 pub fn mk_eqty(&self,
1243 a_is_expected: bool,
1244 origin: infer::TypeOrigin,
1247 -> Result<(), ty::type_err> {
1248 infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
1251 pub fn mk_subr(&self,
1252 a_is_expected: bool,
1253 origin: infer::SubregionOrigin,
1256 infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
1259 pub fn with_region_lb<R>(&self, lb: ast::NodeId, f: || -> R) -> R {
1260 let old_region_lb = self.region_lb.get();
1261 self.region_lb.set(lb);
1263 self.region_lb.set(old_region_lb);
1267 pub fn type_error_message(&self,
1269 mk_msg: |String| -> String,
1271 err: Option<&ty::type_err>) {
1272 self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
1275 pub fn report_mismatched_return_types(&self,
1279 err: &ty::type_err) {
1281 if ty::type_is_error(e) || ty::type_is_error(a) {
1284 self.infcx().report_mismatched_types(sp, e, a, err)
1287 pub fn report_mismatched_types(&self,
1291 err: &ty::type_err) {
1292 self.infcx().report_mismatched_types(sp, e, a, err)
1296 pub enum LvaluePreference {
1301 pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
1302 expr_id: Option<ast::NodeId>,
1303 mut lvalue_pref: LvaluePreference,
1304 should_stop: |ty::t, uint| -> Option<T>)
1305 -> (ty::t, uint, Option<T>) {
1307 * Executes an autoderef loop for the type `t`. At each step, invokes
1308 * `should_stop` to decide whether to terminate the loop. Returns
1309 * the final type and number of derefs that it performed.
1311 * Note: this method does not modify the adjustments table. The caller is
1312 * responsible for inserting an AutoAdjustment record into the `fcx`
1313 * using one of the suitable methods.
1316 let mut t = base_ty;
1317 for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
1318 let resolved_t = structurally_resolved_type(fcx, sp, t);
1320 match should_stop(resolved_t, autoderefs) {
1321 Some(x) => return (resolved_t, autoderefs, Some(x)),
1325 // Otherwise, deref if type is derefable:
1326 let mt = match ty::deref(resolved_t, false) {
1327 Some(mt) => Some(mt),
1330 expr_id.map(|id| MethodCall::autoderef(id, autoderefs as u32));
1331 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1337 if mt.mutbl == ast::MutImmutable {
1338 lvalue_pref = NoPreference;
1341 None => return (resolved_t, autoderefs, None)
1345 // We've reached the recursion limit, error gracefully.
1346 fcx.tcx().sess.span_err(sp,
1347 format!("reached the recursion limit while auto-dereferencing {}",
1348 base_ty.repr(fcx.tcx())).as_slice());
1349 (ty::mk_err(), 0, None)
1352 fn try_overloaded_deref(fcx: &FnCtxt,
1354 method_call: Option<MethodCall>,
1355 base_expr: Option<&ast::Expr>,
1357 lvalue_pref: LvaluePreference)
1359 // Try DerefMut first, if preferred.
1360 let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
1361 (PreferMutLvalue, Some(trait_did)) => {
1362 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1363 token::intern("deref_mut"), trait_did,
1364 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1369 // Otherwise, fall back to Deref.
1370 let method = match (method, fcx.tcx().lang_items.deref_trait()) {
1371 (None, Some(trait_did)) => {
1372 method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1373 token::intern("deref"), trait_did,
1374 base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
1376 (method, _) => method
1381 let ref_ty = ty::ty_fn_ret(method.ty);
1383 Some(method_call) => {
1384 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1388 ty::deref(ref_ty, true)
1394 // AST fragment checking
1395 pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
1396 let tcx = fcx.ccx.tcx;
1399 ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
1400 ast::LitBinary(..) => {
1401 ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
1403 ast::LitChar(_) => ty::mk_char(),
1404 ast::LitInt(_, t) => ty::mk_mach_int(t),
1405 ast::LitUint(_, t) => ty::mk_mach_uint(t),
1406 ast::LitIntUnsuffixed(_) => {
1407 // An unsuffixed integer literal could have any integral type,
1408 // so we create an integral type variable for it.
1409 ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())
1411 ast::LitFloat(_, t) => ty::mk_mach_float(t),
1412 ast::LitFloatUnsuffixed(_) => {
1413 // An unsuffixed floating point literal could have any floating point
1414 // type, so we create a floating point type variable for it.
1415 ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())
1417 ast::LitNil => ty::mk_nil(),
1418 ast::LitBool(_) => ty::mk_bool()
1422 pub fn valid_range_bounds(ccx: &CrateCtxt,
1426 match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1427 Some(val) => Some(val <= 0),
1432 pub fn check_expr_has_type(
1433 fcx: &FnCtxt, expr: &ast::Expr,
1435 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1436 demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
1440 fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1441 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
1442 demand::coerce(fcx, expr.span, expected, expr)
1446 fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
1447 check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
1450 fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
1451 expected: Option<ty::t>) {
1452 check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
1455 fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
1457 expected: Option<ty::t>,
1458 lvalue_pref: LvaluePreference) {
1459 check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1462 fn check_expr(fcx: &FnCtxt, expr: &ast::Expr) {
1463 check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
1466 fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1467 lvalue_pref: LvaluePreference) {
1468 check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
1472 // determine the `self` type, using fresh variables for all variables
1473 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
1474 // would return ($0, $1) where $0 and $1 are freshly instantiated type
1476 pub fn impl_self_ty(vcx: &VtableContext,
1477 span: Span, // (potential) receiver for this impl
1479 -> ty_param_substs_and_ty {
1480 let tcx = vcx.tcx();
1482 let ity = ty::lookup_item_type(tcx, did);
1483 let (n_tps, rps, raw_ty) =
1484 (ity.generics.type_param_defs().len(),
1485 ity.generics.region_param_defs(),
1488 let rps = vcx.infcx.region_vars_for_defs(span, rps);
1489 let tps = vcx.infcx.next_ty_vars(n_tps);
1491 let substs = substs {
1492 regions: ty::NonerasedRegions(rps),
1496 let substd_ty = ty::subst(tcx, &substs, raw_ty);
1498 ty_param_substs_and_ty { substs: substs, ty: substd_ty }
1501 // Only for fields! Returns <none> for methods>
1502 // Indifferent to privacy flags
1503 pub fn lookup_field_ty(tcx: &ty::ctxt,
1504 class_id: ast::DefId,
1505 items: &[ty::field_ty],
1506 fieldname: ast::Name,
1507 substs: &ty::substs) -> Option<ty::t> {
1509 let o_field = items.iter().find(|f| f.name == fieldname);
1510 o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
1513 // Controls whether the arguments are automatically referenced. This is useful
1514 // for overloaded binary and unary operators.
1515 pub enum DerefArgs {
1520 // Given the provenance of a static method, returns the generics of the static
1521 // method's container.
1522 fn generics_of_static_method_container(type_context: &ty::ctxt,
1523 provenance: ast::MethodProvenance)
1526 ast::FromTrait(trait_def_id) => {
1527 ty::lookup_trait_def(type_context, trait_def_id).generics.clone()
1529 ast::FromImpl(impl_def_id) => {
1530 ty::lookup_item_type(type_context, impl_def_id).generics.clone()
1535 // Verifies that type parameters supplied in paths are in the right
1537 fn check_type_parameter_positions_in_path(function_context: &FnCtxt,
1540 // We only care about checking the case in which the path has two or
1542 if path.segments.len() < 2 {
1546 // Verify that no lifetimes or type parameters are present anywhere
1547 // except the final two elements of the path.
1548 for i in range(0, path.segments.len() - 2) {
1549 for lifetime in path.segments.get(i).lifetimes.iter() {
1550 function_context.tcx()
1552 .span_err(lifetime.span,
1553 "lifetime parameters may not \
1558 for typ in path.segments.get(i).types.iter() {
1559 function_context.tcx()
1562 "type parameters may not appear here");
1567 // If there are no parameters at all, there is nothing more to do; the
1568 // rest of typechecking will (attempt to) infer everything.
1571 .all(|s| s.lifetimes.is_empty() && s.types.is_empty()) {
1576 // If this is a static method of a trait or implementation, then
1577 // ensure that the segment of the path which names the trait or
1578 // implementation (the penultimate segment) is annotated with the
1579 // right number of type parameters.
1580 ast::DefStaticMethod(_, provenance, _) => {
1582 generics_of_static_method_container(function_context.ccx.tcx,
1584 let name = match provenance {
1585 ast::FromTrait(_) => "trait",
1586 ast::FromImpl(_) => "impl",
1589 let trait_segment = &path.segments.get(path.segments.len() - 2);
1591 // Make sure lifetime parameterization agrees with the trait or
1592 // implementation type.
1593 let trait_region_parameter_count = generics.region_param_defs().len();
1594 let supplied_region_parameter_count = trait_segment.lifetimes.len();
1595 if trait_region_parameter_count != supplied_region_parameter_count
1596 && supplied_region_parameter_count != 0 {
1597 function_context.tcx()
1599 .span_err(path.span,
1600 format!("expected {nexpected, plural, =1{# lifetime parameter} \
1601 other{# lifetime parameters}}, \
1602 found {nsupplied, plural, =1{# lifetime parameter} \
1603 other{# lifetime parameters}}",
1604 nexpected = trait_region_parameter_count,
1605 nsupplied = supplied_region_parameter_count).as_slice());
1608 // Make sure the number of type parameters supplied on the trait
1609 // or implementation segment equals the number of type parameters
1610 // on the trait or implementation definition.
1611 let formal_ty_param_count = generics.type_param_defs().len();
1612 let required_ty_param_count = generics.type_param_defs().iter()
1613 .take_while(|x| x.default.is_none())
1615 let supplied_ty_param_count = trait_segment.types.len();
1616 if supplied_ty_param_count < required_ty_param_count {
1617 let msg = if required_ty_param_count < generics.type_param_defs().len() {
1618 format!("the {trait_or_impl} referenced by this path needs at least \
1619 {nexpected, plural, =1{# type parameter} \
1620 other{# type parameters}}, \
1621 but {nsupplied, plural, =1{# type parameter} \
1622 other{# type parameters}} were supplied",
1623 trait_or_impl = name,
1624 nexpected = required_ty_param_count,
1625 nsupplied = supplied_ty_param_count)
1627 format!("the {trait_or_impl} referenced by this path needs \
1628 {nexpected, plural, =1{# type parameter} \
1629 other{# type parameters}}, \
1630 but {nsupplied, plural, =1{# type parameter} \
1631 other{# type parameters}} were supplied",
1632 trait_or_impl = name,
1633 nexpected = required_ty_param_count,
1634 nsupplied = supplied_ty_param_count)
1636 function_context.tcx().sess.span_err(path.span,
1638 } else if supplied_ty_param_count > formal_ty_param_count {
1639 let msg = if required_ty_param_count < generics.type_param_defs().len() {
1640 format!("the {trait_or_impl} referenced by this path needs at most \
1641 {nexpected, plural, =1{# type parameter} \
1642 other{# type parameters}}, \
1643 but {nsupplied, plural, =1{# type parameter} \
1644 other{# type parameters}} were supplied",
1645 trait_or_impl = name,
1646 nexpected = formal_ty_param_count,
1647 nsupplied = supplied_ty_param_count)
1649 format!("the {trait_or_impl} referenced by this path needs \
1650 {nexpected, plural, =1{# type parameter} \
1651 other{# type parameters}}, \
1652 but {nsupplied, plural, =1{# type parameter} \
1653 other{# type parameters}} were supplied",
1654 trait_or_impl = name,
1655 nexpected = formal_ty_param_count,
1656 nsupplied = supplied_ty_param_count)
1658 function_context.tcx().sess.span_err(path.span,
1663 // Verify that no lifetimes or type parameters are present on
1664 // the penultimate segment of the path.
1665 let segment = &path.segments.get(path.segments.len() - 2);
1666 for lifetime in segment.lifetimes.iter() {
1667 function_context.tcx()
1669 .span_err(lifetime.span,
1670 "lifetime parameters may not
1674 for typ in segment.types.iter() {
1675 function_context.tcx()
1678 "type parameters may not appear \
1687 /// If an expression has any sub-expressions that result in a type error,
1688 /// inspecting that expression's type with `ty::type_is_error` will return
1689 /// true. Likewise, if an expression is known to diverge, inspecting its
1690 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
1691 /// strict, _|_ can appear in the type of an expression that does not,
1692 /// itself, diverge: for example, fn() -> _|_.)
1693 /// Note that inspecting a type's structure *directly* may expose the fact
1694 /// that there are actually multiple representations for both `ty_err` and
1695 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
1696 fn check_expr_with_unifier(fcx: &FnCtxt,
1698 expected: Option<ty::t>,
1699 lvalue_pref: LvaluePreference,
1701 debug!(">> typechecking");
1703 fn check_method_argument_types(
1706 method_fn_ty: ty::t,
1707 callee_expr: &ast::Expr,
1708 args: &[@ast::Expr],
1709 deref_args: DerefArgs) -> ty::t {
1710 // HACK(eddyb) ignore provided self (it has special typeck rules).
1711 let args = args.slice_from(1);
1712 if ty::type_is_error(method_fn_ty) {
1713 let err_inputs = err_args(args.len());
1714 check_argument_types(fcx, sp, err_inputs.as_slice(), callee_expr,
1715 args, deref_args, false);
1718 match ty::get(method_fn_ty).sty {
1719 ty::ty_bare_fn(ref fty) => {
1720 // HACK(eddyb) ignore self in the definition (see above).
1721 check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1),
1722 callee_expr, args, deref_args,
1727 fcx.tcx().sess.span_bug(callee_expr.span,
1728 "method without bare fn type");
1734 fn check_argument_types(fcx: &FnCtxt,
1736 fn_inputs: &[ty::t],
1737 callee_expr: &ast::Expr,
1738 args: &[@ast::Expr],
1739 deref_args: DerefArgs,
1743 * Generic function that factors out common logic from
1744 * function calls, method calls and overloaded operators.
1747 let tcx = fcx.ccx.tcx;
1749 // Grab the argument types, supplying fresh type variables
1750 // if the wrong number of arguments were supplied
1751 let supplied_arg_count = args.len();
1752 let expected_arg_count = fn_inputs.len();
1753 let formal_tys = if expected_arg_count == supplied_arg_count {
1754 fn_inputs.iter().map(|a| *a).collect()
1755 } else if variadic {
1756 if supplied_arg_count >= expected_arg_count {
1757 fn_inputs.iter().map(|a| *a).collect()
1760 "this function takes at least {nexpected, plural, =1{# parameter} \
1761 other{# parameters}} \
1762 but {nsupplied, plural, =1{# parameter was} \
1763 other{# parameters were}} supplied",
1764 nexpected = expected_arg_count,
1765 nsupplied = supplied_arg_count);
1767 tcx.sess.span_err(sp, msg.as_slice());
1769 err_args(supplied_arg_count)
1773 "this function takes {nexpected, plural, =1{# parameter} \
1774 other{# parameters}} \
1775 but {nsupplied, plural, =1{# parameter was} \
1776 other{# parameters were}} supplied",
1777 nexpected = expected_arg_count,
1778 nsupplied = supplied_arg_count);
1780 tcx.sess.span_err(sp, msg.as_slice());
1782 err_args(supplied_arg_count)
1785 debug!("check_argument_types: formal_tys={:?}",
1786 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<String>>());
1788 // Check the arguments.
1789 // We do this in a pretty awful way: first we typecheck any arguments
1790 // that are not anonymous functions, then we typecheck the anonymous
1791 // functions. This is so that we have more information about the types
1792 // of arguments when we typecheck the functions. This isn't really the
1793 // right way to do this.
1794 let xs = [false, true];
1795 for check_blocks in xs.iter() {
1796 let check_blocks = *check_blocks;
1797 debug!("check_blocks={}", check_blocks);
1799 // More awful hacks: before we check the blocks, try to do
1800 // an "opportunistic" vtable resolution of any trait
1801 // bounds on the call.
1803 vtable::early_resolve_expr(callee_expr, fcx, true);
1806 // For variadic functions, we don't have a declared type for all of
1807 // the arguments hence we only do our usual type checking with
1808 // the arguments who's types we do know.
1809 let t = if variadic {
1814 for (i, arg) in args.iter().take(t).enumerate() {
1815 let is_block = match arg.node {
1816 ast::ExprFnBlock(..) |
1817 ast::ExprProc(..) => true,
1821 if is_block == check_blocks {
1822 debug!("checking the argument");
1823 let mut formal_ty = *formal_tys.get(i);
1827 match ty::get(formal_ty).sty {
1828 ty::ty_rptr(_, mt) => formal_ty = mt.ty,
1831 // So we hit this case when one implements the
1832 // operator traits but leaves an argument as
1833 // just T instead of &T. We'll catch it in the
1834 // mismatch impl/trait method phase no need to
1837 formal_ty = ty::mk_err();
1844 check_expr_coercable_to_type(fcx, *arg, formal_ty);
1850 // We also need to make sure we at least write the ty of the other
1851 // arguments which we skipped above.
1853 for arg in args.iter().skip(expected_arg_count) {
1854 check_expr(fcx, *arg);
1856 // There are a few types which get autopromoted when passed via varargs
1857 // in C but we just error out instead and require explicit casts.
1858 let arg_ty = structurally_resolved_type(fcx, arg.span, fcx.expr_ty(*arg));
1859 match ty::get(arg_ty).sty {
1860 ty::ty_float(ast::TyF32) => {
1861 fcx.type_error_message(arg.span,
1863 format!("can't pass an {} to variadic \
1864 function, cast to c_double", t)
1867 ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
1868 fcx.type_error_message(arg.span, |t| {
1869 format!("can't pass {} to variadic \
1870 function, cast to c_int",
1874 ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
1875 fcx.type_error_message(arg.span, |t| {
1876 format!("can't pass {} to variadic \
1877 function, cast to c_uint",
1887 fn err_args(len: uint) -> Vec<ty::t> {
1888 Vec::from_fn(len, |_| ty::mk_err())
1891 fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
1892 fcx.write_ty(call_expr.id, output);
1895 // A generic function for doing all of the checking for call expressions
1896 fn check_call(fcx: &FnCtxt,
1897 call_expr: &ast::Expr,
1899 args: &[@ast::Expr]) {
1900 // Index expressions need to be handled separately, to inform them
1901 // that they appear in call position.
1904 // Store the type of `f` as the type of the callee
1905 let fn_ty = fcx.expr_ty(f);
1907 // Extract the function signature from `in_fty`.
1908 let fn_sty = structure_of(fcx, f.span, fn_ty);
1910 // This is the "default" function signature, used in case of error.
1911 // In that case, we check each argument against "error" in order to
1912 // set up all the node type bindings.
1913 let error_fn_sig = FnSig {
1914 binder_id: ast::CRATE_NODE_ID,
1915 inputs: err_args(args.len()),
1916 output: ty::mk_err(),
1920 let fn_sig = match *fn_sty {
1921 ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
1922 ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
1924 fcx.type_error_message(call_expr.span, |actual| {
1925 format!("expected function but found `{}`", actual)
1931 // Replace any bound regions that appear in the function
1932 // signature with region variables
1933 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
1934 fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
1937 // Call the generic checker.
1938 check_argument_types(fcx, call_expr.span, fn_sig.inputs.as_slice(), f,
1939 args, DontDerefArgs, fn_sig.variadic);
1941 write_call(fcx, call_expr, fn_sig.output);
1944 // Checks a method call.
1945 fn check_method_call(fcx: &FnCtxt,
1947 method_name: ast::SpannedIdent,
1948 args: &[@ast::Expr],
1949 tps: &[ast::P<ast::Ty>]) {
1951 // We can't know if we need &mut self before we look up the method,
1952 // so treat the receiver as mutable just in case - only explicit
1953 // overloaded dereferences care about the distinction.
1954 check_expr_with_lvalue_pref(fcx, rcvr, PreferMutLvalue);
1956 // no need to check for bot/err -- callee does that
1957 let expr_t = structurally_resolved_type(fcx,
1961 let tps = tps.iter().map(|&ast_ty| fcx.to_ty(ast_ty)).collect::<Vec<_>>();
1962 let fn_ty = match method::lookup(fcx, expr, rcvr,
1963 method_name.node.name,
1964 expr_t, tps.as_slice(),
1966 CheckTraitsAndInherentMethods,
1967 AutoderefReceiver, IgnoreStaticMethods) {
1969 let method_ty = method.ty;
1970 let method_call = MethodCall::expr(expr.id);
1971 fcx.inh.method_map.borrow_mut().insert(method_call, method);
1975 debug!("(checking method call) failing expr is {}", expr.id);
1977 fcx.type_error_message(method_name.span,
1979 format!("type `{}` does not implement any \
1980 method in scope named `{}`",
1982 token::get_ident(method_name.node))
1987 // Add error type for the result
1988 fcx.write_error(expr.id);
1990 // Check for potential static matches (missing self parameters)
1994 method_name.node.name,
1998 CheckTraitsAndInherentMethods,
1999 DontAutoderefReceiver,
2000 ReportStaticMethods);
2006 // Call the generic checker.
2007 let ret_ty = check_method_argument_types(fcx, method_name.span,
2011 write_call(fcx, expr, ret_ty);
2014 // A generic function for checking the then and else in an if
2016 fn check_then_else(fcx: &FnCtxt,
2017 cond_expr: &ast::Expr,
2018 then_blk: &ast::Block,
2019 opt_else_expr: Option<@ast::Expr>,
2022 expected: Option<ty::t>) {
2023 check_expr_has_type(fcx, cond_expr, ty::mk_bool());
2025 let branches_ty = match opt_else_expr {
2026 Some(else_expr) => {
2027 check_block_with_expected(fcx, then_blk, expected);
2028 let then_ty = fcx.node_ty(then_blk.id);
2029 check_expr_with_opt_hint(fcx, else_expr, expected);
2030 let else_ty = fcx.expr_ty(else_expr);
2031 infer::common_supertype(fcx.infcx(),
2032 infer::IfExpression(sp),
2038 check_block_no_value(fcx, then_blk);
2043 let cond_ty = fcx.expr_ty(cond_expr);
2044 let if_ty = if ty::type_is_error(cond_ty) {
2046 } else if ty::type_is_bot(cond_ty) {
2052 fcx.write_ty(id, if_ty);
2055 fn lookup_op_method(fcx: &FnCtxt,
2059 trait_did: Option<ast::DefId>,
2060 args: &[@ast::Expr],
2061 autoderef_receiver: AutoderefReceiverFlag,
2062 unbound_method: ||) -> ty::t {
2063 let method = match trait_did {
2064 Some(trait_did) => {
2065 method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2066 trait_did, self_t, [], autoderef_receiver,
2067 IgnoreStaticMethods)
2073 let method_ty = method.ty;
2074 // HACK(eddyb) Fully qualified path to work around a resolve bug.
2075 let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
2076 fcx.inh.method_map.borrow_mut().insert(method_call, method);
2077 check_method_argument_types(fcx, op_ex.span,
2083 // Check the args anyway
2084 // so we get all the error messages
2085 let expected_ty = ty::mk_err();
2086 check_method_argument_types(fcx, op_ex.span,
2094 // could be either an expr_binop or an expr_assign_binop
2095 fn check_binop(fcx: &FnCtxt,
2100 is_binop_assignment: IsBinopAssignment) {
2101 let tcx = fcx.ccx.tcx;
2103 let lvalue_pref = match is_binop_assignment {
2104 BinopAssignment => PreferMutLvalue,
2105 SimpleBinop => NoPreference
2107 check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
2109 // Callee does bot / err checking
2110 let lhs_t = structurally_resolved_type(fcx, lhs.span,
2113 if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
2114 // Shift is a special case: rhs can be any integral type
2115 check_expr(fcx, rhs);
2116 let rhs_t = fcx.expr_ty(rhs);
2117 require_integral(fcx, rhs.span, rhs_t);
2118 fcx.write_ty(expr.id, lhs_t);
2122 if ty::is_binopable(tcx, lhs_t, op) {
2123 let tvar = fcx.infcx().next_ty_var();
2124 demand::suptype(fcx, expr.span, tvar, lhs_t);
2125 check_expr_has_type(fcx, rhs, tvar);
2127 let result_t = match op {
2128 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
2130 if ty::type_is_simd(tcx, lhs_t) {
2131 if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
2132 fcx.type_error_message(expr.span,
2134 format!("binary comparison \
2135 operation `{}` not \
2136 supported for floating \
2137 point SIMD vector `{}`",
2138 ast_util::binop_to_str(op),
2155 fcx.write_ty(expr.id, result_t);
2159 if op == ast::BiOr || op == ast::BiAnd {
2160 // This is an error; one of the operands must have the wrong
2162 fcx.write_error(expr.id);
2163 fcx.write_error(rhs.id);
2164 fcx.type_error_message(expr.span,
2166 format!("binary operation `{}` cannot be applied \
2168 ast_util::binop_to_str(op),
2175 // Check for overloaded operators if not an assignment.
2176 let result_t = if is_binop_assignment == SimpleBinop {
2177 check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
2179 fcx.type_error_message(expr.span,
2181 format!("binary assignment \
2183 cannot be applied to \
2185 ast_util::binop_to_str(op),
2190 check_expr(fcx, rhs);
2194 fcx.write_ty(expr.id, result_t);
2195 if ty::type_is_error(result_t) {
2196 fcx.write_ty(rhs.id, result_t);
2200 fn check_user_binop(fcx: &FnCtxt,
2202 lhs_expr: @ast::Expr,
2203 lhs_resolved_t: ty::t,
2205 rhs: @ast::Expr) -> ty::t {
2206 let tcx = fcx.ccx.tcx;
2207 let lang = &tcx.lang_items;
2208 let (name, trait_did) = match op {
2209 ast::BiAdd => ("add", lang.add_trait()),
2210 ast::BiSub => ("sub", lang.sub_trait()),
2211 ast::BiMul => ("mul", lang.mul_trait()),
2212 ast::BiDiv => ("div", lang.div_trait()),
2213 ast::BiRem => ("rem", lang.rem_trait()),
2214 ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
2215 ast::BiBitAnd => ("bitand", lang.bitand_trait()),
2216 ast::BiBitOr => ("bitor", lang.bitor_trait()),
2217 ast::BiShl => ("shl", lang.shl_trait()),
2218 ast::BiShr => ("shr", lang.shr_trait()),
2219 ast::BiLt => ("lt", lang.ord_trait()),
2220 ast::BiLe => ("le", lang.ord_trait()),
2221 ast::BiGe => ("ge", lang.ord_trait()),
2222 ast::BiGt => ("gt", lang.ord_trait()),
2223 ast::BiEq => ("eq", lang.eq_trait()),
2224 ast::BiNe => ("ne", lang.eq_trait()),
2225 ast::BiAnd | ast::BiOr => {
2226 check_expr(fcx, rhs);
2227 return ty::mk_err();
2230 lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
2231 trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
2232 fcx.type_error_message(ex.span, |actual| {
2233 format!("binary operation `{}` cannot be applied to type `{}`",
2234 ast_util::binop_to_str(op),
2236 }, lhs_resolved_t, None)
2240 fn check_user_unop(fcx: &FnCtxt,
2243 trait_did: Option<ast::DefId>,
2245 rhs_expr: @ast::Expr,
2246 rhs_t: ty::t) -> ty::t {
2247 lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2248 trait_did, [rhs_expr], DontAutoderefReceiver, || {
2249 fcx.type_error_message(ex.span, |actual| {
2250 format!("cannot apply unary operator `{}` to type `{}`",
2256 // Resolves `expected` by a single level if it is a variable and passes it
2257 // through the `unpack` function. It there is no expected type or
2258 // resolution is not possible (e.g., no constraints yet present), just
2260 fn unpack_expected<O>(
2262 expected: Option<ty::t>,
2263 unpack: |&ty::sty| -> Option<O>)
2267 match resolve_type(fcx.infcx(), t, force_tvar) {
2268 Ok(t) => unpack(&ty::get(t).sty),
2276 fn check_expr_fn(fcx: &FnCtxt,
2278 store: ty::TraitStore,
2280 body: ast::P<ast::Block>,
2281 expected: Option<ty::t>) {
2282 let tcx = fcx.ccx.tcx;
2284 // Find the expected input/output types (if any). Substitute
2285 // fresh bound regions for any bound regions we find in the
2286 // expected types so as to avoid capture.
2287 let expected_sty = unpack_expected(fcx,
2289 |x| Some((*x).clone()));
2292 expected_bounds) = {
2293 match expected_sty {
2294 Some(ty::ty_closure(ref cenv)) => {
2296 replace_late_bound_regions_in_fn_sig(
2298 |_| fcx.inh.infcx.fresh_bound_region(expr.id));
2299 let onceness = match (&store, &cenv.store) {
2300 // As the closure type and onceness go, only three
2301 // combinations are legit:
2305 // If the actual and expected closure type disagree with
2306 // each other, set expected onceness to be always Once or
2307 // Many according to the actual type. Otherwise, it will
2308 // yield either an illegal "many proc" or a less known
2309 // "once closure" in the error message.
2310 (&ty::UniqTraitStore, &ty::UniqTraitStore) |
2311 (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
2313 (&ty::UniqTraitStore, _) => ast::Once,
2314 (&ty::RegionTraitStore(..), _) => ast::Many,
2316 (Some(sig), onceness, cenv.bounds)
2319 // Not an error! Means we're inferring the closure type
2320 let mut bounds = ty::empty_builtin_bounds();
2321 let onceness = match expr.node {
2322 ast::ExprProc(..) => {
2323 bounds.add(ty::BoundSend);
2328 (None, onceness, bounds)
2333 // construct the function type
2334 let fn_ty = astconv::ty_of_closure(fcx,
2342 let fty_sig = fn_ty.sig.clone();
2343 let fty = ty::mk_closure(tcx, fn_ty);
2344 debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
2346 fcx.write_ty(expr.id, fty);
2348 // If the closure is a stack closure and hasn't had some non-standard
2349 // style inferred for it, then check it under its parent's style.
2350 // Otherwise, use its own
2351 let (inherited_style, id) = match store {
2352 ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
2353 fcx.ps.borrow().def),
2354 ty::UniqTraitStore => (ast::NormalFn, expr.id)
2357 check_fn(fcx.ccx, inherited_style, &fty_sig,
2358 decl, id, body, fcx.inh);
2362 // Check field access expressions
2363 fn check_field(fcx: &FnCtxt,
2365 lvalue_pref: LvaluePreference,
2368 tys: &[ast::P<ast::Ty>]) {
2369 let tcx = fcx.ccx.tcx;
2370 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
2371 let expr_t = structurally_resolved_type(fcx, expr.span,
2373 // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
2374 let (_, autoderefs, field_ty) =
2375 autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2376 match ty::get(base_t).sty {
2377 ty::ty_struct(base_id, ref substs) => {
2378 debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2379 let fields = ty::lookup_struct_fields(tcx, base_id);
2380 lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
2387 fcx.write_ty(expr.id, field_ty);
2388 fcx.write_autoderef_adjustment(base.id, autoderefs);
2394 let tps: Vec<ty::t> = tys.iter().map(|&ty| fcx.to_ty(ty)).collect();
2395 match method::lookup(fcx,
2402 CheckTraitsAndInherentMethods,
2404 IgnoreStaticMethods) {
2406 fcx.type_error_message(
2409 format!("attempted to take value of method `{}` on type \
2410 `{}`", token::get_name(field), actual)
2414 tcx.sess.span_note(expr.span,
2415 "maybe a missing `()` to call it? If not, try an anonymous function.");
2419 fcx.type_error_message(
2422 format!("attempted access of field `{}` on \
2423 type `{}`, but no field with that \
2425 token::get_name(field),
2432 fcx.write_error(expr.id);
2435 fn check_struct_or_variant_fields(fcx: &FnCtxt,
2438 class_id: ast::DefId,
2439 node_id: ast::NodeId,
2440 substitutions: ty::substs,
2441 field_types: &[ty::field_ty],
2442 ast_fields: &[ast::Field],
2443 check_completeness: bool) {
2444 let tcx = fcx.ccx.tcx;
2446 let mut class_field_map = HashMap::new();
2447 let mut fields_found = 0;
2448 for field in field_types.iter() {
2449 class_field_map.insert(field.name, (field.id, false));
2452 let mut error_happened = false;
2454 // Typecheck each field.
2455 for field in ast_fields.iter() {
2456 let mut expected_field_type = ty::mk_err();
2458 let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
2461 fcx.type_error_message(
2464 format!("structure `{}` has no field named `{}`",
2465 actual, token::get_ident(field.ident.node))
2469 error_happened = true;
2471 Some((_, true)) => {
2474 format!("field `{}` specified more than once",
2475 token::get_ident(field.ident
2476 .node)).as_slice());
2477 error_happened = true;
2479 Some((field_id, false)) => {
2480 expected_field_type =
2481 ty::lookup_field_type(
2482 tcx, class_id, field_id, &substitutions);
2483 class_field_map.insert(
2484 field.ident.node.name, (field_id, true));
2488 // Make sure to give a type to the field even if there's
2489 // an error, so we can continue typechecking
2490 check_expr_coercable_to_type(
2493 expected_field_type);
2497 fcx.write_error(node_id);
2500 if check_completeness && !error_happened {
2501 // Make sure the programmer specified all the fields.
2502 assert!(fields_found <= field_types.len());
2503 if fields_found < field_types.len() {
2504 let mut missing_fields = Vec::new();
2505 for class_field in field_types.iter() {
2506 let name = class_field.name;
2507 let (_, seen) = *class_field_map.get(&name);
2509 missing_fields.push(
2510 format!("`{}`", token::get_name(name).get()))
2514 tcx.sess.span_err(span,
2516 "missing {nfields, plural, =1{field} other{fields}}: {fields}",
2517 nfields = missing_fields.len(),
2518 fields = missing_fields.connect(", ")).as_slice());
2522 if !error_happened {
2523 fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
2524 class_id, substitutions));
2528 fn check_struct_constructor(fcx: &FnCtxt,
2530 span: codemap::Span,
2531 class_id: ast::DefId,
2532 fields: &[ast::Field],
2533 base_expr: Option<@ast::Expr>) {
2534 let tcx = fcx.ccx.tcx;
2536 // Look up the number of type parameters and the raw type, and
2537 // determine whether the class is region-parameterized.
2538 let item_type = ty::lookup_item_type(tcx, class_id);
2539 let type_parameter_count = item_type.generics.type_param_defs().len();
2540 let region_param_defs = item_type.generics.region_param_defs();
2541 let raw_type = item_type.ty;
2543 // Generate the struct type.
2544 let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
2545 let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
2546 let substitutions = substs {
2547 regions: ty::NonerasedRegions(regions),
2549 tps: type_parameters
2552 let mut struct_type = ty::subst(tcx, &substitutions, raw_type);
2554 // Look up and check the fields.
2555 let class_fields = ty::lookup_struct_fields(tcx, class_id);
2556 check_struct_or_variant_fields(fcx,
2562 class_fields.as_slice(),
2564 base_expr.is_none());
2565 if ty::type_is_error(fcx.node_ty(id)) {
2566 struct_type = ty::mk_err();
2569 // Check the base expression if necessary.
2572 Some(base_expr) => {
2573 check_expr_has_type(fcx, base_expr, struct_type);
2574 if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
2575 struct_type = ty::mk_bot();
2580 // Write in the resulting type.
2581 fcx.write_ty(id, struct_type);
2584 fn check_struct_enum_variant(fcx: &FnCtxt,
2586 span: codemap::Span,
2587 enum_id: ast::DefId,
2588 variant_id: ast::DefId,
2589 fields: &[ast::Field]) {
2590 let tcx = fcx.ccx.tcx;
2592 // Look up the number of type parameters and the raw type, and
2593 // determine whether the enum is region-parameterized.
2594 let item_type = ty::lookup_item_type(tcx, enum_id);
2595 let type_parameter_count = item_type.generics.type_param_defs().len();
2596 let region_param_defs = item_type.generics.region_param_defs();
2597 let raw_type = item_type.ty;
2599 // Generate the enum type.
2600 let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
2601 let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
2602 let substitutions = substs {
2603 regions: ty::NonerasedRegions(regions),
2605 tps: type_parameters
2608 let enum_type = ty::subst(tcx, &substitutions, raw_type);
2610 // Look up and check the enum variant fields.
2611 let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2612 check_struct_or_variant_fields(fcx,
2618 variant_fields.as_slice(),
2621 fcx.write_ty(id, enum_type);
2624 let tcx = fcx.ccx.tcx;
2627 ast::ExprVstore(ev, vst) => {
2628 let typ = match ev.node {
2629 ast::ExprVec(ref args) => {
2630 let mutability = match vst {
2631 ast::ExprVstoreMutSlice => ast::MutMutable,
2632 _ => ast::MutImmutable,
2634 let mut any_error = false;
2635 let mut any_bot = false;
2636 let t: ty::t = fcx.infcx().next_ty_var();
2637 for e in args.iter() {
2638 check_expr_has_type(fcx, *e, t);
2639 let arg_t = fcx.expr_ty(*e);
2640 if ty::type_is_error(arg_t) {
2643 else if ty::type_is_bot(arg_t) {
2652 ast_expr_vstore_to_ty(fcx, ev, vst, ||
2653 ty::mt{ ty: ty::mk_vec(tcx,
2654 ty::mt {ty: t, mutbl: mutability},
2656 mutbl: mutability })
2659 ast::ExprRepeat(element, count_expr) => {
2660 check_expr_with_hint(fcx, count_expr, ty::mk_uint());
2661 let _ = ty::eval_repeat_count(fcx, count_expr);
2662 let mutability = match vst {
2663 ast::ExprVstoreMutSlice => ast::MutMutable,
2664 _ => ast::MutImmutable,
2666 let t = fcx.infcx().next_ty_var();
2667 check_expr_has_type(fcx, element, t);
2668 let arg_t = fcx.expr_ty(element);
2669 if ty::type_is_error(arg_t) {
2671 } else if ty::type_is_bot(arg_t) {
2674 ast_expr_vstore_to_ty(fcx, ev, vst, ||
2675 ty::mt{ ty: ty::mk_vec(tcx,
2676 ty::mt {ty: t, mutbl: mutability},
2681 ast::ExprLit(_) => {
2682 let error = if vst == ast::ExprVstoreSlice {
2683 "`&\"string\"` has been removed; use `\"string\"` instead"
2685 "`~\"string\"` has been removed; use `\"string\".to_string()` instead"
2687 tcx.sess.span_err(expr.span, error);
2690 _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
2692 fcx.write_ty(ev.id, typ);
2693 fcx.write_ty(id, typ);
2696 ast::ExprBox(place, subexpr) => {
2697 check_expr(fcx, place);
2698 check_expr(fcx, subexpr);
2700 let mut checked = false;
2702 ast::ExprPath(ref path) => {
2703 // FIXME(pcwalton): For now we hardcode the two permissible
2704 // places: the exchange heap and the managed heap.
2705 let definition = lookup_def(fcx, path.span, place.id);
2706 let def_id = ast_util::def_id_of_def(definition);
2707 match tcx.lang_items
2709 .get(ExchangeHeapLangItem as uint) {
2710 &Some(item_def_id) if def_id == item_def_id => {
2711 fcx.write_ty(id, ty::mk_uniq(tcx,
2712 fcx.expr_ty(subexpr)));
2715 &Some(_) | &None => {}
2718 match tcx.lang_items
2720 .get(ManagedHeapLangItem as uint) {
2721 &Some(item_def_id) if def_id == item_def_id => {
2722 // Assign the magic `Gc<T>` struct.
2724 match tcx.lang_items
2725 .require(GcLangItem) {
2728 tcx.sess.span_err(expr.span,
2731 krate: ast::CRATE_NODE_ID,
2732 node: ast::DUMMY_NODE_ID,
2737 ty::NonerasedRegions(OwnedSlice::empty());
2738 let sty = ty::mk_struct(tcx,
2748 fcx.write_ty(id, sty);
2751 &Some(_) | &None => {}
2759 tcx.sess.span_err(expr.span,
2760 "only the managed heap and exchange heap are \
2761 currently supported");
2762 fcx.write_ty(id, ty::mk_err());
2766 ast::ExprLit(lit) => {
2767 let typ = check_lit(fcx, lit);
2768 fcx.write_ty(id, typ);
2770 ast::ExprBinary(op, lhs, rhs) => {
2771 check_binop(fcx, expr, op, lhs, rhs, SimpleBinop);
2773 let lhs_ty = fcx.expr_ty(lhs);
2774 let rhs_ty = fcx.expr_ty(rhs);
2775 if ty::type_is_error(lhs_ty) ||
2776 ty::type_is_error(rhs_ty) {
2777 fcx.write_error(id);
2779 else if ty::type_is_bot(lhs_ty) ||
2780 (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
2784 ast::ExprAssignOp(op, lhs, rhs) => {
2785 check_binop(fcx, expr, op, lhs, rhs, BinopAssignment);
2787 let lhs_t = fcx.expr_ty(lhs);
2788 let result_t = fcx.expr_ty(expr);
2789 demand::suptype(fcx, expr.span, result_t, lhs_t);
2791 let tcx = fcx.tcx();
2792 if !ty::expr_is_lval(tcx, lhs) {
2793 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2796 // Overwrite result of check_binop...this preserves existing behavior
2797 // but seems quite dubious with regard to user-defined methods
2798 // and so forth. - Niko
2799 if !ty::type_is_error(result_t)
2800 && !ty::type_is_bot(result_t) {
2801 fcx.write_nil(expr.id);
2804 ast::ExprUnary(unop, oprnd) => {
2805 let exp_inner = unpack_expected(fcx, expected, |sty| {
2807 ast::UnBox | ast::UnUniq => match *sty {
2808 ty::ty_box(ty) | ty::ty_uniq(ty) => Some(ty),
2811 ast::UnNot | ast::UnNeg => expected,
2812 ast::UnDeref => None
2815 let lvalue_pref = match unop {
2816 ast::UnDeref => lvalue_pref,
2819 check_expr_with_opt_hint_and_lvalue_pref(fcx, oprnd, exp_inner, lvalue_pref);
2820 let mut oprnd_t = fcx.expr_ty(oprnd);
2821 if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
2824 oprnd_t = ty::mk_box(tcx, oprnd_t)
2827 oprnd_t = ty::mk_uniq(tcx, oprnd_t);
2830 oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
2831 oprnd_t = match ty::deref(oprnd_t, true) {
2833 None => match try_overloaded_deref(fcx, expr.span,
2834 Some(MethodCall::expr(expr.id)),
2835 Some(&*oprnd), oprnd_t, lvalue_pref) {
2838 let is_newtype = match ty::get(oprnd_t).sty {
2839 ty::ty_struct(did, ref substs) => {
2840 let fields = ty::struct_fields(fcx.tcx(), did, substs);
2842 && fields.get(0).ident ==
2843 token::special_idents::unnamed_field
2848 // This is an obsolete struct deref
2849 tcx.sess.span_err(expr.span,
2850 "single-field tuple-structs can \
2851 no longer be dereferenced");
2853 fcx.type_error_message(expr.span, |actual| {
2854 format!("type `{}` cannot be \
2855 dereferenced", actual)
2864 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2866 if !(ty::type_is_integral(oprnd_t) ||
2867 ty::get(oprnd_t).sty == ty::ty_bool) {
2868 oprnd_t = check_user_unop(fcx, "!", "not",
2869 tcx.lang_items.not_trait(),
2870 expr, oprnd, oprnd_t);
2874 oprnd_t = structurally_resolved_type(fcx, oprnd.span,
2876 if !(ty::type_is_integral(oprnd_t) ||
2877 ty::type_is_fp(oprnd_t)) {
2878 oprnd_t = check_user_unop(fcx, "-", "neg",
2879 tcx.lang_items.neg_trait(),
2880 expr, oprnd, oprnd_t);
2885 fcx.write_ty(id, oprnd_t);
2887 ast::ExprAddrOf(mutbl, oprnd) => {
2888 let hint = unpack_expected(
2890 |sty| match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty),
2892 let lvalue_pref = match mutbl {
2893 ast::MutMutable => PreferMutLvalue,
2894 ast::MutImmutable => NoPreference
2896 check_expr_with_opt_hint_and_lvalue_pref(fcx, oprnd, hint, lvalue_pref);
2898 // Note: at this point, we cannot say what the best lifetime
2899 // is to use for resulting pointer. We want to use the
2900 // shortest lifetime possible so as to avoid spurious borrowck
2901 // errors. Moreover, the longest lifetime will depend on the
2902 // precise details of the value whose address is being taken
2903 // (and how long it is valid), which we don't know yet until type
2904 // inference is complete.
2906 // Therefore, here we simply generate a region variable. The
2907 // region inferencer will then select the ultimate value.
2908 // Finally, borrowck is charged with guaranteeing that the
2909 // value whose address was taken can actually be made to live
2910 // as long as it needs to live.
2911 let region = fcx.infcx().next_region_var(
2912 infer::AddrOfRegion(expr.span));
2914 let tm = ty::mt { ty: fcx.expr_ty(oprnd), mutbl: mutbl };
2915 let oprnd_t = if ty::type_is_error(tm.ty) {
2917 } else if ty::type_is_bot(tm.ty) {
2921 ty::mk_rptr(tcx, region, tm)
2923 fcx.write_ty(id, oprnd_t);
2925 ast::ExprPath(ref pth) => {
2926 let defn = lookup_def(fcx, pth.span, id);
2928 check_type_parameter_positions_in_path(fcx, pth, defn);
2929 let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
2930 instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
2932 ast::ExprInlineAsm(ref ia) => {
2933 for &(_, input) in ia.inputs.iter() {
2934 check_expr(fcx, input);
2936 for &(_, out) in ia.outputs.iter() {
2937 check_expr(fcx, out);
2941 ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
2942 ast::ExprBreak(_) => { fcx.write_bot(id); }
2943 ast::ExprAgain(_) => { fcx.write_bot(id); }
2944 ast::ExprRet(expr_opt) => {
2945 let ret_ty = fcx.ret_ty;
2947 None => match fcx.mk_eqty(false, infer::Misc(expr.span),
2948 ret_ty, ty::mk_nil()) {
2949 Ok(_) => { /* fall through */ }
2953 "`return;` in function returning non-nil");
2957 check_expr_has_type(fcx, e, ret_ty);
2962 ast::ExprParen(a) => {
2963 check_expr_with_opt_hint_and_lvalue_pref(fcx, a, expected, lvalue_pref);
2964 fcx.write_ty(id, fcx.expr_ty(a));
2966 ast::ExprAssign(lhs, rhs) => {
2967 check_expr_with_lvalue_pref(fcx, lhs, PreferMutLvalue);
2969 let tcx = fcx.tcx();
2970 if !ty::expr_is_lval(tcx, lhs) {
2971 tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
2974 let lhs_ty = fcx.expr_ty(lhs);
2975 check_expr_has_type(fcx, rhs, lhs_ty);
2976 let rhs_ty = fcx.expr_ty(rhs);
2978 if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
2979 fcx.write_error(id);
2980 } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
2986 ast::ExprIf(cond, then_blk, opt_else_expr) => {
2987 check_then_else(fcx, cond, then_blk, opt_else_expr,
2988 id, expr.span, expected);
2990 ast::ExprWhile(cond, body) => {
2991 check_expr_has_type(fcx, cond, ty::mk_bool());
2992 check_block_no_value(fcx, body);
2993 let cond_ty = fcx.expr_ty(cond);
2994 let body_ty = fcx.node_ty(body.id);
2995 if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
2996 fcx.write_error(id);
2998 else if ty::type_is_bot(cond_ty) {
3005 ast::ExprForLoop(..) =>
3006 fail!("non-desugared expr_for_loop"),
3007 ast::ExprLoop(body, _) => {
3008 check_block_no_value(fcx, (body));
3009 if !may_break(tcx, expr.id, body) {
3016 ast::ExprMatch(discrim, ref arms) => {
3017 _match::check_match(fcx, expr, discrim, arms.as_slice());
3019 ast::ExprFnBlock(decl, body) => {
3020 let region = astconv::opt_ast_region_to_region(fcx,
3026 ty::RegionTraitStore(region, ast::MutMutable),
3031 ast::ExprProc(decl, body) => {
3039 ast::ExprBlock(b) => {
3040 check_block_with_expected(fcx, b, expected);
3041 fcx.write_ty(id, fcx.node_ty(b.id));
3043 ast::ExprCall(f, ref args) => {
3044 check_call(fcx, expr, f, args.as_slice());
3045 let f_ty = fcx.expr_ty(f);
3046 let (args_bot, args_err) = args.iter().fold((false, false),
3047 |(rest_bot, rest_err), a| {
3048 // is this not working?
3049 let a_ty = fcx.expr_ty(*a);
3050 (rest_bot || ty::type_is_bot(a_ty),
3051 rest_err || ty::type_is_error(a_ty))});
3052 if ty::type_is_error(f_ty) || args_err {
3053 fcx.write_error(id);
3055 else if ty::type_is_bot(f_ty) || args_bot {
3059 ast::ExprMethodCall(ident, ref tps, ref args) => {
3060 check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
3061 let mut arg_tys = args.iter().map(|a| fcx.expr_ty(*a));
3062 let (args_bot, args_err) = arg_tys.fold((false, false),
3063 |(rest_bot, rest_err), a| {
3064 (rest_bot || ty::type_is_bot(a),
3065 rest_err || ty::type_is_error(a))});
3067 fcx.write_error(id);
3068 } else if args_bot {
3072 ast::ExprCast(e, t) => {
3074 let t_1 = fcx.to_ty(t);
3075 let t_e = fcx.expr_ty(e);
3077 debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
3078 debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
3080 if ty::type_is_error(t_e) {
3081 fcx.write_error(id);
3083 else if ty::type_is_bot(t_e) {
3087 match ty::get(t_1).sty {
3088 // This will be looked up later on
3089 ty::ty_trait(..) => (),
3092 if ty::type_is_nil(t_e) {
3093 fcx.type_error_message(expr.span, |actual| {
3094 format!("cast from nil: `{}` as `{}`",
3096 fcx.infcx().ty_to_str(t_1))
3098 } else if ty::type_is_nil(t_1) {
3099 fcx.type_error_message(expr.span, |actual| {
3100 format!("cast to nil: `{}` as `{}`",
3102 fcx.infcx().ty_to_str(t_1))
3106 let t1 = structurally_resolved_type(fcx, e.span, t_1);
3107 let te = structurally_resolved_type(fcx, e.span, t_e);
3108 let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
3109 let t_1_is_char = type_is_char(fcx, expr.span, t_1);
3110 let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
3112 // casts to scalars other than `char` and `bare fn` are trivial
3113 let t_1_is_trivial = t_1_is_scalar &&
3114 !t_1_is_char && !t_1_is_bare_fn;
3116 if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
3117 // casts from C-like enums are allowed
3118 } else if t_1_is_char {
3119 let te = fcx.infcx().resolve_type_vars_if_possible(te);
3120 if ty::get(te).sty != ty::ty_uint(ast::TyU8) {
3121 fcx.type_error_message(expr.span, |actual| {
3122 format!("only `u8` can be cast as \
3123 `char`, not `{}`", actual)
3126 } else if ty::get(t1).sty == ty::ty_bool {
3129 .span_err(expr.span,
3130 "cannot cast as `bool`, compare with \
3132 } else if type_is_region_ptr(fcx, expr.span, t_e) &&
3133 type_is_unsafe_ptr(fcx, expr.span, t_1) {
3135 fn is_vec(t: ty::t) -> bool {
3136 match ty::get(t).sty {
3137 ty::ty_vec(..) => true,
3138 ty::ty_ptr(ty::mt{ty: t, ..}) | ty::ty_rptr(_, ty::mt{ty: t, ..}) |
3139 ty::ty_box(t) | ty::ty_uniq(t) => match ty::get(t).sty {
3140 ty::ty_vec(_, None) => true,
3146 fn types_compatible(fcx: &FnCtxt, sp: Span,
3147 t1: ty::t, t2: ty::t) -> bool {
3151 let el = ty::sequence_element_type(fcx.tcx(),
3153 infer::mk_eqty(fcx.infcx(), false,
3154 infer::Misc(sp), el, t2).is_ok()
3158 // Due to the limitations of LLVM global constants,
3159 // region pointers end up pointing at copies of
3160 // vector elements instead of the original values.
3161 // To allow unsafe pointers to work correctly, we
3162 // need to special-case obtaining an unsafe pointer
3163 // from a region pointer to a vector.
3165 /* this cast is only allowed from &[T] to *T or
3167 match (&ty::get(te).sty, &ty::get(t_1).sty) {
3168 (&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
3169 if types_compatible(fcx, e.span,
3170 mt1.ty, mt2.ty) => {
3171 /* this case is allowed */
3174 demand::coerce(fcx, e.span, t_1, e);
3177 } else if !(type_is_scalar(fcx,expr.span,t_e)
3178 && t_1_is_trivial) {
3180 If more type combinations should be supported than are
3181 supported here, then file an enhancement issue and
3182 record the issue number in this comment.
3184 fcx.type_error_message(expr.span, |actual| {
3185 format!("non-scalar cast: `{}` as `{}`",
3187 fcx.infcx().ty_to_str(t_1))
3192 fcx.write_ty(id, t_1);
3195 ast::ExprVec(ref args) => {
3196 let t: ty::t = fcx.infcx().next_ty_var();
3197 for e in args.iter() {
3198 check_expr_has_type(fcx, *e, t);
3200 let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3202 fcx.write_ty(id, typ);
3204 ast::ExprRepeat(element, count_expr) => {
3205 check_expr_with_hint(fcx, count_expr, ty::mk_uint());
3206 let count = ty::eval_repeat_count(fcx, count_expr);
3207 let t: ty::t = fcx.infcx().next_ty_var();
3208 check_expr_has_type(fcx, element, t);
3209 let element_ty = fcx.expr_ty(element);
3210 if ty::type_is_error(element_ty) {
3211 fcx.write_error(id);
3213 else if ty::type_is_bot(element_ty) {
3217 let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
3219 fcx.write_ty(id, t);
3222 ast::ExprTup(ref elts) => {
3223 let flds = unpack_expected(fcx, expected, |sty| {
3225 ty::ty_tup(ref flds) => Some((*flds).clone()),
3229 let mut bot_field = false;
3230 let mut err_field = false;
3232 let elt_ts = elts.iter().enumerate().map(|(i, e)| {
3233 let opt_hint = match flds {
3234 Some(ref fs) if i < fs.len() => Some(*fs.get(i)),
3237 check_expr_with_opt_hint(fcx, *e, opt_hint);
3238 let t = fcx.expr_ty(*e);
3239 err_field = err_field || ty::type_is_error(t);
3240 bot_field = bot_field || ty::type_is_bot(t);
3245 } else if err_field {
3246 fcx.write_error(id);
3248 let typ = ty::mk_tup(tcx, elt_ts);
3249 fcx.write_ty(id, typ);
3252 ast::ExprStruct(ref path, ref fields, base_expr) => {
3253 // Resolve the path.
3254 let def = tcx.def_map.borrow().find(&id).map(|i| *i);
3256 Some(ast::DefStruct(type_def_id)) => {
3257 check_struct_constructor(fcx, id, expr.span, type_def_id,
3258 fields.as_slice(), base_expr);
3260 Some(ast::DefVariant(enum_id, variant_id, _)) => {
3261 check_struct_enum_variant(fcx, id, expr.span, enum_id,
3262 variant_id, fields.as_slice());
3265 tcx.sess.span_bug(path.span,
3266 "structure constructor does not name a structure type");
3270 ast::ExprField(base, field, ref tys) => {
3271 check_field(fcx, expr, lvalue_pref, base, field.name, tys.as_slice());
3273 ast::ExprIndex(base, idx) => {
3274 check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3275 check_expr(fcx, idx);
3276 let raw_base_t = fcx.expr_ty(base);
3277 let idx_t = fcx.expr_ty(idx);
3278 if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
3279 fcx.write_ty(id, raw_base_t);
3280 } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
3281 fcx.write_ty(id, idx_t);
3283 let (base_t, autoderefs, field_ty) =
3284 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3285 lvalue_pref, |base_t, _| ty::index(base_t));
3288 check_expr_has_type(fcx, idx, ty::mk_uint());
3289 fcx.write_ty(id, mt.ty);
3290 fcx.write_autoderef_adjustment(base.id, autoderefs);
3293 let resolved = structurally_resolved_type(fcx,
3296 let ret_ty = lookup_op_method(fcx,
3299 token::intern("index"),
3300 tcx.lang_items.index_trait(),
3304 fcx.type_error_message(expr.span,
3306 format!("cannot index a \
3313 fcx.write_ty(id, ret_ty);
3320 debug!("type of expr({}) {} is...", expr.id,
3321 syntax::print::pprust::expr_to_str(expr));
3322 debug!("... {}, expected is {}",
3323 ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
3325 Some(t) => ppaux::ty_to_str(tcx, t),
3326 _ => "empty".to_string()
3332 pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
3333 if !type_is_uint(fcx, sp, t) {
3334 fcx.type_error_message(sp, |actual| {
3335 format!("mismatched types: expected `uint` type but found `{}`",
3341 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
3342 if !type_is_integral(fcx, sp, t) {
3343 fcx.type_error_message(sp, |actual| {
3344 format!("mismatched types: expected integral type but found `{}`",
3350 pub fn check_decl_initializer(fcx: &FnCtxt,
3354 let local_ty = fcx.local_ty(init.span, nid);
3355 check_expr_coercable_to_type(fcx, init, local_ty)
3358 pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local) {
3359 let tcx = fcx.ccx.tcx;
3361 let t = fcx.local_ty(local.span, local.id);
3362 fcx.write_ty(local.id, t);
3366 check_decl_initializer(fcx, local.id, init);
3367 let init_ty = fcx.expr_ty(init);
3368 if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
3369 fcx.write_ty(local.id, init_ty);
3375 let pcx = pat_ctxt {
3377 map: pat_id_map(&tcx.def_map, local.pat),
3379 _match::check_pat(&pcx, local.pat, t);
3380 let pat_ty = fcx.node_ty(local.pat.id);
3381 if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
3382 fcx.write_ty(local.id, pat_ty);
3386 pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt) {
3388 let mut saw_bot = false;
3389 let mut saw_err = false;
3391 ast::StmtDecl(decl, id) => {
3394 ast::DeclLocal(ref l) => {
3395 check_decl_local(fcx, *l);
3396 let l_t = fcx.node_ty(l.id);
3397 saw_bot = saw_bot || ty::type_is_bot(l_t);
3398 saw_err = saw_err || ty::type_is_error(l_t);
3400 ast::DeclItem(_) => {/* ignore for now */ }
3403 ast::StmtExpr(expr, id) => {
3405 // Check with expected type of ()
3406 check_expr_has_type(fcx, expr, ty::mk_nil());
3407 let expr_ty = fcx.expr_ty(expr);
3408 saw_bot = saw_bot || ty::type_is_bot(expr_ty);
3409 saw_err = saw_err || ty::type_is_error(expr_ty);
3411 ast::StmtSemi(expr, id) => {
3413 check_expr(fcx, expr);
3414 let expr_ty = fcx.expr_ty(expr);
3415 saw_bot |= ty::type_is_bot(expr_ty);
3416 saw_err |= ty::type_is_error(expr_ty);
3418 ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
3421 fcx.write_bot(node_id);
3424 fcx.write_error(node_id);
3427 fcx.write_nil(node_id)
3431 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block) {
3432 check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
3433 let blkty = fcx.node_ty(blk.id);
3434 if ty::type_is_error(blkty) {
3435 fcx.write_error(blk.id);
3437 else if ty::type_is_bot(blkty) {
3438 fcx.write_bot(blk.id);
3441 let nilty = ty::mk_nil();
3442 demand::suptype(fcx, blk.span, nilty, blkty);
3446 pub fn check_block_with_expected(fcx: &FnCtxt,
3448 expected: Option<ty::t>) {
3450 let mut fcx_ps = fcx.ps.borrow_mut();
3451 let fn_style_state = fcx_ps.recurse(blk);
3452 replace(&mut *fcx_ps, fn_style_state)
3455 fcx.with_region_lb(blk.id, || {
3456 let mut warned = false;
3457 let mut last_was_bot = false;
3458 let mut any_bot = false;
3459 let mut any_err = false;
3460 for s in blk.stmts.iter() {
3461 check_stmt(fcx, *s);
3462 let s_id = ast_util::stmt_id(*s);
3463 let s_ty = fcx.node_ty(s_id);
3464 if last_was_bot && !warned && match s.node {
3465 ast::StmtDecl(decl, _) => {
3467 ast::DeclLocal(_) => true,
3471 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
3477 .add_lint(UnreachableCode,
3480 "unreachable statement".to_string());
3483 if ty::type_is_bot(s_ty) {
3484 last_was_bot = true;
3486 any_bot = any_bot || ty::type_is_bot(s_ty);
3487 any_err = any_err || ty::type_is_error(s_ty);
3490 None => if any_err {
3491 fcx.write_error(blk.id);
3494 fcx.write_bot(blk.id);
3497 fcx.write_nil(blk.id);
3500 if any_bot && !warned {
3504 .add_lint(UnreachableCode,
3507 "unreachable expression".to_string());
3509 check_expr_with_opt_hint(fcx, e, expected);
3510 let ety = fcx.expr_ty(e);
3511 fcx.write_ty(blk.id, ety);
3513 fcx.write_error(blk.id);
3516 fcx.write_bot(blk.id);
3522 *fcx.ps.borrow_mut() = prev;
3525 pub fn check_const(ccx: &CrateCtxt,
3529 let inh = blank_inherited_fields(ccx);
3530 let rty = ty::node_id_to_type(ccx.tcx, id);
3531 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3532 let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3533 check_const_with_ty(&fcx, sp, e, declty);
3536 pub fn check_const_with_ty(fcx: &FnCtxt,
3540 // Gather locals in statics (because of block expressions).
3541 // This is technically uneccessary because locals in static items are forbidden,
3542 // but prevents type checking from blowing up before const checking can properly
3544 GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
3547 let cty = fcx.expr_ty(e);
3548 demand::suptype(fcx, e.span, declty, cty);
3549 regionck::regionck_expr(fcx, e);
3550 writeback::resolve_type_vars_in_expr(fcx, e);
3553 /// Checks whether a type can be represented in memory. In particular, it
3554 /// identifies types that contain themselves without indirection through a
3555 /// pointer, which would mean their size is unbounded. This is different from
3556 /// the question of whether a type can be instantiated. See the definition of
3557 /// `check_instantiable`.
3558 pub fn check_representable(tcx: &ty::ctxt,
3560 item_id: ast::NodeId,
3561 designation: &str) -> bool {
3562 let rty = ty::node_id_to_type(tcx, item_id);
3564 // Check that it is possible to represent this type. This call identifies
3565 // (1) types that contain themselves and (2) types that contain a different
3566 // recursive type. It is only necessary to throw an error on those that
3567 // contain themselves. For case 2, there must be an inner type that will be
3568 // caught by case 1.
3569 match ty::is_type_representable(tcx, sp, rty) {
3570 ty::SelfRecursive => {
3572 sp, format!("illegal recursive {} type; \
3573 wrap the inner value in a box to make it representable",
3574 designation).as_slice());
3577 ty::Representable | ty::ContainsRecursive => (),
3582 /// Checks whether a type can be created without an instance of itself.
3583 /// This is similar but different from the question of whether a type
3584 /// can be represented. For example, the following type:
3586 /// enum foo { None, Some(foo) }
3588 /// is instantiable but is not representable. Similarly, the type
3590 /// enum foo { Some(@foo) }
3592 /// is representable, but not instantiable.
3593 pub fn check_instantiable(tcx: &ty::ctxt,
3595 item_id: ast::NodeId)
3597 let item_ty = ty::node_id_to_type(tcx, item_id);
3598 if !ty::is_instantiable(tcx, item_ty) {
3601 format!("this type cannot be instantiated without an \
3602 instance of itself; consider using \
3604 ppaux::ty_to_str(tcx, item_ty)).as_slice());
3611 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
3612 let t = ty::node_id_to_type(tcx, id);
3613 if ty::type_needs_subst(t) {
3614 tcx.sess.span_err(sp, "SIMD vector cannot be generic");
3617 match ty::get(t).sty {
3618 ty::ty_struct(did, ref substs) => {
3619 let fields = ty::lookup_struct_fields(tcx, did);
3620 if fields.is_empty() {
3621 tcx.sess.span_err(sp, "SIMD vector cannot be empty");
3624 let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
3625 if !fields.iter().all(
3626 |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
3627 tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
3630 if !ty::type_is_machine(e) {
3631 tcx.sess.span_err(sp, "SIMD vector element type should be \
3640 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
3641 vs: &[ast::P<ast::Variant>]) {
3642 for &v in vs.iter() {
3644 ast::TupleVariantKind(ref args) if args.len() > 0 => {
3645 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3646 let arg_tys: Vec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3647 let len = arg_tys.len();
3651 for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
3652 // Allow the last field in an enum to be unsized.
3653 // We want to do this so that we can support smart pointers.
3654 // A struct value with an unsized final field is itself
3655 // unsized and we must track this in the type system.
3656 if !ty::type_is_sized(ccx.tcx, *t) {
3660 args.get(i).ty.span,
3661 format!("type `{}` is dynamically sized. \
3662 dynamically sized types may only \
3663 appear as the final type in a \
3665 ppaux::ty_to_str(ccx.tcx,
3670 ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, struct_def),
3676 pub fn check_enum_variants(ccx: &CrateCtxt,
3678 vs: &[ast::P<ast::Variant>],
3681 fn disr_in_range(ccx: &CrateCtxt,
3683 disr: ty::Disr) -> bool {
3684 fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
3686 ast::TyU8 => disr as u8 as Disr == disr,
3687 ast::TyU16 => disr as u16 as Disr == disr,
3688 ast::TyU32 => disr as u32 as Disr == disr,
3689 ast::TyU64 => disr as u64 as Disr == disr,
3690 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3693 fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
3695 ast::TyI8 => disr as i8 as Disr == disr,
3696 ast::TyI16 => disr as i16 as Disr == disr,
3697 ast::TyI32 => disr as i32 as Disr == disr,
3698 ast::TyI64 => disr as i64 as Disr == disr,
3699 ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3703 attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3704 attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3708 fn do_check(ccx: &CrateCtxt,
3709 vs: &[ast::P<ast::Variant>],
3711 hint: attr::ReprAttr)
3712 -> Vec<Rc<ty::VariantInfo>> {
3714 let rty = ty::node_id_to_type(ccx.tcx, id);
3715 let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
3716 let mut disr_vals: Vec<ty::Disr> = Vec::new();
3717 let mut prev_disr_val: Option<ty::Disr> = None;
3719 for &v in vs.iter() {
3721 // If the discriminant value is specified explicitly in the enum check whether the
3722 // initialization expression is valid, otherwise use the last value plus one.
3723 let mut current_disr_val = match prev_disr_val {
3724 Some(prev_disr_val) => prev_disr_val + 1,
3725 None => ty::INITIAL_DISCRIMINANT_VALUE
3728 match v.node.disr_expr {
3730 debug!("disr expr, checking {}", pprust::expr_to_str(e));
3732 let inh = blank_inherited_fields(ccx);
3733 let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3734 let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
3735 check_const_with_ty(&fcx, e.span, e, declty);
3736 // check_expr (from check_const pass) doesn't guarantee
3737 // that the expression is in a form that eval_const_expr can
3738 // handle, so we may still get an internal compiler error
3740 match const_eval::eval_const_expr_partial(ccx.tcx, e) {
3741 Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
3742 Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
3744 ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3750 format!("expected constant: {}",
3758 // Check for duplicate discriminant values
3759 if disr_vals.contains(¤t_disr_val) {
3760 ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3762 // Check for unrepresentable discriminant values
3764 attr::ReprAny | attr::ReprExtern => (),
3765 attr::ReprInt(sp, ity) => {
3766 if !disr_in_range(ccx, ity, current_disr_val) {
3767 ccx.tcx.sess.span_err(v.span,
3768 "discriminant value outside specified type");
3769 ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3773 disr_vals.push(current_disr_val);
3775 let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, v,
3777 prev_disr_val = Some(current_disr_val);
3779 variants.push(variant_info);
3785 let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
3786 if hint != attr::ReprAny && vs.len() <= 1 {
3787 let msg = if vs.len() == 1 {
3788 "unsupported representation for univariant enum"
3790 "unsupported representation for zero-variant enum"
3792 ccx.tcx.sess.span_err(sp, msg)
3795 let variants = do_check(ccx, vs, id, hint);
3797 // cache so that ty::enum_variants won't repeat this work
3798 ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
3800 check_representable(ccx.tcx, sp, id, "enum");
3802 // Check that it is possible to instantiate this enum:
3804 // This *sounds* like the same that as representable, but it's
3805 // not. See def'n of `check_instantiable()` for details.
3806 check_instantiable(ccx.tcx, sp, id);
3809 pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def {
3810 lookup_def_ccx(fcx.ccx, sp, id)
3813 // Returns the type parameter count and the type for the given definition.
3814 pub fn ty_param_bounds_and_ty_for_def(fcx: &FnCtxt,
3817 -> ty_param_bounds_and_ty {
3819 ast::DefArg(nid, _) | ast::DefLocal(nid, _) |
3820 ast::DefBinding(nid, _) => {
3821 let typ = fcx.local_ty(sp, nid);
3822 return no_params(typ);
3824 ast::DefFn(id, _) | ast::DefStaticMethod(id, _, _) |
3825 ast::DefStatic(id, _) | ast::DefVariant(_, id, _) |
3826 ast::DefStruct(id) => {
3827 return ty::lookup_item_type(fcx.ccx.tcx, id);
3829 ast::DefUpvar(_, inner, _, _) => {
3830 return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
3835 ast::DefTyParam(..)=> {
3836 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
3838 ast::DefMod(..) | ast::DefForeignMod(..) => {
3839 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
3841 ast::DefUse(..) => {
3842 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
3844 ast::DefRegion(..) => {
3845 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
3847 ast::DefTyParamBinder(..) => {
3848 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
3850 ast::DefLabel(..) => {
3851 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
3853 ast::DefSelfTy(..) => {
3854 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
3856 ast::DefMethod(..) => {
3857 fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
3862 // Instantiates the given path, which must refer to an item with the given
3863 // number of type parameters and type.
3864 pub fn instantiate_path(fcx: &FnCtxt,
3866 tpt: ty_param_bounds_and_ty,
3869 node_id: ast::NodeId) {
3870 debug!(">>> instantiate_path");
3872 let ty_param_count = tpt.generics.type_param_defs().len();
3873 let ty_param_req = tpt.generics.type_param_defs().iter()
3874 .take_while(|x| x.default.is_none())
3876 let mut ty_substs_len = 0;
3877 for segment in pth.segments.iter() {
3878 ty_substs_len += segment.types.len()
3881 debug!("tpt={} ty_param_count={:?} ty_substs_len={:?}",
3882 tpt.repr(fcx.tcx()),
3886 // determine the region parameters, using the value given by the user
3887 // (if any) and otherwise using a fresh region variable
3888 let num_expected_regions = tpt.generics.region_param_defs().len();
3889 let num_supplied_regions = pth.segments.last().unwrap().lifetimes.len();
3890 let regions = if num_expected_regions == num_supplied_regions {
3891 OwnedSlice::from_vec(pth.segments.last().unwrap().lifetimes.iter().map(
3892 |l| ast_region_to_region(fcx.tcx(), l)).collect())
3894 if num_supplied_regions != 0 {
3895 fcx.ccx.tcx.sess.span_err(
3897 format!("expected {nexpected, plural, =1{# lifetime parameter} \
3898 other{# lifetime parameters}}, \
3899 found {nsupplied, plural, =1{# lifetime parameter} \
3900 other{# lifetime parameters}}",
3901 nexpected = num_expected_regions,
3902 nsupplied = num_supplied_regions).as_slice());
3905 fcx.infcx().region_vars_for_defs(span, tpt.generics.region_param_defs.as_slice())
3907 let regions = ty::NonerasedRegions(regions);
3909 // Special case: If there is a self parameter, omit it from the list of
3912 // Here we calculate the "user type parameter count", which is the number
3913 // of type parameters actually manifest in the AST. This will differ from
3914 // the internal type parameter count when there are self types involved.
3915 let (user_ty_param_count, user_ty_param_req, self_parameter_index) = match def {
3916 ast::DefStaticMethod(_, provenance @ ast::FromTrait(_), _) => {
3917 let generics = generics_of_static_method_container(fcx.ccx.tcx,
3919 (ty_param_count - 1, ty_param_req - 1, Some(generics.type_param_defs().len()))
3921 _ => (ty_param_count, ty_param_req, None),
3924 // determine values for type parameters, using the values given by
3925 // the user (if any) and otherwise using fresh type variables
3926 let (tps, regions) = if ty_substs_len == 0 {
3927 (fcx.infcx().next_ty_vars(ty_param_count), regions)
3928 } else if ty_param_count == 0 {
3929 fcx.ccx.tcx.sess.span_err
3930 (span, "this item does not take type parameters");
3931 (fcx.infcx().next_ty_vars(ty_param_count), regions)
3932 } else if ty_substs_len > user_ty_param_count {
3933 let expected = if user_ty_param_req < user_ty_param_count {
3938 fcx.ccx.tcx.sess.span_err
3940 format!("too many type parameters provided: {} {}, found {}",
3941 expected, user_ty_param_count, ty_substs_len).as_slice());
3942 (fcx.infcx().next_ty_vars(ty_param_count), regions)
3943 } else if ty_substs_len < user_ty_param_req {
3944 let expected = if user_ty_param_req < user_ty_param_count {
3949 fcx.ccx.tcx.sess.span_err(
3951 format!("not enough type parameters provided: {} {}, found {}",
3954 ty_substs_len).as_slice());
3955 (fcx.infcx().next_ty_vars(ty_param_count), regions)
3957 if ty_substs_len > user_ty_param_req
3958 && !fcx.tcx().sess.features.default_type_params.get() {
3959 fcx.tcx().sess.span_err(pth.span, "default type parameters are \
3960 experimental and possibly buggy");
3961 fcx.tcx().sess.span_note(pth.span, "add #![feature(default_type_params)] \
3962 to the crate attributes to enable");
3965 // Build up the list of type parameters, inserting the self parameter
3966 // at the appropriate position.
3967 let mut tps = Vec::new();
3968 let mut pushed = false;
3969 for (i, ty) in pth.segments.iter()
3970 .flat_map(|segment| segment.types.iter())
3971 .map(|&ast_type| fcx.to_ty(ast_type))
3973 match self_parameter_index {
3974 Some(index) if index == i => {
3975 tps.push(*fcx.infcx().next_ty_vars(1).get(0));
3983 let mut substs = substs {
3989 let defaults = tpt.generics.type_param_defs().iter()
3990 .enumerate().filter_map(|(i, x)| {
3991 match self_parameter_index {
3992 Some(index) if index == i => None,
3993 _ => Some(x.default)
3996 for (i, default) in defaults.skip(ty_substs_len).enumerate() {
3997 match self_parameter_index {
3998 Some(index) if index == i + ty_substs_len => {
3999 substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0));
4006 let ty = default.subst_spanned(fcx.tcx(), &substs, Some(span));
4007 substs.tps.push(ty);
4010 fcx.tcx().sess.span_bug(span,
4011 "missing default for a not explicitely provided type param")
4016 // If the self parameter goes at the end, insert it there.
4017 if !pushed && self_parameter_index.is_some() {
4018 substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0))
4021 assert_eq!(substs.tps.len(), ty_param_count)
4023 let substs {tps, regions, ..} = substs;
4027 let substs = substs { regions: regions,
4031 fcx.write_ty_substs(node_id, tpt.ty, ty::ItemSubsts {
4038 // Resolves `typ` by a single level if `typ` is a type variable. If no
4039 // resolution is possible, then an error is reported.
4040 pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
4041 match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
4042 Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
4044 fcx.type_error_message(sp, |_actual| {
4045 "the type of this value must be known in this \
4046 context".to_string()
4048 demand::suptype(fcx, sp, ty::mk_err(), tp);
4054 // Returns the one-level-deep structure of the given type.
4055 pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
4057 &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
4060 pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4061 let typ_s = structurally_resolved_type(fcx, sp, typ);
4062 return ty::type_is_integral(typ_s);
4065 pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4066 let typ_s = structurally_resolved_type(fcx, sp, typ);
4067 return ty::type_is_uint(typ_s);
4070 pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4071 let typ_s = structurally_resolved_type(fcx, sp, typ);
4072 return ty::type_is_scalar(typ_s);
4075 pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4076 let typ_s = structurally_resolved_type(fcx, sp, typ);
4077 return ty::type_is_char(typ_s);
4080 pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4081 let typ_s = structurally_resolved_type(fcx, sp, typ);
4082 return ty::type_is_bare_fn(typ_s);
4085 pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4086 let typ_s = structurally_resolved_type(fcx, sp, typ);
4087 return ty::type_is_unsafe_ptr(typ_s);
4090 pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4091 let typ_s = structurally_resolved_type(fcx, sp, typ);
4092 return ty::type_is_region_ptr(typ_s);
4095 pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4096 let typ_s = structurally_resolved_type(fcx, sp, typ);
4097 return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
4100 pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
4103 mk_inner: || -> ty::mt)
4106 ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
4107 ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
4109 ast::ExprLit(..) => {
4110 // string literals and *empty slices* live in static memory
4111 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4113 ast::ExprVec(ref elements) if elements.len() == 0 => {
4114 // string literals and *empty slices* live in static memory
4115 ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
4117 ast::ExprRepeat(..) |
4118 ast::ExprVec(..) => {
4119 // vector literals are temporaries on the stack
4120 match fcx.tcx().region_maps.temporary_scope(e.id) {
4121 Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
4122 None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
4126 fcx.ccx.tcx.sess.span_bug(e.span,
4127 "vstore with unexpected \
4135 // Returns true if b contains a break that can exit from b
4136 pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
4137 // First: is there an unlabeled break immediately
4139 (loop_query(b, |e| {
4141 ast::ExprBreak(_) => true,
4145 // Second: is there a labeled break with label
4146 // <id> nested anywhere inside the loop?
4147 (block_query(b, |e| {
4149 ast::ExprBreak(Some(_)) => {
4150 match cx.def_map.borrow().find(&e.id) {
4151 Some(&ast::DefLabel(loop_id)) if id == loop_id => true,
4159 pub fn check_bounds_are_used(ccx: &CrateCtxt,
4161 tps: &OwnedSlice<ast::TyParam>,
4163 debug!("check_bounds_are_used(n_tps={}, ty={})",
4164 tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
4166 // make a vector of booleans initially false, set to true when used
4167 if tps.len() == 0u { return; }
4168 let mut tps_used = Vec::from_elem(tps.len(), false);
4170 ty::walk_ty(ty, |t| {
4171 match ty::get(t).sty {
4172 ty::ty_param(param_ty {idx, ..}) => {
4173 debug!("Found use of ty param \\#{}", idx);
4174 *tps_used.get_mut(idx) = true;
4180 for (i, b) in tps_used.iter().enumerate() {
4182 ccx.tcx.sess.span_err(
4184 format!("type parameter `{}` is unused",
4185 token::get_ident(tps.get(i).ident)).as_slice());
4190 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
4191 fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
4192 ty::mk_param(ccx.tcx, n, local_def(0))
4196 let name = token::get_ident(it.ident);
4197 let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
4198 let split : Vec<&str> = name.get().split('_').collect();
4199 assert!(split.len() >= 2, "Atomic intrinsic not correct format");
4201 //We only care about the operation here
4202 match *split.get(1) {
4203 "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
4207 "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
4209 "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4212 "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
4213 "min" | "umax" | "umin" => {
4214 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4218 (0, Vec::new(), ty::mk_nil())
4221 tcx.sess.span_err(it.span,
4222 format!("unrecognized atomic operation \
4231 "abort" => (0, Vec::new(), ty::mk_bot()),
4232 "breakpoint" => (0, Vec::new(), ty::mk_nil()),
4234 "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
4235 "init" => (1u, Vec::new(), param(ccx, 0u)),
4236 "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4237 "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4238 "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
4239 "move_val_init" => {
4242 ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
4247 "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
4248 "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
4251 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4253 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4255 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4257 mutbl: ast::MutImmutable
4259 (1u, Vec::new(), td_ptr)
4262 let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
4264 Ok(did) => (1u, Vec::new(), ty::mk_struct(ccx.tcx, did, substs {
4267 regions: ty::NonerasedRegions(OwnedSlice::empty())
4270 tcx.sess.span_fatal(it.span, msg.as_slice());
4275 let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
4277 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4279 let region = ty::ReLateBound(it.id, ty::BrAnon(0));
4280 let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
4281 Ok((_, vot)) => vot,
4282 Err(s) => { tcx.sess.span_fatal(it.span, s.as_slice()); }
4285 let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
4287 mutbl: ast::MutImmutable
4289 (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
4294 ty::mk_ptr(tcx, ty::mt {
4296 mutbl: ast::MutImmutable
4300 ty::mk_ptr(tcx, ty::mt {
4302 mutbl: ast::MutImmutable
4305 "copy_memory" | "copy_nonoverlapping_memory" |
4306 "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
4309 ty::mk_ptr(tcx, ty::mt {
4311 mutbl: ast::MutMutable
4313 ty::mk_ptr(tcx, ty::mt {
4315 mutbl: ast::MutImmutable
4321 "set_memory" | "volatile_set_memory" => {
4324 ty::mk_ptr(tcx, ty::mt {
4326 mutbl: ast::MutMutable
4333 "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4334 "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4337 vec!( ty::mk_f32(), ty::mk_i32() ),
4342 vec!( ty::mk_f64(), ty::mk_i32() ),
4345 "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4346 "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4347 "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4348 "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4351 vec!( ty::mk_f32(), ty::mk_f32() ),
4356 vec!( ty::mk_f64(), ty::mk_f64() ),
4359 "expf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4360 "expf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4361 "exp2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4362 "exp2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4363 "logf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4364 "logf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4365 "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4366 "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4367 "log2f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4368 "log2f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4371 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
4376 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
4379 "fabsf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4380 "fabsf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4381 "copysignf32" => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
4382 "copysignf64" => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
4383 "floorf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4384 "floorf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4385 "ceilf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4386 "ceilf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4387 "truncf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4388 "truncf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4389 "rintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4390 "rintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4391 "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4392 "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4393 "roundf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
4394 "roundf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
4395 "ctpop8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4396 "ctpop16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4397 "ctpop32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4398 "ctpop64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4399 "ctlz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4400 "ctlz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4401 "ctlz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4402 "ctlz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4403 "cttz8" => (0, vec!( ty::mk_u8() ), ty::mk_u8()),
4404 "cttz16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4405 "cttz32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4406 "cttz64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4407 "bswap16" => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
4408 "bswap32" => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
4409 "bswap64" => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
4412 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4414 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
4416 "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
4417 (0, vec!(ty::mk_i8(), ty::mk_i8()),
4418 ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
4420 "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
4421 (0, vec!(ty::mk_i16(), ty::mk_i16()),
4422 ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
4424 "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
4425 (0, vec!(ty::mk_i32(), ty::mk_i32()),
4426 ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
4428 "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
4429 (0, vec!(ty::mk_i64(), ty::mk_i64()),
4430 ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
4432 "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
4433 (0, vec!(ty::mk_u8(), ty::mk_u8()),
4434 ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
4436 "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
4437 (0, vec!(ty::mk_u16(), ty::mk_u16()),
4438 ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
4440 "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
4441 (0, vec!(ty::mk_u32(), ty::mk_u32()),
4442 ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
4444 "u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
4445 (0, vec!(ty::mk_u64(), ty::mk_u64()),
4446 ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
4449 tcx.sess.span_err(it.span,
4450 format!("unrecognized intrinsic function: `{}`",
4451 *other).as_slice());
4456 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
4457 fn_style: ast::UnsafeFn,
4458 abi: abi::RustIntrinsic,
4466 let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
4467 let i_n_tps = i_ty.generics.type_param_defs().len();
4468 if i_n_tps != n_tps {
4469 tcx.sess.span_err(it.span,
4470 format!("intrinsic has wrong number of type \
4471 parameters: found {}, expected {}",
4475 require_same_types(tcx,
4482 format!("intrinsic has wrong type: expected `{}`",
4483 ppaux::ty_to_str(ccx.tcx, fty))