use util::common::{ErrorReported, indenter};
use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
-use std::cell::{Cell, RefCell};
+use std::cell::{Cell, RefCell, Ref, RefMut};
use std::collections::hash_map::Entry;
use std::cmp;
use std::mem::replace;
use syntax::ptr::P;
use syntax::symbol::{Symbol, InternedString, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
-use syntax_pos::{self, BytePos, Span, DUMMY_SP};
+use syntax_pos::{self, BytePos, Span};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
mod intrinsic;
mod op;
+/// A wrapper for InferCtxt's `in_progress_tables` field.
+#[derive(Copy, Clone)]
+struct MaybeInProgressTables<'a, 'tcx: 'a> {
+ maybe_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
+}
+
+impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> {
+ fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> {
+ match self.maybe_tables {
+ Some(tables) => tables.borrow(),
+ None => {
+ bug!("MaybeInProgressTables: inh/fcx.tables.borrow() with no tables")
+ }
+ }
+ }
+
+ fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
+ match self.maybe_tables {
+ Some(tables) => tables.borrow_mut(),
+ None => {
+ bug!("MaybeInProgressTables: inh/fcx.tables.borrow_mut() with no tables")
+ }
+ }
+ }
+}
+
+
/// closures defined within the function. For example:
///
/// fn foo() {
pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: InferCtxt<'a, 'gcx, 'tcx>,
+ tables: MaybeInProgressTables<'a, 'tcx>,
+
locals: RefCell<NodeMap<Ty<'tcx>>>,
fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
- let tables = ty::TypeckTables::empty();
InheritedBuilder {
- infcx: tcx.infer_ctxt(tables),
+ infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(),
def_id,
}
}
});
Inherited {
+ tables: MaybeInProgressTables {
+ maybe_tables: infcx.in_progress_tables,
+ },
infcx: infcx,
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
locals: RefCell::new(NodeMap()),
}
}
- let signature = |item: &ty::AssociatedItem| {
- match item.kind {
- ty::AssociatedKind::Method => {
- format!("{}", tcx.type_of(item.def_id).fn_sig().0)
- }
- ty::AssociatedKind::Type => format!("type {};", item.name.to_string()),
- ty::AssociatedKind::Const => {
- format!("const {}: {:?};", item.name.to_string(), tcx.type_of(item.def_id))
- }
- }
- };
-
if !missing_items.is_empty() {
let mut err = struct_span_err!(tcx.sess, impl_span, E0046,
"not all trait items implemented, missing: `{}`",
if let Some(span) = tcx.hir.span_if_local(trait_item.def_id) {
err.span_label(span, format!("`{}` from trait", trait_item.name));
} else {
- err.note(&format!("`{}` from trait: `{}`",
- trait_item.name,
- signature(&trait_item)));
+ err.note_trait_signature(trait_item.name.to_string(),
+ trait_item.signature(&tcx));
}
}
err.emit();
value)
}
- pub fn write_nil(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, self.tcx.mk_nil());
- }
-
- pub fn write_error(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, self.tcx.types.err);
- }
-
pub fn require_type_meets(&self,
ty: Ty<'tcx>,
span: Span,
// We also need to make sure we at least write the ty of the other
// arguments which we skipped above.
if variadic {
+ fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
+ type_error_struct!(s, span, t, E0617,
+ "can't pass `{}` to variadic function, cast to `{}`",
+ t, cast_ty).emit();
+ }
+
for arg in args.iter().skip(expected_arg_count) {
let arg_ty = self.check_expr(&arg);
// There are a few types which get autopromoted when passed via varargs
// in C but we just error out instead and require explicit casts.
- let arg_ty = self.structurally_resolved_type(arg.span,
- arg_ty);
+ let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
match arg_ty.sty {
ty::TyFloat(ast::FloatTy::F32) => {
- self.type_error_message(arg.span, |t| {
- format!("can't pass an `{}` to variadic \
- function, cast to `c_double`", t)
- }, arg_ty);
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
}
ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
- self.type_error_message(arg.span, |t| {
- format!("can't pass `{}` to variadic \
- function, cast to `c_int`",
- t)
- }, arg_ty);
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
}
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
- self.type_error_message(arg.span, |t| {
- format!("can't pass `{}` to variadic \
- function, cast to `c_uint`",
- t)
- }, arg_ty);
+ variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
}
ty::TyFnDef(.., f) => {
let ptr_ty = self.tcx.mk_fn_ptr(f);
let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
- self.type_error_message(arg.span,
- |t| {
- format!("can't pass `{}` to variadic \
- function, cast to `{}`", t, ptr_ty)
- }, arg_ty);
+ variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
}
_ => {}
}
.emit();
self.tcx().types.err
} else {
- let mut err = self.type_error_struct(field.span, |actual| {
- format!("no field `{}` on type `{}`",
- field.node, actual)
- }, expr_t);
- match expr_t.sty {
- ty::TyAdt(def, _) if !def.is_enum() => {
- if let Some(suggested_field_name) =
- Self::suggest_field_name(def.struct_variant(), field, vec![]) {
- err.span_label(field.span,
- format!("did you mean `{}`?", suggested_field_name));
- } else {
- err.span_label(field.span,
- "unknown field");
- };
- }
- ty::TyRawPtr(..) => {
- err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \
- `(*{0}).{1}`",
- self.tcx.hir.node_to_pretty_string(base.id),
- field.node));
+ if !expr_t.is_primitive_ty() {
+ let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0609,
+ "no field `{}` on type `{}`",
+ field.node, expr_t);
+ match expr_t.sty {
+ ty::TyAdt(def, _) if !def.is_enum() => {
+ if let Some(suggested_field_name) =
+ Self::suggest_field_name(def.struct_variant(), field, vec![]) {
+ err.span_label(field.span,
+ format!("did you mean `{}`?", suggested_field_name));
+ } else {
+ err.span_label(field.span, "unknown field");
+ };
+ }
+ ty::TyRawPtr(..) => {
+ err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \
+ with `(*{0}).{1}`",
+ self.tcx.hir.node_to_pretty_string(base.id),
+ field.node));
+ }
+ _ => {}
}
- _ => {}
- }
- err.emit();
+ err
+ } else {
+ type_error_struct!(self.tcx().sess, field.span, expr_t, E0610,
+ "`{}` is a primitive type and therefore doesn't have fields",
+ expr_t)
+ }.emit();
self.tcx().types.err
}
}
self.check_expr_has_type(base_expr, struct_ty);
match struct_ty.sty {
ty::TyAdt(adt, substs) if adt.is_struct() => {
- self.tables.borrow_mut().fru_field_types.insert(
- expr.id,
- adt.struct_variant().fields.iter().map(|f| {
- self.normalize_associated_types_in(
- expr.span, &f.ty(self.tcx, substs)
- )
- }).collect()
- );
+ let fru_field_types = adt.struct_variant().fields.iter().map(|f| {
+ self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs))
+ }).collect();
+ self.tables.borrow_mut().fru_field_types.insert(expr.id, fru_field_types);
}
_ => {
span_err!(self.tcx.sess, base_expr.span, E0436,
pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
// Don't do all the complex logic below for DeclItem.
match stmt.node {
- hir::StmtDecl(ref decl, id) => {
+ hir::StmtDecl(ref decl, _) => {
match decl.node {
hir::DeclLocal(_) => {}
hir::DeclItem(_) => {
- self.write_nil(id);
return;
}
}
self.diverges.set(Diverges::Maybe);
self.has_errors.set(false);
- let (node_id, _span) = match stmt.node {
- hir::StmtDecl(ref decl, id) => {
- let span = match decl.node {
+ match stmt.node {
+ hir::StmtDecl(ref decl, _) => {
+ match decl.node {
hir::DeclLocal(ref l) => {
self.check_decl_local(&l);
- l.span
- }
- hir::DeclItem(_) => {/* ignore for now */
- DUMMY_SP
}
- };
- (id, span)
+ hir::DeclItem(_) => {/* ignore for now */}
+ }
}
- hir::StmtExpr(ref expr, id) => {
+ hir::StmtExpr(ref expr, _) => {
// Check with expected type of ()
self.check_expr_has_type(&expr, self.tcx.mk_nil());
- (id, expr.span)
}
- hir::StmtSemi(ref expr, id) => {
+ hir::StmtSemi(ref expr, _) => {
self.check_expr(&expr);
- (id, expr.span)
}
- };
-
- if self.has_errors.get() {
- self.write_error(node_id);
- } else {
- self.write_nil(node_id);
}
// Combine the diverging and has_error flags.
hir::StmtSemi(ref e, _) => e,
_ => return,
};
- let last_expr_ty = self.expr_ty(last_expr);
+ let last_expr_ty = self.node_ty(last_expr.id);
if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
return;
}