Compilation error when trying to use palette
NeverGivinUp opened this issue ยท 52 comments
When adding any use statement from my local palette crate to my library -- I have not tried using the official version -- I get the following error:
error[E0275]: overflow evaluating the requirement `f64: std::ops::Div<palette::blend::PreAlpha<_>>`
--> src\text.rs:35:50
|
35 | let centering_height_shift = self.height / 2.0;
| ^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`web_utils`)
= note: required because of the requirements on the impl of `std::ops::Div<palette::blend::PreAlpha<palette::blend::PreAlpha<_>>>` for `f64`
= note: 127 redundant requirements hidden
= note: required because of the requirements on the impl of `std::ops::Div<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<palette::blend::PreAlpha<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` for `f64`
The error goes away, when I comment out the line
impl_scalar_binop!(Div::div, DivAssign::div_assign, [f32, f64]);
I believe is unrelated to my local changes and it certainly is unrelated to the code, where the error occurs. It may be related to a bug in the rust compiler.
I had similar errors that came and went away but I don't remember how I fixed it last time.
Which compiler version are you using? Does it change if you switch to another version?
I updated to the current nightly during our conversation on the weekend. My code unfortunately requires associated type bounds
and does not compile with the stable compiler. How do I use an older nightly compiler?
I see, then it's trickier to test with something stable unless it can be minimized into an example without them.
I'm not sure off the top of my head but you may be able to pick the nightly version with rustup.
Using an old nightly (in this case the one from 2022-01-01) didn't help. Neither did replacing the division by 2 by a multiplication by 0.5. This was the only line, the compiler didn't like, though. And extreme disambiguation did help
let centering_height_shift = <f64 as Div>::div(self.height, 2.0);
What if you write self.height / 2.0f64
? Does it still complain?
I'm reopening this because there may be something that can mitigate the issue.
What if you write
self.height / 2.0f64
? Does it still complain?
Yes.
Also if I create a separate variable with explicit type
let h: f64 = self.height;
h/2.0_f64
Still does not work
I'm reopening this because there may be something that can mitigate the issue.
There is an answer in the StackOverflow post, which I originally linked, which seems to contain 2 workarounds. But I didn't read them properly.
Ah, so something about how it transforms the division into a function call is getting stuck. It would be nice to have a small test case to keep here and also find out which implementation is the problematic one.
Would you mind sharing the full code or try to reduce it into a minimal test case?
I'll have a look at those workarounds later and see if they could help too. Thanks for pointing them out!
https://github.com/NeverGivinUp/palette_compilation_rest.git
(was meant to be a compilation test, not a rest)
Perfect, thanks! ๐
This just started hitting my code today. Any multiplication with two f64's trips up one by one. I can't go change all these lines to the ::mul(self, rhs) format, since that would be silly. What would you recommend to do?
Ouch, sorry about that. You can try to use variables with explicit types to help the compiler, but it's also not ideal. ๐ You could also see if it depends on the compiler version. I didn't get around to figuring out exactly what triggers it before releasing, so I'm sorry for not having better answers right now, but thanks for highlighting that it's still an issue.
For me, it happens in a projects after running a routinely cargo update
which made the following results to my Cargo.lock:
Updating crates.io index
Adding fast-srgb8 v1.0.0
Removing find-crate v0.6.3
Updating getrandom v0.2.8 -> v0.2.9
Updating palette v0.6.1 -> v0.7.0
Updating palette_derive v0.6.1 -> v0.7.0
Updating ratio-color v0.2.0 -> v0.3.0
Updating serde v1.0.159 -> v1.0.160
Updating serde_derive v1.0.159 -> v1.0.160
Updating simba v0.8.0 -> v0.8.1
Updating syn v2.0.13 -> v2.0.14
Removing toml v0.5.11
Updating uuid v1.3.0 -> v1.3.1
Where ratio-color
is my quickly made palette library depending on palette
.
The error is exactly the one given regarding the recursion limit suggestion and PreAlpha.
The first offending line in my code is a const multiplication of:
pub const DOUBLE_PI: f64 = 2.0_f64 * std::f64::consts::PI;
But as soon as I patch that, all f64 multiplications inside function bodies get marked, probably because of the order in which things are compiled.
It's rather uncommon for a library to touch the functionalities of others (or std in that matter), which makes it a rather strange error that should have been prohibited by the orphan rule usually?
Indeed, there's no obvious reason why it would be bothered by PreAlpha
, unless it tries to somehow evaluate it as a possible candidate in the multiplication. That's what makes your case especially strange.
Do you think it would be possible to make a minimal example of when it fails? It could be cross referenced with the one above to see if there's any pattern.
Also, which compiler version are you using?
I am able to reproduce this the following way:
[package]
name = "bug_palette"
version = "0.1.0"
edition = "2021"
[dependencies]
scad = "1.2.2"
palette = "0.7.0"
// main.rs
use palette::Oklch;
use scad::OffsetType;
fn main() {
println!("{}", 42.0 * 1.0); // bug also happens when specifying f32 or f64
}
error[E0275]: overflow evaluating the requirement `f32: Mul<PreAlpha<_>>`
--> src/main.rs:5:25
|
5 | println!("{}", 42.0 * 1.0);
| ^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`repro`)
= note: required for `f32` to implement `Mul<PreAlpha<PreAlpha<_>>>`
= note: 127 redundant requirements hidden
= note: required for `f32` to implement `Mul<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<PreAlpha<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
I'm on latest stable:
stable-x86_64-unknown-linux-gnu (default)
rustc 1.68.2 (9eb3afe9e 2023-03-27)
Great, thanks! From this it pretty much looks like it's getting stuck while considering PreAlpha
as a possible right-hand-side type. I'm not sure how to stop it, other than deleting the implementation of Mul<PreAlpha<T>> for f32
and so on, but that's the difference I can see from for example Alpha
, which hasn't been showing this behavior. I see that there's a lot of bug reports for rustc
with similar cases (but not exactly the same in the ones I have checked), so that may be the way to go in the end.
I will give it a proper try this weekend (or tomorrow if I have time)
By the way @Azorlogh, does it still fail when removing the scad
dependency? It shouldn't be related but I'm curious to see how spooky this issue is.
The issue is quite spooky indeed. Removing any of the use
statements makes my example compile fine.
scad::OffsetType
itself is just a pretty trivial enum.
Definitely spooky but the spookiness also makes it harder to set up a reliable test case for regression. ๐ค
I found this, that seem to be pretty much the same case: rust-lang/rust#80542
I created PR #312 to try to work around this. It works for the example from @Azorlogh, but let me know if it still fails in any other cases. You should be able to change your palette
dependency to this to give it a try before it's merged:
[dependencies]
palette = { git = "https://github.com/Ogeon/palette.git", branch = "work_around_issue_283" }
The fix has been released in 0.7.1. Feel free to reopen this issue if it appears again.
This seems to be an issue once again, but now for IntoIterator
. My code does not depend on palette
directly but yields the following error with no source location:
error[E0275]: overflow evaluating the requirement `&_: IntoIterator`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`...`)
= note: required for `&palette::lch::Lch<_, _>` to implement `IntoIterator`
= note: 126 redundant requirements hidden
= note: required for `&Lch<_, Lch<_, Lch<_, Lch<_, Lch<_, Lch<_, Lch<_, ...>>>>>>>` to implement `IntoIterator`
The specific type varies between compilations, seemingly by random, but so far I've seen OkLabHue
, LuvHue
, Lch
, Rgb
, and Luma
.
I've tried both cargo clean
and building with -Znext-solver
but neither works. I've also cloned the repo of the direct dependent on palette
which does not yield the error on cargo check
or cargo test
. I'm at a complete loss as to what is causing the error so any and all help is greatly appreciated.
I'm running the latest stable:
$ rustc -vV
rustc 1.76.0 (07dca489a 2024-02-04)
binary: rustc
commit-hash: 07dca489ac2d933c78d3c5158e3f43beefeb02ce
commit-date: 2024-02-04
host: aarch64-apple-darwin
release: 1.76.0
LLVM version: 17.0.6
Oh, no. ๐ฌ Do you think you could provide a minimal example that reproduces it? I have some idea of where it may be from, but it helps to have an example for testing.
A minimal example might be quite difficult as the application I'm working on is a decently large GUI using iced
(which is the direct dependent of palette
)
If you still would like to have a look I could push the current state of my repo to a new branch and send you a link in a couple of hours.
That would also be helpful, thanks. Do you know if the problem started after any particular change?
The problem started when updating to the latest version of iced, I fear that it may be some other bug that causes this and makes the compile go a little haywire.
I committed my working changes here https://github.com/Smalands-Nation/register-rs/tree/iced_migration_palette_bug
Thank you. If it's anything like the original issue, it's basically a latent problem that just didn't get triggered until now. A trait requirement that happens to send the trait resolver into a loop when the stars happen to align. I'm asking all these questions because it's so difficult to reproduce it without those triggering circumstances.
It's ultimately a compiler bug, and I hoped the next resolver would be able to handle it (it does handle some cases of it), but I'll have to find some workaround that isn't too breaking for now.
I feared as much...
I've only taken a very quick glance but couldn't this be solved for some to the types by introducing a trait bound on the inner iterator that is not met by the colors themselves.
A hasty example for Rgb could look something like
impl<'a, S, C> IntoIterator for Rgb<S, C>
where
C: IntoIterator + num_traits::Num,
{
...
}
Of course this assumes the inner iterator is never another colortype which I do not know is always the case as I've only skimmed through palette
.
That's also my prime suspect. The feature that introduced the iterator is the ability to convert an array of colors into a struct of arrays, so Vec<Rgb<S, T>>
could become Rgb<S, Vec<T>>
. I think something like what you are suggesting could work, but the constraint should probably be something that makes sure it's array-like. Alternatively, since that's surprisingly hard, have specific implementations for Vec
, &[T]
, &mut [T]
, [T; N]
, etc. and avoid the risk of recursion entirely.
Could we not then impose bounds on Item
as Rgb<S, Vec<Vec<T>>
and similar seem unlikely if not impossible
Another hasty example
impl<'a, S, C> IntoIterator for Rgb<S, C>
where
C: IntoIterator,
<C as IntoIterator>::Item: num_traits::Num,
{
...
}
The library isn't relying on num_traits
in its current form, but that would have been something to try otherwise, assuming that's enough to convince the resolver. Specific types may be more robust in general, though, since it doesn't even imply that something like Rgb<_, Rgb<_, f32>>
would be a possibility. I have been a bit busy today, so sorry for not jumping onto this immediately, but I will have a closer look tomorrow and see what works.
I tried restricting the item type, but it didn't help. I will make implementations for specific collection types instead.
I'm also running into this while attempting to upgrade iced
. Here's a minimal example:
use {
std::convert::Infallible,
iced::{
Application,
Command,
Element,
Settings,
widget::Column,
},
};
struct State;
impl Application for State {
type Executor = iced::executor::Default;
type Message = Infallible;
type Theme = iced::Theme;
type Flags = ();
fn new((): Self::Flags) -> (Self, Command<Infallible>) { (Self, Command::none()) }
fn title(&self) -> String { String::default() }
fn update(&mut self, _: Infallible) -> Command<Infallible> { Command::none() }
fn view(&self) -> Element<'_, Infallible> {
Column::with_children(Vec::default().into_iter().map(|()| Column::new()).collect()).into()
}
}
fn main() -> iced::Result {
State::run(Settings::default())
}
Oh, thanks for the minimal example! I'll see if I can make it into a test later.
I have pushed a preliminary work-around as #380. The solution for Alpha
isn't great, so I may change it before publishing for real. You can try it out by adding this to your Cargo.toml
.
[patch.crates-io]
palette = { git = "https://github.com/Ogeon/palette", branch = "issue_283_into_iterator" }
With this patch applied, the compiler seems to get stuck (2 minutes of CPU time and counting on the example above, 19 minutes and counting on the original project).
That's probably what I thought was slow linking, but I had to cancel it and go. ๐ฌ It could be the Alpha
wrapper.
I upgraded my app to iced 0.12 and i have the same issue with Luv
overflow evaluating the requirement &_: IntoIterator
required for &palette::luv::Luv<_, _>
to implement `IntoIterator
I added a commit with less generic implementations for Alpha
, which I got to build after fixing a couple of mistakes in the code @Strosel submitted. Nothing big, just ambiguous output types for collect
and attempts to call into
in const
. Probably masked by this bug.
You should get the new commit with cargo update
, as I understand it, if you have the patch from above.
Looks good!
That's great! If nothing more pops up, I'll finish it next time I have time (this week is a bit cramped ๐ฌ) and publish it.
Version 0.7.5 has been released with the fix. I will remove the temporary branch and you can remove the Cargo.toml patch. Thanks for reporting the error and testing the fix!
I'm still getting a really similar error to the ones mentioned above
for me it's just with Id<Id<Id<...>>>>>
@Ogeon Thanks for the fix. That made it apparent what the issue was. On 0.7.3, I got the recursion error as above, and on 0.7.5 I got an error like this:
error[E0283]: type annotations needed
--> proj/src/lib.rs:123:68
|
123 | Column::with_children(Vec::default().into_iter().map(|()| Column::new()).collect()).into()
| --------------------- ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
| |
| required by a bound introduced by this call
|
= note: cannot satisfy `_: IntoIterator`
note: required by a bound in `iced::widget::Column::<'a, Message, Theme, Renderer>::with_children`
If I change the code to use .collect::<Vec<_>>()
, everything works fine, even on 0.7.3
Hi, that looks like a regular ambiguity that can happen with collect
. Did you perhaps also update iced
at the same time?
I'm assuming this is the function you are calling, which takes a generic type that can be iterated (impl Trait
in argument position is the same as T where T: Trait
), which doesn't give collect
enough information to infer its return type. However, it does look like you can solve this one by not calling collect
, since any iterator also implements IntoIterator
.
@Ogeon I'm able to reproduce this recursion limit error when specifying palette = "=0.7.3"
in my Cargo.toml
file, and don't get the recursion limit error when specifying palette = "=0.7.5"
(which lets me see the real error in my case). I don't see anything else as having changed, here's a diff of Cargo.lock
:
2148c1148
< version = "0.7.3"
---
> version = "0.7.5"
2150c2150
< checksum = "b2e2f34147767aa758aa649415b50b69eeb46a67f9dc7db8011eeb3d84b351dc"
---
> checksum = "ebfc23a4b76642983d57e4ad00fb4504eb30a8ce3c70f4aee1f725610e36d97a"
I can reliably toggle the recursion limit error by switching back and forth between those two versions, and AFAICT no other crates are changing versions.
That is the function I'm calling, yeah. Leaving off .collect()
works as well, as you describe. I think the real issue is just that 0.7.3 causes a spurious error message that masks the real issue in some scenarios, and in my case it was because I was using .collect()
instead of either leaving it off as you suggest, or specifying .collect::<Vec<_>>()
. Upgrading to 0.7.5 should work, but if anybody is stuck on 0.7.3 and gets a recursion limit error, it seems that they'll want to check their code for bare .collect()
s that might be triggering the issue.
True, it was most likely masking the error. It's possible that it interacted badly with impl IntoIterator
, since that was the trait that caused the recursion. Trying to figure out what collect
should return may have gotten it stuck there.