Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b212a3f

Browse files
committedAug 19, 2017
Auto merge of #43952 - arielb1:the-big-backout, r=nikomatsakis
[beta] back out #42480 and its dependents #42480 makes the ICE in #43132 worse, and the "safe" fix to that causes the #43787 exponential worst-case. Let's back everything out for beta to avoid regressions, and get the permafix in nightly.
2 parents 54279df + 97e9c7e commit b212a3f

File tree

13 files changed

+287
-400
lines changed

13 files changed

+287
-400
lines changed
 

‎src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ define_dep_nodes!( <'tcx>
495495
// imprecision in our dep-graph tracking. The important thing is
496496
// that for any given trait-ref, we always map to the **same**
497497
// trait-select node.
498-
[anon] TraitSelect,
498+
[] TraitSelect { trait_def_id: DefId, input_def_id: DefId },
499499

500500
// For proj. cache, we just keep a list of all def-ids, since it is
501501
// not a hotspot.

‎src/librustc/dep_graph/dep_tracking_map.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,24 @@ use rustc_data_structures::fx::FxHashMap;
1212
use std::cell::RefCell;
1313
use std::hash::Hash;
1414
use std::marker::PhantomData;
15+
use ty::TyCtxt;
1516
use util::common::MemoizationMap;
1617

17-
use super::{DepKind, DepNodeIndex, DepGraph};
18+
use super::{DepNode, DepGraph};
1819

1920
/// A DepTrackingMap offers a subset of the `Map` API and ensures that
2021
/// we make calls to `read` and `write` as appropriate. We key the
2122
/// maps with a unique type for brevity.
2223
pub struct DepTrackingMap<M: DepTrackingMapConfig> {
2324
phantom: PhantomData<M>,
2425
graph: DepGraph,
25-
map: FxHashMap<M::Key, (M::Value, DepNodeIndex)>,
26+
map: FxHashMap<M::Key, M::Value>,
2627
}
2728

2829
pub trait DepTrackingMapConfig {
2930
type Key: Eq + Hash + Clone;
3031
type Value: Clone;
31-
fn to_dep_kind() -> DepKind;
32+
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode;
3233
}
3334

3435
impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
@@ -39,6 +40,27 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
3940
map: FxHashMap(),
4041
}
4142
}
43+
44+
/// Registers a (synthetic) read from the key `k`. Usually this
45+
/// is invoked automatically by `get`.
46+
fn read(&self, tcx: TyCtxt, k: &M::Key) {
47+
let dep_node = M::to_dep_node(tcx, k);
48+
self.graph.read(dep_node);
49+
}
50+
51+
pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> {
52+
self.read(tcx, k);
53+
self.map.get(k)
54+
}
55+
56+
pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool {
57+
self.read(tcx, k);
58+
self.map.contains_key(k)
59+
}
60+
61+
pub fn keys(&self) -> Vec<M::Key> {
62+
self.map.keys().cloned().collect()
63+
}
4264
}
4365

4466
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
@@ -76,22 +98,22 @@ impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
7698
/// The key is the line marked `(*)`: the closure implicitly
7799
/// accesses the body of the item `item`, so we register a read
78100
/// from `Hir(item_def_id)`.
79-
fn memoize<OP>(&self, key: M::Key, op: OP) -> M::Value
101+
fn memoize<OP>(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value
80102
where OP: FnOnce() -> M::Value
81103
{
82104
let graph;
83105
{
84106
let this = self.borrow();
85-
if let Some(&(ref result, dep_node)) = this.map.get(&key) {
86-
this.graph.read_index(dep_node);
107+
if let Some(result) = this.map.get(&key) {
108+
this.read(tcx, &key);
87109
return result.clone();
88110
}
89111
graph = this.graph.clone();
90112
}
91113

92-
let (result, dep_node) = graph.with_anon_task(M::to_dep_kind(), op);
93-
self.borrow_mut().map.insert(key, (result.clone(), dep_node));
94-
graph.read_index(dep_node);
114+
let _task = graph.in_task(M::to_dep_node(tcx, &key));
115+
let result = op();
116+
self.borrow_mut().map.insert(key, result.clone());
95117
result
96118
}
97119
}

‎src/librustc/traits/fulfill.rs

Lines changed: 112 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use dep_graph::DepGraph;
1112
use infer::{InferCtxt, InferOk};
12-
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
13+
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
1314
use ty::error::ExpectedFound;
1415
use rustc_data_structures::obligation_forest::{ObligationForest, Error};
1516
use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
1617
use std::marker::PhantomData;
1718
use syntax::ast;
18-
use util::nodemap::NodeMap;
19+
use util::nodemap::{FxHashSet, NodeMap};
1920
use hir::def_id::DefId;
2021

2122
use super::CodeAmbiguity;
@@ -33,6 +34,11 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
3334
fn as_predicate(&self) -> &Self::Predicate { &self.obligation.predicate }
3435
}
3536

37+
pub struct GlobalFulfilledPredicates<'tcx> {
38+
set: FxHashSet<ty::PolyTraitPredicate<'tcx>>,
39+
dep_graph: DepGraph,
40+
}
41+
3642
/// The fulfillment context is used to drive trait resolution. It
3743
/// consists of a list of obligations that must be (eventually)
3844
/// satisfied. The job is to track which are satisfied, which yielded
@@ -177,6 +183,13 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
177183

178184
assert!(!infcx.is_in_snapshot());
179185

186+
let tcx = infcx.tcx;
187+
188+
if tcx.fulfilled_predicates.borrow().check_duplicate(tcx, &obligation.predicate) {
189+
debug!("register_predicate_obligation: duplicate");
190+
return
191+
}
192+
180193
self.predicates.register_obligation(PendingPredicateObligation {
181194
obligation,
182195
stalled_on: vec![]
@@ -251,6 +264,13 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
251264
});
252265
debug!("select: outcome={:?}", outcome);
253266

267+
// these are obligations that were proven to be true.
268+
for pending_obligation in outcome.completed {
269+
let predicate = &pending_obligation.obligation.predicate;
270+
selcx.tcx().fulfilled_predicates.borrow_mut()
271+
.add_if_global(selcx.tcx(), predicate);
272+
}
273+
254274
errors.extend(
255275
outcome.errors.into_iter()
256276
.map(|e| to_fulfillment_error(e)));
@@ -298,7 +318,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
298318
_marker: PhantomData<&'c PendingPredicateObligation<'tcx>>)
299319
where I: Clone + Iterator<Item=&'c PendingPredicateObligation<'tcx>>,
300320
{
301-
if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
321+
if coinductive_match(self.selcx, cycle.clone()) {
302322
debug!("process_child_obligations: coinductive match");
303323
} else {
304324
let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
@@ -355,31 +375,21 @@ fn process_predicate<'a, 'gcx, 'tcx>(
355375

356376
match obligation.predicate {
357377
ty::Predicate::Trait(ref data) => {
358-
let trait_obligation = obligation.with(data.clone());
359-
360-
if data.is_global() {
361-
// no type variables present, can use evaluation for better caching.
362-
// FIXME: consider caching errors too.
363-
if
364-
// make defaulted unit go through the slow path for better warnings,
365-
// please remove this when the warnings are removed.
366-
!trait_obligation.predicate.skip_binder().self_ty().is_defaulted_unit() &&
367-
selcx.evaluate_obligation_conservatively(&obligation) {
368-
debug!("selecting trait `{:?}` at depth {} evaluated to holds",
369-
data, obligation.recursion_depth);
370-
return Ok(Some(vec![]))
371-
}
378+
let tcx = selcx.tcx();
379+
if tcx.fulfilled_predicates.borrow().check_duplicate_trait(tcx, data) {
380+
return Ok(Some(vec![]));
372381
}
373382

383+
let trait_obligation = obligation.with(data.clone());
374384
match selcx.select(&trait_obligation) {
375385
Ok(Some(vtable)) => {
376386
debug!("selecting trait `{:?}` at depth {} yielded Ok(Some)",
377-
data, obligation.recursion_depth);
387+
data, obligation.recursion_depth);
378388
Ok(Some(vtable.nested_obligations()))
379389
}
380390
Ok(None) => {
381391
debug!("selecting trait `{:?}` at depth {} yielded Ok(None)",
382-
data, obligation.recursion_depth);
392+
data, obligation.recursion_depth);
383393

384394
// This is a bit subtle: for the most part, the
385395
// only reason we can fail to make progress on
@@ -540,6 +550,40 @@ fn process_predicate<'a, 'gcx, 'tcx>(
540550
}
541551
}
542552

553+
/// For defaulted traits, we use a co-inductive strategy to solve, so
554+
/// that recursion is ok. This routine returns true if the top of the
555+
/// stack (`cycle[0]`):
556+
/// - is a defaulted trait, and
557+
/// - it also appears in the backtrace at some position `X`; and,
558+
/// - all the predicates at positions `X..` between `X` an the top are
559+
/// also defaulted traits.
560+
fn coinductive_match<'a,'c,'gcx,'tcx,I>(selcx: &mut SelectionContext<'a,'gcx,'tcx>,
561+
cycle: I) -> bool
562+
where I: Iterator<Item=&'c PendingPredicateObligation<'tcx>>,
563+
'tcx: 'c
564+
{
565+
let mut cycle = cycle;
566+
cycle
567+
.all(|bt_obligation| {
568+
let result = coinductive_obligation(selcx, &bt_obligation.obligation);
569+
debug!("coinductive_match: bt_obligation={:?} coinductive={}",
570+
bt_obligation, result);
571+
result
572+
})
573+
}
574+
575+
fn coinductive_obligation<'a,'gcx,'tcx>(selcx: &SelectionContext<'a,'gcx,'tcx>,
576+
obligation: &PredicateObligation<'tcx>)
577+
-> bool {
578+
match obligation.predicate {
579+
ty::Predicate::Trait(ref data) => {
580+
selcx.tcx().trait_has_default_impl(data.def_id())
581+
}
582+
_ => {
583+
false
584+
}
585+
}
586+
}
543587

544588
fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
545589
r_b: ty::Region<'tcx>,
@@ -559,6 +603,55 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
559603

560604
}
561605

606+
impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> {
607+
pub fn new(dep_graph: DepGraph) -> GlobalFulfilledPredicates<'gcx> {
608+
GlobalFulfilledPredicates {
609+
set: FxHashSet(),
610+
dep_graph,
611+
}
612+
}
613+
614+
pub fn check_duplicate(&self, tcx: TyCtxt, key: &ty::Predicate<'tcx>) -> bool {
615+
if let ty::Predicate::Trait(ref data) = *key {
616+
self.check_duplicate_trait(tcx, data)
617+
} else {
618+
false
619+
}
620+
}
621+
622+
pub fn check_duplicate_trait(&self, tcx: TyCtxt, data: &ty::PolyTraitPredicate<'tcx>) -> bool {
623+
// For the global predicate registry, when we find a match, it
624+
// may have been computed by some other task, so we want to
625+
// add a read from the node corresponding to the predicate
626+
// processing to make sure we get the transitive dependencies.
627+
if self.set.contains(data) {
628+
debug_assert!(data.is_global());
629+
self.dep_graph.read(data.dep_node(tcx));
630+
debug!("check_duplicate: global predicate `{:?}` already proved elsewhere", data);
631+
632+
true
633+
} else {
634+
false
635+
}
636+
}
637+
638+
fn add_if_global(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, key: &ty::Predicate<'tcx>) {
639+
if let ty::Predicate::Trait(ref data) = *key {
640+
// We only add things to the global predicate registry
641+
// after the current task has proved them, and hence
642+
// already has the required read edges, so we don't need
643+
// to add any more edges here.
644+
if data.is_global() {
645+
if let Some(data) = tcx.lift_to_global(data) {
646+
if self.set.insert(data.clone()) {
647+
debug!("add_if_global: global predicate `{:?}` added", data);
648+
}
649+
}
650+
}
651+
}
652+
}
653+
}
654+
562655
fn to_fulfillment_error<'tcx>(
563656
error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>)
564657
-> FulfillmentError<'tcx>

‎src/librustc/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use syntax_pos::{Span, DUMMY_SP};
3131
pub use self::coherence::orphan_check;
3232
pub use self::coherence::overlapping_impls;
3333
pub use self::coherence::OrphanCheckErr;
34-
pub use self::fulfill::{FulfillmentContext, RegionObligation};
34+
pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
3535
pub use self::project::MismatchedProjectionTypes;
3636
pub use self::project::{normalize, normalize_projection_type, Normalized};
3737
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal};

‎src/librustc/traits/project.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -462,19 +462,13 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
462462
selcx.infcx().report_overflow_error(&obligation, false);
463463
}
464464
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
465-
// If we find the value in the cache, then return it along
466-
// with the obligations that went along with it. Note
467-
// that, when using a fulfillment context, these
468-
// obligations could in principle be ignored: they have
469-
// already been registered when the cache entry was
470-
// created (and hence the new ones will quickly be
471-
// discarded as duplicated). But when doing trait
472-
// evaluation this is not the case, and dropping the trait
473-
// evaluations can causes ICEs (e.g. #43132).
465+
// If we find the value in the cache, then the obligations
466+
// have already been returned from the previous entry (and
467+
// should therefore have been honored).
474468
debug!("opt_normalize_projection_type: \
475469
found normalized ty `{:?}`",
476470
ty);
477-
return Some(ty);
471+
return Some(NormalizedTy { value: ty, obligations: vec![] });
478472
}
479473
Err(ProjectionCacheEntry::Error) => {
480474
debug!("opt_normalize_projection_type: \
@@ -1342,7 +1336,7 @@ enum ProjectionCacheEntry<'tcx> {
13421336
InProgress,
13431337
Ambiguous,
13441338
Error,
1345-
NormalizedTy(NormalizedTy<'tcx>),
1339+
NormalizedTy(Ty<'tcx>),
13461340
}
13471341

13481342
// NB: intentionally not Clone
@@ -1395,7 +1389,7 @@ impl<'tcx> ProjectionCache<'tcx> {
13951389
let fresh_key = if cacheable {
13961390
debug!("ProjectionCacheEntry::complete: adding cache entry: key={:?}, value={:?}",
13971391
key, value);
1398-
self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.clone()))
1392+
self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.value))
13991393
} else {
14001394
debug!("ProjectionCacheEntry::complete: cannot cache: key={:?}, value={:?}",
14011395
key, value);

‎src/librustc/traits/select.rs

Lines changed: 64 additions & 215 deletions
Large diffs are not rendered by default.

‎src/librustc/traits/trans/mod.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
// seems likely that they should eventually be merged into more
1414
// general routines.
1515

16-
use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig};
16+
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig,
17+
DepConstructor};
18+
use hir::def_id::DefId;
1719
use infer::TransNormalize;
1820
use std::cell::RefCell;
1921
use std::marker::PhantomData;
@@ -39,7 +41,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
3941
// Remove any references to regions; this helps improve caching.
4042
let trait_ref = self.erase_regions(&trait_ref);
4143

42-
self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
44+
self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || {
4345
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
4446
trait_ref, trait_ref.def_id());
4547

@@ -137,7 +139,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
137139
if !ty.has_projection_types() {
138140
ty
139141
} else {
140-
self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
142+
self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || {
141143
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
142144
self.tcx.normalize_associated_type(&ty)
143145
})
@@ -169,8 +171,8 @@ pub struct TraitSelectionCache<'tcx> {
169171
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
170172
type Key = ty::PolyTraitRef<'tcx>;
171173
type Value = Vtable<'tcx, ()>;
172-
fn to_dep_kind() -> DepKind {
173-
DepKind::TraitSelect
174+
fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode {
175+
key.to_poly_trait_predicate().dep_node(tcx)
174176
}
175177
}
176178

@@ -183,8 +185,31 @@ pub struct ProjectionCache<'gcx> {
183185
impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
184186
type Key = Ty<'gcx>;
185187
type Value = Ty<'gcx>;
186-
fn to_dep_kind() -> DepKind {
187-
DepKind::TraitSelect
188+
fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode {
189+
// Ideally, we'd just put `key` into the dep-node, but we
190+
// can't put full types in there. So just collect up all the
191+
// def-ids of structs/enums as well as any traits that we
192+
// project out of. It doesn't matter so much what we do here,
193+
// except that if we are too coarse, we'll create overly
194+
// coarse edges between impls and the trans. For example, if
195+
// we just used the def-id of things we are projecting out of,
196+
// then the key for `<Foo as SomeTrait>::T` and `<Bar as
197+
// SomeTrait>::T` would both share a dep-node
198+
// (`TraitSelect(SomeTrait)`), and hence the impls for both
199+
// `Foo` and `Bar` would be considered inputs. So a change to
200+
// `Bar` would affect things that just normalized `Foo`.
201+
// Anyway, this heuristic is not ideal, but better than
202+
// nothing.
203+
let def_ids: Vec<DefId> =
204+
key.walk()
205+
.filter_map(|t| match t.sty {
206+
ty::TyAdt(adt_def, _) => Some(adt_def.did),
207+
ty::TyProjection(ref proj) => Some(proj.item_def_id),
208+
_ => None,
209+
})
210+
.collect();
211+
212+
DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids })
188213
}
189214
}
190215

‎src/librustc/ty/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,12 @@ pub struct GlobalCtxt<'tcx> {
507507
/// Merge this with `selection_cache`?
508508
pub evaluation_cache: traits::EvaluationCache<'tcx>,
509509

510+
/// A set of predicates that have been fulfilled *somewhere*.
511+
/// This is used to avoid duplicate work. Predicates are only
512+
/// added to this set when they mention only "global" names
513+
/// (i.e., no type or lifetime parameters).
514+
pub fulfilled_predicates: RefCell<traits::GlobalFulfilledPredicates<'tcx>>,
515+
510516
/// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime.
511517
pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>,
512518

@@ -680,6 +686,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
680686
let interners = CtxtInterners::new(arena);
681687
let common_types = CommonTypes::new(&interners);
682688
let dep_graph = hir.dep_graph.clone();
689+
let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
683690
let max_cnum = s.cstore.crates().iter().map(|c| c.as_usize()).max().unwrap_or(0);
684691
let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1);
685692
providers[LOCAL_CRATE] = local_providers;
@@ -728,6 +735,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
728735
named_region_map,
729736
trait_map: resolutions.trait_map,
730737
export_map: resolutions.export_map,
738+
fulfilled_predicates: RefCell::new(fulfilled_predicates),
731739
hir,
732740
def_path_hash_to_def_id,
733741
maps: maps::Maps::new(providers),

‎src/librustc/ty/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub use self::IntVarValue::*;
1515
pub use self::LvaluePreference::*;
1616
pub use self::fold::TypeFoldable;
1717

18+
use dep_graph::{DepNode, DepConstructor};
1819
use hir::{map as hir_map, FreevarMap, TraitMap};
1920
use hir::def::{Def, CtorKind, ExportMap};
2021
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -946,6 +947,28 @@ impl<'tcx> TraitPredicate<'tcx> {
946947
self.trait_ref.def_id
947948
}
948949

950+
/// Creates the dep-node for selecting/evaluating this trait reference.
951+
fn dep_node(&self, tcx: TyCtxt) -> DepNode {
952+
// Extact the trait-def and first def-id from inputs. See the
953+
// docs for `DepNode::TraitSelect` for more information.
954+
let trait_def_id = self.def_id();
955+
let input_def_id =
956+
self.input_types()
957+
.flat_map(|t| t.walk())
958+
.filter_map(|t| match t.sty {
959+
ty::TyAdt(adt_def, ..) => Some(adt_def.did),
960+
ty::TyClosure(def_id, ..) => Some(def_id),
961+
ty::TyFnDef(def_id, ..) => Some(def_id),
962+
_ => None
963+
})
964+
.next()
965+
.unwrap_or(trait_def_id);
966+
DepNode::new(tcx, DepConstructor::TraitSelect {
967+
trait_def_id,
968+
input_def_id,
969+
})
970+
}
971+
949972
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
950973
self.trait_ref.input_types()
951974
}
@@ -960,6 +983,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
960983
// ok to skip binder since trait def-id does not care about regions
961984
self.0.def_id()
962985
}
986+
987+
pub fn dep_node(&self, tcx: TyCtxt) -> DepNode {
988+
// ok to skip binder since depnode does not care about regions
989+
self.0.dep_node(tcx)
990+
}
963991
}
964992

965993
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]

‎src/librustc/util/common.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use std::iter::repeat;
1919
use std::path::Path;
2020
use std::time::{Duration, Instant};
2121

22+
use ty::TyCtxt;
23+
2224
// The name of the associated type for `Fn` return types
2325
pub const FN_OUTPUT_NAME: &'static str = "Output";
2426

@@ -209,7 +211,7 @@ pub trait MemoizationMap {
209211
/// needed in the `op` to ensure that the correct edges are
210212
/// added into the dep graph. See the `DepTrackingMap` impl for
211213
/// more details!
212-
fn memoize<OP>(&self, key: Self::Key, op: OP) -> Self::Value
214+
fn memoize<OP>(&self, tcx: TyCtxt, key: Self::Key, op: OP) -> Self::Value
213215
where OP: FnOnce() -> Self::Value;
214216
}
215217

@@ -219,7 +221,7 @@ impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
219221
type Key = K;
220222
type Value = V;
221223

222-
fn memoize<OP>(&self, key: K, op: OP) -> V
224+
fn memoize<OP>(&self, _tcx: TyCtxt, key: K, op: OP) -> V
223225
where OP: FnOnce() -> V
224226
{
225227
let result = self.borrow().get(&key).cloned();

‎src/test/compile-fail/issue-39970.rs

Lines changed: 0 additions & 31 deletions
This file was deleted.

‎src/test/compile-fail/issue-42796.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.

‎src/test/run-pass/issue-43132.rs

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.