rustc: make the comon case of tcx.infer_ctxt(()) nicer.
This commit is contained in:
parent
63481a57dc
commit
fc5c31c48c
@ -31,7 +31,7 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use ty::relate::RelateResult;
|
||||
use traits::{self, ObligationCause, PredicateObligations, Reveal};
|
||||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use std::cell::{Cell, RefCell, Ref, RefMut};
|
||||
use std::cell::{Cell, RefCell, Ref};
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use errors::DiagnosticBuilder;
|
||||
@ -72,39 +72,14 @@ pub type Bound<T> = Option<T>;
|
||||
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
|
||||
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
|
||||
|
||||
/// A version of &ty::TypeckTables which can be `Missing` (not needed),
|
||||
/// `InProgress` (during typeck) or `Interned` (result of typeck).
|
||||
/// Only the `InProgress` version supports `borrow_mut`.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum InferTables<'a, 'tcx: 'a> {
|
||||
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
|
||||
Missing
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferTables<'a, 'tcx> {
|
||||
pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> {
|
||||
match self {
|
||||
InferTables::InProgress(tables) => tables.borrow(),
|
||||
InferTables::Missing => {
|
||||
bug!("InferTables: infcx.tables.borrow() with no tables")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
|
||||
match self {
|
||||
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, 'tcx>,
|
||||
/// During type-checking/inference of a body, `in_progress_tables`
|
||||
/// contains a reference to the tables being built up, which are
|
||||
/// used for reading closure kinds/signatures as they are inferred,
|
||||
/// and for error reporting logic to read arbitrary node types.
|
||||
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
|
||||
|
||||
// Cache for projections. This cache is snapshotted along with the
|
||||
// infcx.
|
||||
@ -360,23 +335,7 @@ impl fmt::Display for FixupError {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InferEnv<'a, 'tcx> {
|
||||
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
||||
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
|
||||
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper type of a temporary returned by tcx.infer_ctxt(...).
|
||||
/// Helper type of a temporary returned by tcx.infer_ctxt().
|
||||
/// Necessary because we can't write the following bound:
|
||||
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
|
||||
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
@ -386,16 +345,23 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
InferCtxtBuilder {
|
||||
global_tcx: self,
|
||||
arena: DroplessArena::new(),
|
||||
fresh_tables: env.fresh_tables().map(RefCell::new),
|
||||
fresh_tables: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
/// Used only by `rustc_typeck` during body type-checking/inference,
|
||||
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
|
||||
pub fn with_fresh_in_progress_tables(mut self) -> Self {
|
||||
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
|
||||
where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R
|
||||
{
|
||||
@ -404,11 +370,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
ref arena,
|
||||
ref fresh_tables,
|
||||
} = *self;
|
||||
let tables = fresh_tables.as_ref()
|
||||
.map_or(InferTables::Missing, InferTables::InProgress);
|
||||
let in_progress_tables = fresh_tables.as_ref();
|
||||
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
tcx,
|
||||
in_progress_tables,
|
||||
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
||||
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
||||
int_unification_table: RefCell::new(UnificationTable::new()),
|
||||
@ -531,7 +496,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
return value;
|
||||
}
|
||||
|
||||
self.infer_ctxt(()).enter(|infcx| {
|
||||
self.infer_ctxt().enter(|infcx| {
|
||||
value.trans_normalize(&infcx, param_env)
|
||||
})
|
||||
}
|
||||
@ -553,7 +518,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
return value;
|
||||
}
|
||||
|
||||
self.infer_ctxt(()).enter(|infcx| {
|
||||
self.infer_ctxt().enter(|infcx| {
|
||||
value.trans_normalize(&infcx, env.reveal_all())
|
||||
})
|
||||
}
|
||||
@ -757,10 +722,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
was_in_snapshot: in_snapshot,
|
||||
// Borrow tables "in progress" (i.e. during typeck)
|
||||
// to ban writes from within a snapshot to them.
|
||||
_in_progress_tables: match self.tables {
|
||||
InferTables::InProgress(ref tables) => tables.try_borrow().ok(),
|
||||
_ => None
|
||||
}
|
||||
_in_progress_tables: self.in_progress_tables.map(|tables| {
|
||||
tables.borrow()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1366,14 +1330,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
span: Span)
|
||||
-> bool {
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
|
||||
// Even if the type may have no inference variables, during
|
||||
// type-checking closure types are in local tables only.
|
||||
let local_closures = match self.tables {
|
||||
InferTables::InProgress(_) => ty.has_closure_types(),
|
||||
_ => false
|
||||
};
|
||||
if !local_closures {
|
||||
// Even if the type may have no inference variables, during
|
||||
// type-checking closure types are in local tables only.
|
||||
if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
|
||||
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
|
||||
return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
|
||||
}
|
||||
}
|
||||
@ -1391,7 +1351,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
def_id: DefId)
|
||||
-> Option<ty::ClosureKind>
|
||||
{
|
||||
if let InferTables::InProgress(tables) = self.tables {
|
||||
if let Some(tables) = self.in_progress_tables {
|
||||
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||
return tables.borrow()
|
||||
.closure_kinds
|
||||
@ -1409,7 +1369,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
|
||||
if let InferTables::InProgress(tables) = self.tables {
|
||||
if let Some(tables) = self.in_progress_tables {
|
||||
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||
if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
|
||||
return ty;
|
||||
|
@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body};
|
||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use hir::map::NodeExpr;
|
||||
use hir::def_id::DefId;
|
||||
use infer::{self, InferCtxt, InferTables};
|
||||
use infer::{self, InferCtxt};
|
||||
use infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
||||
use std::fmt;
|
||||
@ -72,9 +72,12 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||
fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
|
||||
match self.infcx.tables.borrow().node_types.get(node_id) {
|
||||
Some(&ty) => {
|
||||
fn node_matches_type(&mut self, node_id: NodeId) -> bool {
|
||||
let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
|
||||
tables.borrow().node_id_to_type_opt(node_id)
|
||||
});
|
||||
match ty_opt {
|
||||
Some(ty) => {
|
||||
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
||||
ty.walk().any(|inner_ty| {
|
||||
inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
|
||||
@ -88,7 +91,7 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,7 +102,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, local: &'gcx Local) {
|
||||
if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
|
||||
if self.found_local_pattern.is_none() && self.node_matches_type(local.id) {
|
||||
self.found_local_pattern = Some(&*local.pat);
|
||||
}
|
||||
intravisit::walk_local(self, local);
|
||||
@ -107,7 +110,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn visit_body(&mut self, body: &'gcx Body) {
|
||||
for argument in &body.arguments {
|
||||
if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
|
||||
if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) {
|
||||
self.found_arg_pattern = Some(&*argument.pat);
|
||||
}
|
||||
}
|
||||
@ -654,7 +657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Additional context information explaining why the closure only implements
|
||||
// a particular trait.
|
||||
if let InferTables::InProgress(tables) = self.tables {
|
||||
if let Some(tables) = self.in_progress_tables {
|
||||
match tables.borrow().closure_kinds.get(&node_id) {
|
||||
Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => {
|
||||
err.span_note(span, &format!(
|
||||
|
@ -484,7 +484,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
|
||||
unnormalized_env.reveal);
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let predicates = match fully_normalize(
|
||||
&infcx,
|
||||
cause,
|
||||
@ -598,7 +598,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("normalize_and_test_predicates(predicates={:?})",
|
||||
predicates);
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
let mut fulfill_cx = FulfillmentContext::new();
|
||||
|
@ -125,7 +125,7 @@ pub fn find_associated_item<'a, 'tcx>(
|
||||
let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
|
||||
match ancestors.defs(tcx, item.name, item.kind).next() {
|
||||
Some(node_item) => {
|
||||
let substs = tcx.infer_ctxt(()).enter(|infcx| {
|
||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
||||
@ -188,7 +188,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
|
||||
|
||||
// Create a infcx, taking the predicates of impl1 as assumptions:
|
||||
let result = tcx.infer_ctxt(()).enter(|infcx| {
|
||||
let result = tcx.infer_ctxt().enter(|infcx| {
|
||||
// Normalize the trait reference. The WF rules ought to ensure
|
||||
// that this always succeeds.
|
||||
let impl1_trait_ref =
|
||||
|
@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children {
|
||||
let possible_sibling = *slot;
|
||||
|
||||
let tcx = tcx.global_tcx();
|
||||
let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| {
|
||||
let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
|
||||
let overlap = traits::overlapping_impls(&infcx,
|
||||
possible_sibling,
|
||||
impl_def_id);
|
||||
|
@ -46,7 +46,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
self.infer_ctxt(()).enter(|infcx| {
|
||||
self.infer_ctxt().enter(|infcx| {
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
|
||||
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||
|
@ -175,7 +175,7 @@ impl<'tcx> ty::ParamEnv<'tcx> {
|
||||
self_type: Ty<'tcx>, span: Span)
|
||||
-> Result<(), CopyImplementationError<'tcx>> {
|
||||
// FIXME: (@jroesch) float this code up
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let (adt, substs) = match self_type.sty {
|
||||
ty::TyAdt(adt, substs) => (adt, substs),
|
||||
_ => return Err(CopyImplementationError::NotAnAdt),
|
||||
@ -977,7 +977,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
{
|
||||
let (param_env, ty) = query.into_parts();
|
||||
let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
|
||||
tcx.infer_ctxt(())
|
||||
tcx.infer_ctxt()
|
||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||
param_env,
|
||||
ty,
|
||||
@ -991,7 +991,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
{
|
||||
let (param_env, ty) = query.into_parts();
|
||||
let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
||||
tcx.infer_ctxt(())
|
||||
tcx.infer_ctxt()
|
||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||
param_env,
|
||||
ty,
|
||||
@ -1005,7 +1005,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
{
|
||||
let (param_env, ty) = query.into_parts();
|
||||
let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
|
||||
tcx.infer_ctxt(())
|
||||
tcx.infer_ctxt()
|
||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||
param_env,
|
||||
ty,
|
||||
|
@ -483,7 +483,7 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
||||
trait_ref);
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
||||
|
@ -154,7 +154,7 @@ fn test_env<F>(source_string: &str,
|
||||
index,
|
||||
"test_crate",
|
||||
|tcx| {
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut region_maps = RegionMaps::new();
|
||||
body(Env {
|
||||
infcx: &infcx,
|
||||
|
@ -956,7 +956,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
|
||||
cx.param_env,
|
||||
trait_ref.to_poly_trait_predicate());
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
match selcx.select(&obligation) {
|
||||
// The method comes from a `T: Trait` bound.
|
||||
|
@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
|
||||
};
|
||||
|
||||
let src = MirSource::from_node(tcx, id);
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let cx = Cx::new(&infcx, src);
|
||||
let mut mir = if cx.tables().tainted_by_errors {
|
||||
build::construct_error(cx, body_id)
|
||||
@ -171,7 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
{
|
||||
let span = tcx.hir.span(ctor_id);
|
||||
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let (mut mir, src) =
|
||||
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
||||
|
||||
|
@ -998,7 +998,7 @@ impl MirPass for QualifyAndPromoteConstants {
|
||||
// Statics must be Sync.
|
||||
if mode == Mode::Static {
|
||||
let ty = mir.return_ty;
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
|
||||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
||||
|
@ -759,7 +759,7 @@ impl MirPass for TypeckMir {
|
||||
return;
|
||||
}
|
||||
let param_env = tcx.param_env(def_id);
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut checker = TypeChecker::new(&infcx, item_id, param_env);
|
||||
{
|
||||
let mut verifier = TypeVerifier::new(&mut checker, mir);
|
||||
|
@ -219,7 +219,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env,
|
||||
normalize_cause.clone());
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let inh = Inherited::new(infcx, impl_m.def_id);
|
||||
let infcx = &inh.infcx;
|
||||
|
||||
@ -726,7 +726,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>) {
|
||||
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let inh = Inherited::new(infcx, impl_c.def_id);
|
||||
let infcx = &inh.infcx;
|
||||
|
@ -79,7 +79,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
||||
|
||||
// check that the impl type can be made to match the trait type.
|
||||
|
||||
tcx.infer_ctxt(()).enter(|ref infcx| {
|
||||
tcx.infer_ctxt().enter(|ref infcx| {
|
||||
let impl_param_env = tcx.param_env(self_type_did);
|
||||
let tcx = infcx.tcx;
|
||||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
||||
|
@ -108,7 +108,7 @@ use lint;
|
||||
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;
|
||||
@ -147,6 +147,33 @@ mod compare_method;
|
||||
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() {
|
||||
@ -159,6 +186,8 @@ mod op;
|
||||
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>>,
|
||||
@ -535,9 +564,8 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
@ -562,6 +590,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
||||
});
|
||||
|
||||
Inherited {
|
||||
tables: MaybeInProgressTables {
|
||||
maybe_tables: infcx.in_progress_tables,
|
||||
},
|
||||
infcx: infcx,
|
||||
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
|
||||
locals: RefCell::new(NodeMap()),
|
||||
@ -3302,14 +3333,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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,
|
||||
|
@ -208,7 +208,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source,
|
||||
target);
|
||||
|
||||
tcx.infer_ctxt(()).enter(|infcx| {
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let cause = ObligationCause::misc(span, impl_node_id);
|
||||
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
||||
mt_b: ty::TypeAndMut<'tcx>,
|
||||
|
@ -70,7 +70,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
|
||||
|
||||
for (i, &impl1_def_id) in impls.iter().enumerate() {
|
||||
for &impl2_def_id in &impls[(i + 1)..] {
|
||||
self.tcx.infer_ctxt(()).enter(|infcx| {
|
||||
self.tcx.infer_ctxt().enter(|infcx| {
|
||||
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
|
||||
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>)
|
||||
-> bool {
|
||||
tcx.infer_ctxt(()).enter(|ref infcx| {
|
||||
tcx.infer_ctxt().enter(|ref infcx| {
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
let mut fulfill_cx = FulfillmentContext::new();
|
||||
match infcx.at(&cause, param_env).eq(expected, actual) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user