Skip to content

Introduce cache for projection #32287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

27 changes: 24 additions & 3 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ pub struct InferCtxt<'a, 'tcx: 'a> {

pub tables: &'a RefCell<ty::Tables<'tcx>>,

// Cache for projections. This cache is snapshotted along with the
// infcx.
//
// Public so that `traits::project` can use it.
pub projection_cache: RefCell<traits::ProjectionCache<'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.
Expand Down Expand Up @@ -365,6 +371,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>,
InferCtxt {
tcx: tcx,
tables: tables,
projection_cache: RefCell::new(traits::ProjectionCache::new()),
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
Expand Down Expand Up @@ -516,6 +523,7 @@ fn expected_found<T>(a_is_expected: bool,

#[must_use = "once you start a snapshot, you should always consume it"]
pub struct CombinedSnapshot {
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
type_snapshot: type_variable::Snapshot,
int_snapshot: unify::Snapshot<ty::IntVid>,
float_snapshot: unify::Snapshot<ty::FloatVid>,
Expand Down Expand Up @@ -725,6 +733,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

fn start_snapshot(&self) -> CombinedSnapshot {
CombinedSnapshot {
projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
type_snapshot: self.type_variables.borrow_mut().snapshot(),
int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
Expand All @@ -734,11 +743,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) {
debug!("rollback_to(cause={})", cause);
let CombinedSnapshot { type_snapshot,
let CombinedSnapshot { projection_cache_snapshot,
type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = snapshot;

self.projection_cache
.borrow_mut()
.rollback_to(projection_cache_snapshot);
self.type_variables
.borrow_mut()
.rollback_to(type_snapshot);
Expand All @@ -754,11 +767,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

fn commit_from(&self, snapshot: CombinedSnapshot) {
debug!("commit_from!");
let CombinedSnapshot { type_snapshot,
let CombinedSnapshot { projection_cache_snapshot,
type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = snapshot;

self.projection_cache
.borrow_mut()
.commit(projection_cache_snapshot);
self.type_variables
.borrow_mut()
.commit(type_snapshot);
Expand Down Expand Up @@ -805,7 +822,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
F: FnOnce() -> Result<T, E>
{
debug!("commit_regions_if_ok()");
let CombinedSnapshot { type_snapshot,
let CombinedSnapshot { projection_cache_snapshot,
type_snapshot,
int_snapshot,
float_snapshot,
region_vars_snapshot } = self.start_snapshot();
Expand All @@ -816,6 +834,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

// Roll back any non-region bindings - they should be resolved
// inside `f`, with, e.g. `resolve_type_vars_if_possible`.
self.projection_cache
.borrow_mut()
.rollback_to(projection_cache_snapshot);
self.type_variables
.borrow_mut()
.rollback_to(type_snapshot);
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
// also includes references to its upvars as part
// of its type, and those types are resolved at
// the same time.
//
// FIXME(#32286) logic seems false if no upvars
pending_obligation.stalled_on =
trait_ref_type_vars(selcx, data.to_poly_trait_ref());

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Trait Resolution. See the Book for more.
//! Trait Resolution. See README.md for an overview of how this works.

pub use self::SelectionError::*;
pub use self::FulfillmentErrorCode::*;
Expand Down Expand Up @@ -36,8 +36,9 @@ pub use self::coherence::orphan_check;
pub use self::coherence::overlapping_impls;
pub use self::coherence::OrphanCheckErr;
pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
pub use self::project::{MismatchedProjectionTypes, ProjectionMode};
pub use self::project::MismatchedProjectionTypes;
pub use self::project::{normalize, Normalized};
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, ProjectionMode};
pub use self::object_safety::is_object_safe;
pub use self::object_safety::astconv_object_safety_violations;
pub use self::object_safety::object_safety_violations;
Expand Down
Loading