about summary refs log tree commit diff
path: root/src/test/rustdoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-19 05:05:48 +0000
committerbors <bors@rust-lang.org>2019-01-19 05:05:48 +0000
commitaf73e64423a450d887df32e2998b8831d7ec653e (patch)
tree551bdaadaf845322311ea630e7973fd933a21f1f /src/test/rustdoc
parent53b622a48a7945e223dbc5cfb30f7cbd38acc7c5 (diff)
parent9b68dcd32a1be5d219a6bcedc2c9fc63d6d463a4 (diff)
downloadrust-af73e64423a450d887df32e2998b8831d7ec653e.tar.gz
rust-af73e64423a450d887df32e2998b8831d7ec653e.zip
Auto merge of #56722 - Aaron1011:fix/blanket-eval-overflow, r=nikomatsakis
Fix stack overflow when finding blanket impls

Currently, SelectionContext tries to prevent stack overflow by keeping
track of the current recursion depth. However, this depth tracking is
only used when performing normal section (which includes confirmation).
No such tracking is performed for evaluate_obligation_recursively, which
can allow a stack overflow to occur.

To fix this, this commit tracks the current predicate evaluation depth.
This is done separately from the existing obligation depth tracking:
an obligation overflow can occur across multiple calls to 'select' (e.g.
when fulfilling a trait), while a predicate evaluation overflow can only
happen as a result of a deep recursive call stack.

Fixes #56701

I've re-used `tcx.sess.recursion_limit` when checking for predication evaluation overflows. This is such a weird corner case that I don't believe it's necessary to have a separate setting controlling the maximum depth.
Diffstat (limited to 'src/test/rustdoc')
-rw-r--r--src/test/rustdoc/issue-56701.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/test/rustdoc/issue-56701.rs b/src/test/rustdoc/issue-56701.rs
new file mode 100644
index 00000000000..6fb30a4ff4c
--- /dev/null
+++ b/src/test/rustdoc/issue-56701.rs
@@ -0,0 +1,34 @@
+// This shouldn't cause a stack overflow when rustdoc is run
+
+use std::ops::Deref;
+use std::ops::DerefMut;
+
+pub trait SimpleTrait {
+    type SimpleT;
+}
+
+impl<Inner: SimpleTrait, Outer: Deref<Target = Inner>> SimpleTrait for Outer {
+    type SimpleT = Inner::SimpleT;
+}
+
+pub trait AnotherTrait {
+    type AnotherT;
+}
+
+impl<T, Simple: SimpleTrait<SimpleT = Vec<T>>> AnotherTrait for Simple {
+    type AnotherT = T;
+}
+
+pub struct Unrelated<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>>(UnrelatedT);
+
+impl<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>> Deref for Unrelated<Inner, UnrelatedT> {
+    type Target = Vec<Inner>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+
+pub fn main() { }
+