1
Fork 0

Ground work for replacing the ClosureTyper trait

This commit is contained in:
Jared Roesch 2015-06-25 13:08:10 -07:00
parent 79d02895ff
commit 480cd8fe67
15 changed files with 170 additions and 21 deletions

View file

@ -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);

View file

@ -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(),

View file

@ -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

View file

@ -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,

View file

@ -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,
}

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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

View file

@ -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);

View file

@ -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()),

View file

@ -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);

View file

@ -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);
}

View file

@ -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,

View file

@ -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) => {