Open SimonSapin opened 7 years ago
I've also hit this bug (is it fair to say it is a bug?)
I was able to condense my error condition down to
// the writing is on the wall, let's not look at the entire wall
#![recursion_limit="10"]
struct Encoder {}
trait CanEncode { fn write(self); }
impl Encoder {
fn write<E: CanEncode>(&mut self, x: E) { x.write() }
}
impl<'a, T> CanEncode for &'a [T] where
&'a T: CanEncode
{
fn write(self) {}
}
fn main() {
let mut wtr = Encoder {};
wtr.write::<&[_]>(42).unwrap();
}
this gives the curious and (to me) nonsensical error message:
rustc 1.17.0 (56124baa9 2017-04-24)
error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
--> <anon>:20:9
|
20 | wtr.write::<&[_]>(42).unwrap();
| ^^^^^
|
= help: consider adding a `#![recursion_limit="20"]` attribute to your crate
= note: required because of the requirements on the impl of `CanEncode` for `&[_]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[_]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[_]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[_]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[_]]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[_]]]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[[_]]]]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[[[_]]]]]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[[[[_]]]]]]]]]`
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[[[[[_]]]]]]]]]]`
error: aborting due to previous error
Compilation failed.
It's not very clear what's going on here. I have absolutely no idea why the compiler is checking &[[[_]]] and so forth, and I have absolutely no idea why it's checking Sized for these, and why it can't figure out it's never going to work.
All in all, it's really confusing, and it smells a lot like a bug, to me.
Is there any way to fix this, and if not, will it be fixed when chalk lands?
The plot thickens...
use std::io::{Read, Write};
use std::fs::File;
use std::path::Path;
// Comment this out... and everything will work fine
use thisdoesntexistyolo::haha;
struct Something<T: Read + Write> {
thing: T,
}
impl<'a, T: 'a + Read + Write> Something<T>
where &'a T: Read
{
fn new(thing: T) -> Something<T> {
Something { thing }
}
}
fn main() {
let file = File::open(Path::new("doesntmatter.txt")).unwrap();
let mut st: Something<File> = Something::new(file);
}
error[E0275]: overflow evaluating the requirement `_: std::io::Read`
--> src/main.rs:22:35
|
22 | let mut st: Something<File> = Something::new(file);
| ^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `std::io::Read` for `&tar::archive::ArchiveInner<_>`
= note: required because of the requirements on the impl of `std::io::Read` for `&tokio_reactor::poll_evented::PollEvented<tar::archive::ArchiveInner<_>>`
= note: required because of the requirements on the impl of `std::io::Read` for `&tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tar::archive::ArchiveInner<_>>>`
= note: required because of the requirements on the impl of `std::io::Read` for `&tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tar::archive::ArchiveInner<_>>>>`
= note: required because of the requirements on the impl of `std::io::Read` for `&tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tokio_reactor::poll_evented::PollEvented<tar::archive::ArchiveInner<_>>>>>`
Minimized test case from https://github.com/rust-lang/rust/issues/39959#issuecomment-301342230 (also changed to Vec<T>
because it's Sized
but the error overflows evaluating _: Sized
requirement here too):
trait Trait {}
impl<'a, T> Trait for &'a Vec<T> where &'a T: Trait {}
fn call<E: Trait>() {}
fn foo() {
call::<&Vec<_>>();
}
Reproducible on every stable Rust back to 1.0, beta and nightly.
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7ffb08380a25020785bf958a3e600687.
Same error with a struct instead of Vec
. I couldn't repro with any other trait than Sized
, external or not.
struct Struct<T> where T: Sized {
t: T
}
trait Trait {}
impl<'a, T> Trait for &'a Struct<T> where &'a T: Trait {}
fn call<E: Trait>() {}
fn foo() {
call::<&Struct<_>>();
}
I think I've found an even nastier reproduction of this. Not only do I get the same (long) error output, but mine didn't even reference a file, or a line… Just the error message, number, and the recursion. That is,
error[E0275]: overflow evaluating the requirement `std::io::Cursor<&mut Vec<u8>>: std::io::Write`
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`foobar`)
= note: required because of the requirements on the impl of `std::io::Write` for `&mut std::io::Cursor<&mut Vec<u8>>`
= note: required because of the requirements on the impl of `std::io::Write` for `&mut &mut std::io::Cursor<&mut Vec<u8>>`
(and so on)
error: aborting due to previous error
In my example, there is an error in the code: Tag::write
calls XmlItem::write
with a &mut W
, which becomes W
in XmlItem
. XmlItem
then recurses back to Tag
with a &mut W
, or really, a &mut &mut W
from the original W
. And so on, ad infinitum; the template can't be instantiated b/c it would require infinite instantiation. The diagnostic isn't helpful, however.
Stable, 1.48.0, and nightly 2020-12-03, though nightly is kind enough to elide some of the redundant impls. (But still fails to identify a line/file.)
Triage: almost no change. The requirements list now hides the intermediary steps if they repeat, so at least now the output is less verbose.
The last case still doesn't have a span.
I'm writing a numerical crate and am encountering this bug a lot. So far, I've been able to get around it by cloning my values which reduces the complexity of my trait constraints but I can never tell what triggers the bug.
Here's a minimal example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88f2fbd8464ede697605101f29dbcda0 Code is also here: https://gist.github.com/88f2fbd8464ede697605101f29dbcda0
Another instance of this showed up on URLO with a playground link that produces the error.
I was able to find a workaround for this case by adding a bound type variable. I have reproduced the differing sections below.
Compile Error:
impl<X, Xs> Foo for (Cons<X, Xs>, ())
where
(Xs, ()): Foo,
<(Xs, ()) as Foo>::X: Any,
{
type X = Tuple;
}
Compiles Successfully:
impl<X, Xs, X2> Foo for (Cons<X, Xs>, ())
where
(Xs, ()): Foo<X=X2>,
X2: Any,
{
type X = Tuple;
}
Here's another tiny test-case by @Lemmih that we ran into when using the ordered_float crate: https://github.com/reem/rust-ordered-float/issues/91#issuecomment-865504545
Triage:
Current output for original report:
error[E0275]: overflow evaluating the requirement `Ser<'_, Option<_>>: Serialize`
--> src/main.rs:18:5
|
18 | Ser::new(value);
| ^^^^^^^^
|
= help: consider adding a `#![recursion_limit="10"]` attribute to your crate (`playground`)
note: required because of the requirements on the impl of `Serialize` for `Ser<'_, Option<Option<_>>>`
--> src/main.rs:15:13
|
15 | impl<'a, T> Serialize for Ser<'a, Option<T>> where Ser<'a, T>: Serialize {}
| ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
= note: 4 redundant requirements hidden
= note: required because of the requirements on the impl of `Serialize` for `Ser<Option<Option<Option<Option<Option<Option<_>>>>>>>`
For the third report:
error[E0432]: unresolved import `thisdoesntexistyolo`
--> src/main.rs:8:5
|
8 | use thisdoesntexistyolo::haha;
| ^^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `thisdoesntexistyolo`
error[E0275]: overflow evaluating the requirement `_: Sized`
--> src/lib.rs:7:5
|
4 | fn call<E: Trait>() {}
| ----- required by this bound in `call`
...
7 | call::<&Vec<_>>();
| ^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
note: required because of the requirements on the impl of `Trait` for `&Vec<_>`
--> src/lib.rs:2:13
|
2 | impl<'a, T> Trait for &'a Vec<T> where &'a T: Trait {}
| ^^^^^ ^^^^^^^^^^
= note: 128 redundant requirements hidden
= note: required because of the requirements on the impl of `Trait` for `&Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<Vec<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
For the second report:
error[E0275]: overflow evaluating the requirement `_: Sized`
--> src/main.rs:20:9
|
20 | wtr.write::<&[_]>(42).unwrap();
| ^^^^^
|
= help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`playground`)
note: required because of the requirements on the impl of `CanEncode` for `&[_]`
--> src/main.rs:12:13
|
12 | impl<'a, T> CanEncode for &'a [T] where
| ^^^^^^^^^ ^^^^^^^
= note: 10 redundant requirements hidden
= note: required because of the requirements on the impl of `CanEncode` for `&[[[[[[[[[[[_]]]]]]]]]]]`
Fifth report:
error[E0275]: overflow evaluating the requirement `_: Sized`
--> src/lib.rs:11:5
|
8 | fn call<E: Trait>() {}
| ----- required by this bound in `call`
...
11 | call::<&Struct<_>>();
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
note: required because of the requirements on the impl of `Trait` for `&Struct<_>`
--> src/lib.rs:6:13
|
6 | impl<'a, T> Trait for &'a Struct<T> where &'a T: Trait {}
| ^^^^^ ^^^^^^^^^^^^^
= note: 128 redundant requirements hidden
= note: required because of the requirements on the impl of `Trait` for `&Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<Struct<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
The case that loses spans now looks like this, still without a span:
error[E0275]: overflow evaluating the requirement `&mut Vec<u8>: std::io::Write`
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
= note: required because of the requirements on the impl of `std::io::Write` for `&mut &mut Vec<u8>`
= note: 128 redundant requirements hidden
= note: required because of the requirements on the impl of `std::io::Write` for `&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Vec<u8>`
The other example linked:
error[E0275]: overflow evaluating the requirement `&BTreeSet<_>: Sub<&BTreeSet<_>>`
--> src/main.rs:28:30
|
17 | fn test<T, const N: usize>(p: &Vector<T, N>) -> Vector<T, N>
| ---- required by a bound in this
18 | where
19 | for<'a> &'a T: Sub<&'a T, Output = T>,
| ---------------------- required by this bound in `test`
...
28 | println!("Output: {:?}", test(&a)); // This fails
| ^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
note: required because of the requirements on the impl of `Sub<&Vector<BTreeSet<_>, {_: usize}>>` for `&Vector<BTreeSet<_>, {_: usize}>`
--> src/main.rs:6:33
|
6 | impl<'a, 'b, T, const N: usize> Sub<&'a Vector<T, N>> for &'b Vector<T, N>
| ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
= note: 127 redundant requirements hidden
= note: required because of the requirements on the impl of `for<'a> Sub` for `&'a Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<Vector<BTreeSet<_>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>, {_: usize}>`
And the output for the last two comments, which are using recent compilers so their output hasn't changed:
error[E0275]: overflow evaluating the requirement `(Cons<_, _>, ()): Foo`
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
= note: required because of the requirements on the impl of `Foo` for `(Cons<_, Cons<_, _>>, ())`
= note: 127 redundant requirements hidden
= note: required because of the requirements on the impl of `Foo` for `(Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, Cons<_, _>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, ())`
error[E0275]: overflow evaluating the requirement `&HashSet<_, _>: Sub`
--> src/lib.rs:11:22
|
3 | fn test<T>(p: T) -> T
| ---- required by a bound in this
4 | where
5 | for<'a> &'a T: std::ops::Sub<&'a T, Output = T>,
| -------------------------------- required by this bound in `test`
...
11 | println!("{:?}", test(0.0_f64));
| ^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`error_case`)
= note: required because of the requirements on the impl of `Sub` for `&OrderedFloat<HashSet<_, _>>`
= note: 127 redundant requirements hidden
= note: required because of the requirements on the impl of `for<'a> Sub` for `&'a OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<OrderedFloat<HashSet<_, _>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
There are multiple bugs here and the most minimal example does not show the worst bug.
struct Struct<T>(T);
trait Trait {}
impl<T> Trait for Struct<T> where T: Trait {}
impl Trait for u8 {}
fn call<E: Trait>() {}
fn foo() {
call::<Struct<_>>();
}
The above code must fail with "type annotations needed" because both Struct<Struct<u8>>
and Struct<u8>
are valid solutions. With references it should fail with that message as well but instead it recurses.
But the actually bad bug, which I'm fairly sure exists is that code that should compile does not. @e2-71828 posted an example of that but that one compiles in the current playground. I'm pretty sure that I've encountered it recently but unfortunately I didn't save the problematic version of the code anywhere.
If you find this issue while debugging that, please post the code.
@e2-71828 posted an example of that but that one compiles in the current playground.
I was interested where that issue got fixed (I originally authored that example) so I spent some time bisecting the fix today.
bors 4a99c5f5 is the first commit that builds my example successfully, which is an auto-merge of https://github.com/rust-lang/rust/pull/97345 That PR looks (to me at least) like it's simply targeting performance improvement and seems to have unintentionally fixed the bug... I'm hoping the implementation details of that PR might help suggest where the root cause of these type inference loops lie.
The nature of the speedup from that PR is seemingly some kind of early pruning inside the trait solver. It’s possible that the logic used there consistently prunes away the problematic branches before they get a chance to infinitely recurse.
Hello, I have another repro to add to the pile. https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=3d0813888dd49475147c9cfbed636797 Looks like it's okay if the trait recurses immediately (taking an i32
/ Vec<T>
), but adding one layer of indirection to the types (taking an &i32
/ &Vec<T>
) makes it evaluate the recursion forever.
I have figured out the root cause!
evaluate_stack has code that is supposed to prevent exactly this case.
But there is a bug in rustc_middle::ty::_match::Match
. It is supposed to check if two types can be unified. For example FreshTy(9) as std::marker::Sized
and Union<FreshTy(1), FreshTy(2)> as Trait
can be unified but Match
thinks this is not the case because the relevant Relate
implementation thinks the trait bounds have to match.
I am not yet sure what the fix is because while this is incorrect for Match
I haven't looked at other things that use Relate
.
The original case now ICEs :(
Doesn't look like it ICEs with the latest nightly (2023-07-13)
error[E0275]: overflow evaluating the requirement `Ser<'_, Option<_>>: Serialize`
--> src/main.rs:18:10
|
18 | Ser::new(value);
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "10"]` attribute to your crate (`playground`)
note: required for `Ser<'_, Option<Option<_>>>` to implement `Serialize`
--> src/main.rs:15:13
|
15 | impl<'a, T> Serialize for Ser<'a, Option<T>> where Ser<'a, T>: Serialize {}
| ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ --------- unsatisfied trait bound introduced here
= note: 3 redundant requirements hidden
= note: required for `Ser<'_, Option<Option<Option<Option<Option<_>>>>>>` to implement `Serialize`
note: required by a bound in `Ser<'a, T>`
--> src/main.rs:9:42
|
9 | impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
| ^^^^^^^^^ required by this bound in `Ser<'a, T>`
I don't see an ICE either any longer
@rustbot label -I-ICE
The test case in the description doesn't seem to overflow with -Znext-solver=globally
(but still overflows without)
[13:57] Joe-Mac.local:rust (master %) | rustc +nightly -Znext-solver=globally test.rs (base)
warning: trait `Serialize` is never used
--> test.rs:5:7
|
5 | trait Serialize {}
| ^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: struct `Ser` is never constructed
--> test.rs:7:8
|
7 | struct Ser<'a, T: 'a>(&'a T);
| ^^^
warning: associated function `new` is never used
--> test.rs:10:12
|
9 | impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
| -------------------------------------------------- associated function in this implementation
10 | pub fn new(value: &'a T) -> Self {
| ^^^
warning: function `serialize` is never used
--> test.rs:17:4
|
17 | fn serialize<'a, T>(value: &'a T) where Ser<'a, T>: Serialize {
| ^^^^^^^^^
warning: 4 warnings emitted
I have created an interesting problem the compiler cannot resolve a type. I do not know if this is a compiler issue or if I am simply doing something wrong, but the diagnostic information I am given does not really help me understand what the issue. Before I updated my toolchain, it gave me no errors, and in my production code I can actually get the compiler to go into an infinite loop that never completes, but I'm not able to reproduce that.
The below code will work if I simply remove the trait hints on the trait type Ty
. With any combination of trait hints, it breaks. All I'd like to do is require certain traits for the trait type.
error[E0275]: overflow evaluating the requirement `<St as Tr>::Ty == _`
trait Tr {
type Ty where Self::Ty: Clone;
}
#[derive(Debug)]
struct St {
fi: <Self as Tr>::Ty
}
impl Tr for St {
type Ty = i64;
}
pub fn main() {
let inst = St { fi: 42 };
println!("{:?}, {}", inst, inst.fi + 12);
}
Reduced test case:
Output in rustc 1.17.0-nightly (536a900c4 2017-02-17):
Without
#![recursion_limit = "5"]
, the error message is similar but much larger. If this isn’t a bug, at least the diagnostic should be improved.