about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo.net>2017-05-15 12:21:28 +0200
committerMichael Woerister <michaelwoerister@posteo.net>2017-05-15 15:28:28 +0200
commit40a6734ae1a1ec9ad96b8f5b58a64d10d0cdbe76 (patch)
treebed9a964631771761e329d00eb49ade2081b4ce1 /src
parent8da2fe8ed72cc9960f4043867fc55c2b4bc4a3e3 (diff)
downloadrust-40a6734ae1a1ec9ad96b8f5b58a64d10d0cdbe76.tar.gz
rust-40a6734ae1a1ec9ad96b8f5b58a64d10d0cdbe76.zip
Re-introduce cycle-check in assoc. item resolution.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/traits/project.rs40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index d6f6350373a..e119ead7473 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -29,6 +29,7 @@ use infer::type_variable::TypeVariableOrigin;
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use syntax::ast;
 use syntax::symbol::Symbol;
+use syntax_pos::DUMMY_SP;
 use ty::subst::Subst;
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder};
@@ -1317,13 +1318,38 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
     assoc_ty_name: ast::Name)
     -> Option<specialization_graph::NodeItem<ty::AssociatedItem>>
 {
-    let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = selcx.tcx().trait_def(trait_def_id);
-
-    trait_def
-        .ancestors(selcx.tcx(), impl_def_id)
-        .defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type)
-        .next()
+    let tcx = selcx.tcx();
+    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    // This function may be called while we are still building the
+    // specialization graph that is queried below (via TraidDef::ancestors()),
+    // so, in order to avoid infinite recursion, we detect this case by
+    // seeing if a query of the specialization graph fails with a cycle error.
+    // If we are in cycle, and thus still building the graph, we perform a
+    // reduced version of the associated item lookup that does not need the
+    // specialization graph.
+    let specialization_graph_complete =
+        ty::queries::specialization_graph_of::try_get(tcx,
+                                                      DUMMY_SP,
+                                                      trait_def_id).is_ok();
+    if !specialization_graph_complete {
+        let impl_node = specialization_graph::Node::Impl(impl_def_id);
+        for item in impl_node.items(tcx) {
+            if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
+                return Some(specialization_graph::NodeItem {
+                    node: specialization_graph::Node::Impl(impl_def_id),
+                    item: item,
+                });
+            }
+        }
+        None
+    } else {
+        trait_def
+            .ancestors(tcx, impl_def_id)
+            .defs(tcx, assoc_ty_name, ty::AssociatedKind::Type)
+            .next()
+    }
 }
 
 // # Cache