Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRecursion limit during monomorphization hit quicker on beta #38033
Comments
alexcrichton
referenced this issue
Nov 27, 2016
Closed
reached the recursion limit during monomorphization (selection ambiguity) #262
This comment has been minimized.
This comment has been minimized.
|
Inlining for posterity: use std::marker;
use std::mem;
fn main() {
let workers = (0..0).map(|_| result::<u32, ()>());
drop(join_all(workers).poll());
}
trait Future {
type Item;
type Error;
fn poll(&mut self) -> Result<Self::Item, Self::Error>;
}
trait IntoFuture {
type Future: Future<Item=Self::Item, Error=Self::Error>;
type Item;
type Error;
fn into_future(self) -> Self::Future;
}
impl<F: Future> IntoFuture for F {
type Future = F;
type Item = F::Item;
type Error = F::Error;
fn into_future(self) -> F {
self
}
}
struct FutureResult<T, E> {
_inner: marker::PhantomData<(T, E)>,
}
fn result<T, E>() -> FutureResult<T, E> {
loop {}
}
impl<T, E> Future for FutureResult<T, E> {
type Item = T;
type Error = E;
fn poll(&mut self) -> Result<T, E> {
loop {}
}
}
struct JoinAll<I>
where I: IntoIterator,
I::Item: IntoFuture,
{
elems: Vec<<I::Item as IntoFuture>::Item>,
}
fn join_all<I>(_: I) -> JoinAll<I>
where I: IntoIterator,
I::Item: IntoFuture,
{
loop {}
}
impl<I> Future for JoinAll<I>
where I: IntoIterator,
I::Item: IntoFuture,
{
type Item = Vec<<I::Item as IntoFuture>::Item>;
type Error = <I::Item as IntoFuture>::Error;
fn poll(&mut self) -> Result<Self::Item, Self::Error> {
let elems = mem::replace(&mut self.elems, Vec::new());
elems.into_iter().map(|e| {
e
}).collect::<Vec<_>>();
loop {}
}
} |
This comment has been minimized.
This comment has been minimized.
|
Thats... not a recursion limit error
Overflow does not cause ambiguity for quite some time. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 You mean this used to be the case, but now this is just ambiguous and not due to an overflow? |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
|
There's no overflow, only ambiguity and a very outdated error message - overflow last caused ambiguity in the 0.X days. |
This comment has been minimized.
This comment has been minimized.
|
Then this looks like it's caused by an interaction between a bug(?) in specialization and the new (in beta?) specialization of |
This comment has been minimized.
This comment has been minimized.
|
Sure. Trans-time ambiguity is always a bug. |
This comment has been minimized.
This comment has been minimized.
Could we have a |
This comment has been minimized.
This comment has been minimized.
|
Oh I remember why this is so familiar: on one of my branches I broke a similar specialization by not sorting the predicates for constraining purposes. But here we can't just look at the history, this could be a bug that was always present in specialization, whether in this sorting logic or elsewhere. |
This comment has been minimized.
This comment has been minimized.
|
@eddyb No, I have never seen it. |
arielb1
added
the
A-traits
label
Nov 27, 2016
This comment has been minimized.
This comment has been minimized.
|
This is like an annoying problem with the projection cache's handling of nested obligations. Nested projection obligations enter here in this case:
Here the normalization result is the result of the nested impl By itself, this is proper behaviour - the additional obligation is returned, and the RFC 447 rules ensure that it is processed before the output However, the projection cache breaks this - it caches the This appears to work in most cases because during "one-pass evaluation" we tend to process obligations in LIFO order - after an obligation is added to the cache, we process its nested obligations before we do anything else (and if we have a cycle, we handle it specifically). And this specific case can be fixed by this little patch that removes the violation of LIFO order: diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 76bead9..24731e8 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1215,8 +1215,8 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
obligation,
&closure_type.sig,
util::TupleArgumentsFlag::No)
- .with_addl_obligations(obligations)
.with_addl_obligations(vtable.nested)
+ .with_addl_obligations(obligations)
}
fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(However, I am not sure relying on this "strict LIFO order evaluation" is particularly wise. cc @rust-lang/compiler . |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I'd r+ that patch, backport it to beta, and separately decide on the underlying design problem. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I feel like I fixed this bug recently UPDATE: Or perhaps a related one. I can't find the branch I was thinking of just now. |
This comment has been minimized.
This comment has been minimized.
|
Huh. Ah, I dimly recall now. I at one point had a fix that included the obligations in the cache entry, but I wasn't happy about it, and ultimately the problem was fixed by adding a call to |
arielb1
added a commit
to arielb1/rust
that referenced
this issue
Nov 28, 2016
arielb1
referenced this issue
Nov 28, 2016
Merged
evaluate obligations in LIFO order during closure projection #38059
This comment has been minimized.
This comment has been minimized.
|
Opened PR. |
alexcrichton commentedNov 27, 2016
This program compiles successfully on stable but hits the recursion limit on beta/nightly. This seems like a regression where we hit it too quickly? Is it something we can perhaps fix?
The specific error is:
cc @rust-lang/compiler
originally reported as rust-lang-nursery/futures-rs#262