Ground work for replacing the ClosureTyper trait
This commit is contained in:
parent
79d02895ff
commit
480cd8fe67
15 changed files with 170 additions and 21 deletions
|
@ -283,7 +283,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
|
|||
|
||||
fn check_static_type(&self, e: &ast::Expr) {
|
||||
let ty = self.tcx.node_id_to_type(e.id);
|
||||
let infcx = infer::new_infer_ctxt(self.tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
|
||||
let mut fulfill_cx = traits::FulfillmentContext::new(false);
|
||||
let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
|
||||
fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
|
||||
|
|
|
@ -1031,7 +1031,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
|
|||
substs: trait_substs });
|
||||
|
||||
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
|
||||
let mut selcx = traits::SelectionContext::new(&infcx, &infcx.parameter_environment);
|
||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
||||
|
|
|
@ -23,19 +23,24 @@ pub use self::freshen::TypeFreshener;
|
|||
pub use self::region_inference::GenericKind;
|
||||
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::McResult;
|
||||
use middle::region::{self, CodeExtent};
|
||||
use middle::subst;
|
||||
use middle::subst::Substs;
|
||||
use middle::subst::Subst;
|
||||
use middle::traits;
|
||||
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
|
||||
use middle::ty::{self, Ty, HasTypeFlags};
|
||||
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
|
||||
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
|
||||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use std::cell::{RefCell};
|
||||
use std::cell::{RefCell, Ref};
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::codemap::Span;
|
||||
use util::nodemap::FnvHashMap;
|
||||
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
|
||||
|
||||
use self::combine::CombineFields;
|
||||
use self::region_inference::{RegionVarBindings, RegionSnapshot};
|
||||
|
@ -64,6 +69,8 @@ pub type fres<T> = Result<T, fixup_err>; // "fixup result"
|
|||
pub struct InferCtxt<'a, 'tcx: 'a> {
|
||||
pub tcx: &'a ty::ctxt<'tcx>,
|
||||
|
||||
pub tables: &'a RefCell<ty::Tables<'tcx>>,
|
||||
|
||||
// We instantiate UnificationTable with bounds<Ty> because the
|
||||
// types that might instantiate a general type variable have an
|
||||
// order, represented by its upper and lower bounds.
|
||||
|
@ -80,7 +87,9 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
|
|||
|
||||
pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>,
|
||||
|
||||
// pub tables: &'a RefCell<ty::Tables<'tcx>>
|
||||
normalize: bool,
|
||||
|
||||
err_count_on_creation: usize,
|
||||
}
|
||||
|
||||
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
|
||||
|
@ -314,15 +323,19 @@ pub fn fixup_err_to_string(f: fixup_err) -> String {
|
|||
}
|
||||
|
||||
pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
|
||||
tables: &'a RefCell<ty::Tables<'tcx>>,
|
||||
param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
|
||||
-> InferCtxt<'a, 'tcx> {
|
||||
InferCtxt {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
||||
int_unification_table: RefCell::new(UnificationTable::new()),
|
||||
float_unification_table: RefCell::new(UnificationTable::new()),
|
||||
region_vars: RegionVarBindings::new(tcx),
|
||||
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment())
|
||||
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
|
||||
normalize: true,
|
||||
err_count_on_creation: tcx.sess.err_count()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,6 +450,92 @@ pub struct CombinedSnapshot {
|
|||
region_vars_snapshot: RegionSnapshot,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> mc::Typer<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
||||
let ty = self.node_ty(id);
|
||||
self.resolve_type_vars_or_error(&ty)
|
||||
}
|
||||
|
||||
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
|
||||
let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
|
||||
self.resolve_type_vars_or_error(&ty)
|
||||
}
|
||||
|
||||
fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||
!traits::type_known_to_meet_builtin_bound(self, self, ty, ty::BoundCopy, span)
|
||||
}
|
||||
|
||||
fn node_method_ty(&self, method_call: ty::MethodCall)
|
||||
-> Option<Ty<'tcx>> {
|
||||
self.tables
|
||||
.borrow()
|
||||
.method_map
|
||||
.get(&method_call)
|
||||
.map(|method| method.ty)
|
||||
.map(|ty| self.resolve_type_vars_if_possible(&ty))
|
||||
}
|
||||
|
||||
fn node_method_origin(&self, method_call: ty::MethodCall)
|
||||
-> Option<ty::MethodOrigin<'tcx>>
|
||||
{
|
||||
self.tables
|
||||
.borrow()
|
||||
.method_map
|
||||
.get(&method_call)
|
||||
.map(|method| method.origin.clone())
|
||||
}
|
||||
|
||||
fn adjustments(&self) -> Ref<NodeMap<ty::AutoAdjustment<'tcx>>> {
|
||||
fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) -> &'a NodeMap<ty::AutoAdjustment<'tcx>> {
|
||||
&tables.adjustments
|
||||
}
|
||||
|
||||
Ref::map(self.tables.borrow(), project_adjustments)
|
||||
}
|
||||
|
||||
fn is_method_call(&self, id: ast::NodeId) -> bool {
|
||||
self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
|
||||
}
|
||||
|
||||
fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
|
||||
self.parameter_environment.temporary_scope(rvalue_id)
|
||||
}
|
||||
|
||||
fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
|
||||
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
|
||||
&self.parameter_environment
|
||||
}
|
||||
|
||||
fn closure_kind(&self,
|
||||
def_id: ast::DefId)
|
||||
-> Option<ty::ClosureKind>
|
||||
{
|
||||
self.tables.borrow().closure_kinds.get(&def_id).cloned()
|
||||
}
|
||||
|
||||
fn closure_type(&self,
|
||||
def_id: ast::DefId,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self.tcx, substs)
|
||||
}
|
||||
|
||||
fn closure_upvars(&self,
|
||||
def_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Option<Vec<ty::ClosureUpvar<'tcx>>>
|
||||
{
|
||||
ty::ctxt::closure_upvars(self, def_id, substs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
|
||||
t.fold_with(&mut self.freshener())
|
||||
|
@ -858,6 +957,48 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.region_vars.new_bound(debruijn)
|
||||
}
|
||||
|
||||
/// Apply `adjustment` to the type of `expr`
|
||||
pub fn adjust_expr_ty(&self,
|
||||
expr: &ast::Expr,
|
||||
adjustment: Option<&ty::AutoAdjustment<'tcx>>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
let raw_ty = self.expr_ty(expr);
|
||||
let raw_ty = self.shallow_resolve(raw_ty);
|
||||
let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty);
|
||||
raw_ty.adjust(self.tcx,
|
||||
expr.span,
|
||||
expr.id,
|
||||
adjustment,
|
||||
|method_call| self.tables
|
||||
.borrow()
|
||||
.method_map
|
||||
.get(&method_call)
|
||||
.map(|method| resolve_ty(method.ty)))
|
||||
}
|
||||
|
||||
pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
|
||||
match self.tables.borrow().node_types.get(&id) {
|
||||
Some(&t) => t,
|
||||
// FIXME
|
||||
None if self.tcx.sess.err_count() - self.err_count_on_creation != 0 => self.tcx.types.err,
|
||||
None => {
|
||||
self.tcx.sess.bug(
|
||||
&format!("no type for node {}: {} in fcx",
|
||||
id, self.tcx.map.node_to_string(id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
|
||||
match self.tables.borrow().node_types.get(&ex.id) {
|
||||
Some(&t) => t,
|
||||
None => {
|
||||
self.tcx.sess.bug(&format!("no type for expr in fcx"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_regions_and_report_errors(&self,
|
||||
free_regions: &FreeRegionMap,
|
||||
subject_node_id: ast::NodeId) {
|
||||
|
@ -932,6 +1073,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
value.fold_with(&mut r)
|
||||
}
|
||||
|
||||
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.has_infer_types() || ty.references_error() { Err(()) } else { Ok(ty) }
|
||||
}
|
||||
|
||||
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> fres<T> {
|
||||
/*!
|
||||
* Attempts to resolve all type/region variables in
|
||||
|
|
|
@ -397,7 +397,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
|
|||
|
||||
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx, Some(elaborated_env));
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
|
||||
let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause,
|
||||
&infcx.parameter_environment.caller_bounds) {
|
||||
Ok(predicates) => predicates,
|
||||
|
|
|
@ -54,6 +54,7 @@ use util::nodemap::FnvHashMap;
|
|||
|
||||
pub struct SelectionContext<'cx, 'tcx:'cx> {
|
||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||
|
||||
closure_typer: &'cx (ty::ClosureTyper<'tcx>+'cx),
|
||||
|
||||
/// Freshener used specifically for skolemizing entries on the
|
||||
|
@ -77,6 +78,7 @@ pub struct SelectionContext<'cx, 'tcx:'cx> {
|
|||
/// other words, we consider `$0 : Bar` to be unimplemented if
|
||||
/// there is no type that the user could *actually name* that
|
||||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
|
||||
intercrate: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -4468,7 +4468,8 @@ impl<'tcx> TyS<'tcx> {
|
|||
span: Span)
|
||||
-> bool
|
||||
{
|
||||
let infcx = infer::new_infer_ctxt(param_env.tcx(), Some(param_env.clone()));
|
||||
let tcx = param_env.tcx();
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env.clone()));
|
||||
|
||||
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env,
|
||||
self, bound, span);
|
||||
|
|
|
@ -997,7 +997,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
trait_ref, trait_ref.def_id());
|
||||
|
||||
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
|
@ -1059,7 +1059,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
predicates);
|
||||
|
||||
let tcx = ccx.tcx();
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
let typer = NormalizingClosureTyper::new(tcx);
|
||||
let mut selcx = traits::SelectionContext::new(&infcx, &typer);
|
||||
let mut fulfill_cx = traits::FulfillmentContext::new(false);
|
||||
|
|
|
@ -324,7 +324,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
|
|||
// FIXME(#20304) -- cache
|
||||
// NOTE: @jroesch
|
||||
// Here is of an example where we do not use a param_env but use a typer instead.
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
let typer = NormalizingClosureTyper::new(tcx);
|
||||
let mut selcx = traits::SelectionContext::new(&infcx, &typer);
|
||||
let cause = traits::ObligationCause::dummy();
|
||||
|
|
|
@ -43,7 +43,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
|
||||
impl_trait_ref);
|
||||
|
||||
let mut infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
let mut fulfillment_cx = traits::FulfillmentContext::new(true);
|
||||
|
||||
let trait_to_impl_substs = &impl_trait_ref.substs;
|
||||
|
@ -418,7 +418,7 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
debug!("compare_const_impl(impl_trait_ref={:?})",
|
||||
impl_trait_ref);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
let mut fulfillment_cx = traits::FulfillmentContext::new(true);
|
||||
|
||||
// The below is for the most part highly similar to the procedure
|
||||
|
|
|
@ -93,8 +93,8 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
|
|||
ty: named_type } =
|
||||
tcx.lookup_item_type(self_type_did);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
|
||||
infcx.commit_if_ok(|snapshot| {
|
||||
let (named_type_to_skolem, skol_map) =
|
||||
infcx.construct_skolemized_subst(named_type_generics, snapshot);
|
||||
|
|
|
@ -382,7 +382,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
|||
-> Inherited<'a, 'tcx> {
|
||||
|
||||
Inherited {
|
||||
infcx: infer::new_infer_ctxt(tcx, Some(param_env)),
|
||||
infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
|
||||
locals: RefCell::new(NodeMap()),
|
||||
tables: tables,
|
||||
fn_sig_map: RefCell::new(NodeMap()),
|
||||
|
|
|
@ -448,7 +448,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
|
||||
source, target);
|
||||
|
||||
let infcx = new_infer_ctxt(tcx, Some(param_env));
|
||||
let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
|
||||
|
||||
let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
|
||||
mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
|
||||
|
@ -630,7 +630,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||
pub fn check_coherence(crate_context: &CrateCtxt) {
|
||||
CoherenceChecker {
|
||||
crate_context: crate_context,
|
||||
inference_context: new_infer_ctxt(crate_context.tcx, None),
|
||||
inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None),
|
||||
inherent_impls: RefCell::new(FnvHashMap()),
|
||||
}.check(crate_context.tcx.map.krate());
|
||||
unsafety::check(crate_context.tcx);
|
||||
|
|
|
@ -133,7 +133,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
|
|||
impl1_def_id,
|
||||
impl2_def_id);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(self.tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
|
||||
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
|
||||
self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
|
||||
}
|
||||
|
|
|
@ -2204,7 +2204,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
|||
base_type,
|
||||
base_type_free);
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
drop(::require_same_types(tcx,
|
||||
Some(&infcx),
|
||||
false,
|
||||
|
|
|
@ -188,7 +188,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
|
|||
{
|
||||
let result = match maybe_infcx {
|
||||
None => {
|
||||
let infcx = infer::new_infer_ctxt(tcx, None);
|
||||
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
|
||||
infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
|
||||
}
|
||||
Some(infcx) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue