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;
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()),
// 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,
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;
}