pub use self::region_inference::{GenericKind, VerifyBound};
use hir::def_id::DefId;
-use hir;
use middle::free_region::{FreeRegionMap, RegionRelations};
use middle::region::RegionMaps;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::McResult;
use middle::lang_items;
use mir::tcx::LvalueTy;
use ty::subst::{Kind, Subst, Substs};
use rustc_data_structures::unify::{self, UnificationTable};
use std::cell::{Cell, RefCell, Ref, RefMut};
use std::fmt;
-use std::ops::Deref;
use syntax::ast;
use errors::DiagnosticBuilder;
use syntax_pos::{self, Span, DUMMY_SP};
/// `InProgress` (during typeck) or `Interned` (result of typeck).
/// Only the `InProgress` version supports `borrow_mut`.
#[derive(Copy, Clone)]
-pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- Interned(&'a ty::TypeckTables<'gcx>),
+pub enum InferTables<'a, 'tcx: 'a> {
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
Missing
}
-pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
- Interned(&'a ty::TypeckTables<'gcx>),
- InProgress(Ref<'a, ty::TypeckTables<'tcx>>)
-}
-
-impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> {
- type Target = ty::TypeckTables<'tcx>;
- fn deref(&self) -> &Self::Target {
- match *self {
- InferTablesRef::Interned(tables) => tables,
- InferTablesRef::InProgress(ref tables) => tables
- }
- }
-}
-
-impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> {
- pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> {
+impl<'a, 'tcx> InferTables<'a, 'tcx> {
+ pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> {
match self {
- InferTables::Interned(tables) => InferTablesRef::Interned(tables),
- InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()),
+ InferTables::InProgress(tables) => tables.borrow(),
InferTables::Missing => {
bug!("InferTables: infcx.tables.borrow() with no tables")
}
}
}
- pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> {
- match self {
- InferTables::Interned(tables) => tables,
- InferTables::InProgress(_) => {
- bug!("InferTables: infcx.tables.expect_interned() during type-checking");
- }
- InferTables::Missing => {
- bug!("InferTables: infcx.tables.expect_interned() with no tables")
- }
- }
- }
-
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
match self {
- InferTables::Interned(_) => {
- bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking");
- }
InferTables::InProgress(tables) => tables.borrow_mut(),
InferTables::Missing => {
bug!("InferTables: infcx.tables.borrow_mut() with no tables")
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
- pub tables: InferTables<'a, 'gcx, 'tcx>,
+ pub tables: InferTables<'a, 'tcx>,
// Cache for projections. This cache is snapshotted along with the
// infcx.
}
pub trait InferEnv<'a, 'tcx> {
- fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> (Option<&'a ty::TypeckTables<'tcx>>,
- Option<ty::TypeckTables<'tcx>>);
+ fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>>;
}
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
- fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
- -> (Option<&'a ty::TypeckTables<'tcx>>,
- Option<ty::TypeckTables<'tcx>>) {
- (None, None)
- }
-}
-
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> {
- fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
- -> (Option<&'a ty::TypeckTables<'tcx>>,
- Option<ty::TypeckTables<'tcx>>) {
- (Some(self), None)
+ fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
+ None
}
}
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
- fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
- -> (Option<&'a ty::TypeckTables<'tcx>>,
- Option<ty::TypeckTables<'tcx>>) {
- (None, Some(self))
- }
-}
-
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
- fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> (Option<&'a ty::TypeckTables<'tcx>>,
- Option<ty::TypeckTables<'tcx>>) {
- let def_id = tcx.hir.body_owner_def_id(self);
- (Some(tcx.typeck_tables_of(def_id)), None)
+ fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
+ Some(self)
}
}
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
arena: DroplessArena,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
- tables: Option<&'a ty::TypeckTables<'gcx>>,
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
- let (tables, fresh_tables) = env.to_parts(self);
InferCtxtBuilder {
global_tcx: self,
arena: DroplessArena::new(),
- fresh_tables: fresh_tables.map(RefCell::new),
- tables: tables,
+ fresh_tables: env.fresh_tables().map(RefCell::new),
}
}
/// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
/// for MemCategorizationContext/ExprUseVisitor.
/// If any inference functionality is used, ICEs will occur.
- pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
- -> InferCtxt<'a, 'gcx, 'gcx> {
- let (tables, _) = body.to_parts(self);
+ pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> {
InferCtxt {
tcx: self,
- tables: InferTables::Interned(tables.unwrap()),
+ tables: InferTables::Missing,
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
global_tcx,
ref arena,
ref fresh_tables,
- tables,
} = *self;
- let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
- fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
- });
+ let tables = fresh_tables.as_ref()
+ .map_or(InferTables::Missing, InferTables::InProgress);
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
tcx: tcx,
tables: tables,
self.tainted_by_errors_flag.set(true)
}
- pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
- match self.tables.borrow().node_types.get(&id) {
- Some(&t) => t,
- // FIXME
- None if self.is_tainted_by_errors() =>
- self.tcx.types.err,
- None => {
- bug!("no type for node {}: {} in fcx",
- id, self.tcx.hir.node_to_string(id));
- }
- }
- }
-
- pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
- match self.tables.borrow().node_types.get(&ex.id) {
- Some(&t) => t,
- None => {
- bug!("no type for expr in fcx");
- }
- }
- }
-
pub fn resolve_regions_and_report_errors(&self,
region_context: DefId,
region_map: &RegionMaps,
value.fold_with(&mut r)
}
- /// Resolves all type variables in `t` and then, if any were left
- /// unresolved, substitutes an error type. This is used after the
- /// main checking when doing a second pass before writeback. The
- /// justification is that writeback will produce an error for
- /// these unconstrained type variables.
- fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
- let ty = self.resolve_type_vars_if_possible(t);
- if ty.references_error() || ty.is_ty_var() {
- debug!("resolve_type_vars_or_error: error from {:?}", ty);
- Err(())
- } else {
- Ok(ty)
- }
- }
-
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
/*!
* Attempts to resolve all type/region variables in
self.region_vars.verify_generic_bound(origin, kind, a, bound);
}
- pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
- let ty = self.node_type(id);
- self.resolve_type_vars_or_error(&ty)
- }
-
- pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
- let ty = self.tables.borrow().expr_ty_adjusted(expr);
- self.resolve_type_vars_or_error(&ty)
- }
-
pub fn type_moves_by_default(&self,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
}
- pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
- self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
- }
-
pub fn closure_kind(&self,
def_id: DefId)
-> Option<ty::ClosureKind>