Skip to content
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

Rollup of 7 pull requests #69172

Merged
merged 19 commits into from
Feb 15, 2020
Merged
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
90afc07
Use a `ParamEnvAnd<Predicate>` for caching in `ObligationForest`
Aaron1011 Jan 23, 2020
6509db8
or_patterns: harden bindings test
Centril Feb 5, 2020
29437e5
or_patterns: rename previous test
Centril Feb 5, 2020
17e632d
or_patterns: test default binding modes
Centril Feb 5, 2020
b5aca31
typeck: refactor default binding mode logic & improve docs
Centril Feb 5, 2020
3806056
Correct inference of primitive operand type behind binary operation
varkor Jan 11, 2020
0276d7a
Add more tests
varkor Feb 9, 2020
ebbaf46
simplify_try: address some of eddyb's comments
Centril Feb 11, 2020
f5bd964
fix extra subslice lowering
Centril Feb 13, 2020
dbd8220
Avoid `base_parser`, it's not needed.
nnethercote Feb 4, 2020
88b0912
Fix a typo in a variable name.
nnethercote Feb 10, 2020
d8589de
Update pulldown-cmark dependency
GuillaumeGomez Feb 13, 2020
3f7ed88
Rollup merge of #68129 - varkor:infer-binary-operand-behind-reference…
JohnTitor Feb 14, 2020
2c5bdee
Rollup merge of #68475 - Aaron1011:fix/forest-caching, r=nikomatsakis
JohnTitor Feb 14, 2020
829a363
Rollup merge of #68856 - Centril:or-pat-ref-pat, r=matthewjasper
JohnTitor Feb 14, 2020
e0ea1e7
Rollup merge of #69051 - Centril:st-fixes, r=eddyb
JohnTitor Feb 14, 2020
940fff7
Rollup merge of #69128 - Centril:fix-69103, r=davidtwco
JohnTitor Feb 14, 2020
72def9a
Rollup merge of #69150 - nnethercote:68848-follow-up, r=petrochenkov
JohnTitor Feb 14, 2020
a6ff1db
Rollup merge of #69164 - GuillaumeGomez:update-pulldown-cmark, r=Dyla…
JohnTitor Feb 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Use a ParamEnvAnd<Predicate> for caching in ObligationForest
Previously, we used a plain `Predicate` to cache results (e.g. successes
and failures) in ObligationForest. However, fulfillment depends on the
precise `ParamEnv` used, so this is unsound in general.

This commit changes the impl of `ForestObligation` for
`PendingPredicateObligation` to use `ParamEnvAnd<Predicate>` instead of
`Predicate` for the associated type. The associated type and method are
renamed from 'predicate' to 'cache_key' to reflect the fact that type is
no longer just a predicate.
Aaron1011 committed Jan 23, 2020

Verified

This commit was signed with the committer’s verified signature.
Aaron1011 Aaron Hill
commit 90afc0765e5e536af6307b63e1655a38df06e235
9 changes: 6 additions & 3 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
@@ -18,10 +18,13 @@ use super::{FulfillmentError, FulfillmentErrorCode};
use super::{ObligationCause, PredicateObligation};

impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
type Predicate = ty::Predicate<'tcx>;
/// Note that we include both the `ParamEnv` and the `Predicate`,
/// as the `ParamEnv` can influence whether fulfillment succeeds
/// or fails.
type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;

fn as_predicate(&self) -> &Self::Predicate {
&self.obligation.predicate
fn as_cache_key(&self) -> Self::CacheKey {
self.obligation.param_env.and(self.obligation.predicate)
}
}

2 changes: 1 addition & 1 deletion src/librustc_data_structures/obligation_forest/graphviz.rs
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest<O>

fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> {
let node = &self.nodes[*index];
let label = format!("{:?} ({:?})", node.obligation.as_predicate(), node.state.get());
let label = format!("{:?} ({:?})", node.obligation.as_cache_key(), node.state.get());

dot::LabelText::LabelStr(label.into())
}
29 changes: 17 additions & 12 deletions src/librustc_data_structures/obligation_forest/mod.rs
Original file line number Diff line number Diff line change
@@ -86,9 +86,13 @@ mod graphviz;
mod tests;

pub trait ForestObligation: Clone + Debug {
type Predicate: Clone + hash::Hash + Eq + Debug;
type CacheKey: Clone + hash::Hash + Eq + Debug;

fn as_predicate(&self) -> &Self::Predicate;
/// Converts this `ForestObligation` suitable for use as a cache key.
/// If two distinct `ForestObligations`s return the same cache key,
/// then it must be sound to use the result of processing one obligation
/// (e.g. success for error) for the other obligation
fn as_cache_key(&self) -> Self::CacheKey;
}

pub trait ObligationProcessor {
@@ -138,12 +142,12 @@ pub struct ObligationForest<O: ForestObligation> {
nodes: Vec<Node<O>>,

/// A cache of predicates that have been successfully completed.
done_cache: FxHashSet<O::Predicate>,
done_cache: FxHashSet<O::CacheKey>,

/// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately,
/// its contents are not guaranteed to match those of `nodes`. See the
/// comments in `process_obligation` for details.
active_cache: FxHashMap<O::Predicate, usize>,
active_cache: FxHashMap<O::CacheKey, usize>,

/// A vector reused in compress(), to avoid allocating new vectors.
node_rewrites: RefCell<Vec<usize>>,
@@ -157,7 +161,7 @@ pub struct ObligationForest<O: ForestObligation> {
/// See [this][details] for details.
///
/// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780
error_cache: FxHashMap<ObligationTreeId, FxHashSet<O::Predicate>>,
error_cache: FxHashMap<ObligationTreeId, FxHashSet<O::CacheKey>>,
}

#[derive(Debug)]
@@ -305,11 +309,12 @@ impl<O: ForestObligation> ObligationForest<O> {

// Returns Err(()) if we already know this obligation failed.
fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Result<(), ()> {
if self.done_cache.contains(obligation.as_predicate()) {
if self.done_cache.contains(&obligation.as_cache_key()) {
debug!("register_obligation_at: ignoring already done obligation: {:?}", obligation);
return Ok(());
}

match self.active_cache.entry(obligation.as_predicate().clone()) {
match self.active_cache.entry(obligation.as_cache_key().clone()) {
Entry::Occupied(o) => {
let node = &mut self.nodes[*o.get()];
if let Some(parent_index) = parent {
@@ -333,7 +338,7 @@ impl<O: ForestObligation> ObligationForest<O> {
&& self
.error_cache
.get(&obligation_tree_id)
.map(|errors| errors.contains(obligation.as_predicate()))
.map(|errors| errors.contains(&obligation.as_cache_key()))
.unwrap_or(false);

if already_failed {
@@ -380,7 +385,7 @@ impl<O: ForestObligation> ObligationForest<O> {
self.error_cache
.entry(node.obligation_tree_id)
.or_default()
.insert(node.obligation.as_predicate().clone());
.insert(node.obligation.as_cache_key().clone());
}

/// Performs a pass through the obligation list. This must
@@ -618,11 +623,11 @@ impl<O: ForestObligation> ObligationForest<O> {
// `self.nodes`. See the comment in `process_obligation`
// for more details.
if let Some((predicate, _)) =
self.active_cache.remove_entry(node.obligation.as_predicate())
self.active_cache.remove_entry(&node.obligation.as_cache_key())
{
self.done_cache.insert(predicate);
} else {
self.done_cache.insert(node.obligation.as_predicate().clone());
self.done_cache.insert(node.obligation.as_cache_key().clone());
}
if do_completed == DoCompleted::Yes {
// Extract the success stories.
@@ -635,7 +640,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// We *intentionally* remove the node from the cache at this point. Otherwise
// tests must come up with a different type on every type error they
// check against.
self.active_cache.remove(node.obligation.as_predicate());
self.active_cache.remove(&node.obligation.as_cache_key());
self.insert_into_error_cache(index);
node_rewrites[index] = orig_nodes_len;
dead_nodes += 1;
4 changes: 2 additions & 2 deletions src/librustc_data_structures/obligation_forest/tests.rs
Original file line number Diff line number Diff line change
@@ -4,9 +4,9 @@ use std::fmt;
use std::marker::PhantomData;

impl<'a> super::ForestObligation for &'a str {
type Predicate = &'a str;
type CacheKey = &'a str;

fn as_predicate(&self) -> &Self::Predicate {
fn as_cache_key(&self) -> Self::CacheKey {
self
}
}