Move the list of region obligations into the fulfillment context.
This commit is contained in:
parent
9bdd7f0040
commit
70be49d2c7
@ -9,11 +9,15 @@
|
||||
// except according to those terms.
|
||||
|
||||
use middle::mem_categorization::Typer;
|
||||
use middle::ty;
|
||||
use middle::infer::InferCtxt;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::infer::{mod, InferCtxt};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::hash_map::{Occupied, Vacant};
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use util::ppaux::Repr;
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
use super::CodeAmbiguity;
|
||||
use super::TraitObligation;
|
||||
@ -47,6 +51,38 @@ pub struct FulfillmentContext<'tcx> {
|
||||
// attempted to select. This is used to avoid repeating work
|
||||
// when `select_new_obligations` is called.
|
||||
attempted_mark: uint,
|
||||
|
||||
// A set of constraints that regionck must validate. Each
|
||||
// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
// outlive the lifetime 'a". These constraints derive from
|
||||
// instantiated type parameters. So if you had a struct defined
|
||||
// like
|
||||
//
|
||||
// struct Foo<T:'static> { ... }
|
||||
//
|
||||
// then in some expression `let x = Foo { ... }` it will
|
||||
// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
// the same time, it will record a region obligation of
|
||||
// `$0:'static`. This will get checked later by regionck. (We
|
||||
// can't generally check these things right away because we have
|
||||
// to wait until types are resolved.)
|
||||
//
|
||||
// These are stored in a map keyed to the id of the innermost
|
||||
// enclosing fn body / static initializer expression. This is
|
||||
// because the location where the obligation was incurred can be
|
||||
// relevant with respect to which sublifetime assumptions are in
|
||||
// place. The reason that we store under the fn-id, and not
|
||||
// something more fine-grained, is so that it is easier for
|
||||
// regionck to be sure that it has found *all* the region
|
||||
// obligations (otherwise, it's easy to fail to walk to a
|
||||
// particular node-id).
|
||||
region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
|
||||
}
|
||||
|
||||
pub struct RegionObligation<'tcx> {
|
||||
pub sub_region: ty::Region,
|
||||
pub sup_type: Ty<'tcx>,
|
||||
pub origin: infer::SubregionOrigin<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> FulfillmentContext<'tcx> {
|
||||
@ -55,6 +91,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
duplicate_set: HashSet::new(),
|
||||
trait_obligations: Vec::new(),
|
||||
attempted_mark: 0,
|
||||
region_obligations: NodeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,6 +108,26 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_region_obligation(&mut self,
|
||||
body_id: ast::NodeId,
|
||||
region_obligation: RegionObligation<'tcx>)
|
||||
{
|
||||
match self.region_obligations.entry(body_id) {
|
||||
Vacant(entry) => { entry.set(vec![region_obligation]); },
|
||||
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn region_obligations(&self,
|
||||
body_id: ast::NodeId)
|
||||
-> &[RegionObligation<'tcx>]
|
||||
{
|
||||
match self.region_obligations.get(&body_id) {
|
||||
None => Default::default(),
|
||||
Some(vec) => vec.as_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_all_or_error<'a>(&mut self,
|
||||
infcx: &InferCtxt<'a,'tcx>,
|
||||
param_env: &ty::ParameterEnvironment<'tcx>,
|
||||
@ -208,3 +265,12 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
|
||||
self.sub_region.repr(tcx),
|
||||
self.sup_type.repr(tcx),
|
||||
self.origin.repr(tcx))
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use syntax::ast;
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
use util::common::ErrorReported;
|
||||
|
||||
pub use self::fulfill::FulfillmentContext;
|
||||
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
||||
pub use self::select::SelectionContext;
|
||||
pub use self::select::SelectionCache;
|
||||
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
|
||||
|
@ -84,13 +84,14 @@ use self::TupleArgumentsFlag::*;
|
||||
|
||||
use astconv::{mod, ast_region_to_region, ast_ty_to_ty, AstConv};
|
||||
use check::_match::pat_ctxt;
|
||||
use middle::{const_eval, def, traits};
|
||||
use middle::{const_eval, def};
|
||||
use middle::infer;
|
||||
use middle::lang_items::IteratorItem;
|
||||
use middle::mem_categorization::{mod, McResult};
|
||||
use middle::pat_util::{mod, pat_id_map};
|
||||
use middle::region::CodeExtent;
|
||||
use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace};
|
||||
use middle::traits;
|
||||
use middle::ty::{FnSig, VariantInfo, Polytype};
|
||||
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
|
||||
use middle::ty::{mod, Ty};
|
||||
@ -108,7 +109,6 @@ use util::ppaux::{mod, UserString, Repr};
|
||||
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
|
||||
|
||||
use std::cell::{Cell, Ref, RefCell};
|
||||
use std::collections::hash_map::{Occupied, Vacant};
|
||||
use std::mem::replace;
|
||||
use std::rc::Rc;
|
||||
use syntax::{mod, abi, attr};
|
||||
@ -161,42 +161,10 @@ pub struct Inherited<'a, 'tcx: 'a> {
|
||||
// one is never copied into the tcx: it is only used by regionck.
|
||||
fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
|
||||
|
||||
// A set of constraints that regionck must validate. Each
|
||||
// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
// outlive the lifetime 'a". These constraints derive from
|
||||
// instantiated type parameters. So if you had a struct defined
|
||||
// like
|
||||
//
|
||||
// struct Foo<T:'static> { ... }
|
||||
//
|
||||
// then in some expression `let x = Foo { ... }` it will
|
||||
// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
// the same time, it will record a region obligation of
|
||||
// `$0:'static`. This will get checked later by regionck. (We
|
||||
// can't generally check these things right away because we have
|
||||
// to wait until types are resolved.)
|
||||
//
|
||||
// These are stored in a map keyed to the id of the innermost
|
||||
// enclosing fn body / static initializer expression. This is
|
||||
// because the location where the obligation was incurred can be
|
||||
// relevant with respect to which sublifetime assumptions are in
|
||||
// place. The reason that we store under the fn-id, and not
|
||||
// something more fine-grained, is so that it is easier for
|
||||
// regionck to be sure that it has found *all* the region
|
||||
// obligations (otherwise, it's easy to fail to walk to a
|
||||
// particular node-id).
|
||||
region_obligations: RefCell<NodeMap<Vec<RegionObligation<'tcx>>>>,
|
||||
|
||||
// Tracks trait obligations incurred during this function body.
|
||||
fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
|
||||
}
|
||||
|
||||
struct RegionObligation<'tcx> {
|
||||
sub_region: ty::Region,
|
||||
sup_type: Ty<'tcx>,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
}
|
||||
|
||||
/// When type-checking an expression, we propagate downward
|
||||
/// whatever type hint we are able in the form of an `Expectation`.
|
||||
enum Expectation<'tcx> {
|
||||
@ -328,7 +296,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
||||
upvar_borrow_map: RefCell::new(FnvHashMap::new()),
|
||||
unboxed_closures: RefCell::new(DefIdMap::new()),
|
||||
fn_sig_map: RefCell::new(NodeMap::new()),
|
||||
region_obligations: RefCell::new(NodeMap::new()),
|
||||
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
|
||||
}
|
||||
}
|
||||
@ -1988,15 +1955,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
r: ty::Region)
|
||||
{
|
||||
let mut region_obligations = self.inh.region_obligations.borrow_mut();
|
||||
let region_obligation = RegionObligation { sub_region: r,
|
||||
sup_type: ty,
|
||||
origin: origin };
|
||||
|
||||
match region_obligations.entry(self.body_id) {
|
||||
Vacant(entry) => { entry.set(vec![region_obligation]); },
|
||||
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
|
||||
}
|
||||
let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
|
||||
let region_obligation = traits::RegionObligation { sub_region: r,
|
||||
sup_type: ty,
|
||||
origin: origin };
|
||||
fulfillment_cx.register_region_obligation(self.body_id, region_obligation);
|
||||
}
|
||||
|
||||
pub fn add_default_region_param_bounds(&self,
|
||||
@ -5833,11 +5796,3 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
|
||||
self.sub_region.repr(tcx),
|
||||
self.sup_type.repr(tcx),
|
||||
self.origin.repr(tcx))
|
||||
}
|
||||
}
|
||||
|
@ -353,18 +353,13 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
fn visit_region_obligations(&mut self, node_id: ast::NodeId)
|
||||
{
|
||||
debug!("visit_region_obligations: node_id={}", node_id);
|
||||
let region_obligations = self.fcx.inh.region_obligations.borrow();
|
||||
match region_obligations.get(&node_id) {
|
||||
None => { }
|
||||
Some(vec) => {
|
||||
for r_o in vec.iter() {
|
||||
debug!("visit_region_obligations: r_o={}",
|
||||
r_o.repr(self.tcx()));
|
||||
let sup_type = self.resolve_type(r_o.sup_type);
|
||||
type_must_outlive(self, r_o.origin.clone(),
|
||||
sup_type, r_o.sub_region);
|
||||
}
|
||||
}
|
||||
let fulfillment_cx = self.fcx.inh.fulfillment_cx.borrow();
|
||||
for r_o in fulfillment_cx.region_obligations(node_id).iter() {
|
||||
debug!("visit_region_obligations: r_o={}",
|
||||
r_o.repr(self.tcx()));
|
||||
let sup_type = self.resolve_type(r_o.sup_type);
|
||||
type_must_outlive(self, r_o.origin.clone(),
|
||||
sup_type, r_o.sub_region);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user