Trying to understand patching dependencies

I have a made a change to iced and while I"m waiting for a review of the maintainer I want to use the changed version in a project I'm working on. To do that in my Cargo.toml I have:

[dependencies]
iced = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }

This works but now I want to also use iced_aw, a separate crate in the iced ecosystem that's developed in its own repo, so I add:

iced_aw = { git = "https://github.com/iced-rs/iced_aw" }

iced_aw itself depends on crates.io published versions iced and iced_widget (a package from the iced workspace) so I need to patch these dependencies so cargo uses my version instead. I therefore add:

[patch.crates-io]
iced_widget = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }
iced = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }

When I run cargo update && cargo tree | grep iced I see that iced_aw is still using iced_widget 0.1.3 and not 0.12.0 from the patch.

My questions now are, is that because 0.12.0 is not compatible with 0.1.3 according to semver? And how can I force cargo to use the version from my patch anyway? I checked and these versions of iced_widget are indeed not compatible so I don't expect thi to compile but I would still like to understand how to patch a dependency in this situation.

Complete code

main.rs:

use iced::{
    widget::{button, checkbox, container},
    Sandbox, Settings,
};
use iced_aw::grid;

struct App;

#[derive(Debug, Clone)]
struct Message;

impl Sandbox for App {
    type Message = Message;

    fn new() -> Self {
        Self
    }

    fn title(&self) -> String {
        "Iced patched dependecy question".into()
    }

    fn update(&mut self, _message: Self::Message) {}

    fn view(&self) -> iced::Element<'_, Self::Message> {
        let grid: iced_aw::Grid<'_, Message, _> =
            grid!(button("Click me"), checkbox("Check me", true));
        container(grid).into()
    }
}

fn main() -> iced::Result {
    App::run(Settings::default())
}

Cargo.toml:

[package]
name = "iced-patched-question"
version = "0.1.0"
edition = "2021"

[dependencies]
iced = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }
iced_aw = { git = "https://github.com/iced-rs/iced_aw" }

[patch.crates-io]
iced_widget = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }
iced = { git = "https://github.com/avsaase/iced", branch = "feat/disabled-widgets" }

That's correct. From the docs:

This means that the version number of the local checkout is significant and will affect whether the patch is used.


AFAIK you can't and you need to add another patch for the 0.1.* version as well.

I'm trying to add a second dependency but it's not clear to me how to do that in this situation. I added

iced_widget2 = { version = "0.1.3", git = "https://github.com/avsaase/iced", package = "iced_widget", branch = "feat/disabled-widgets" }

but that gives the error

The patch location `https://github.com/avsaase/iced?branch=feat/disabled-widgets` contains a `iced_widget` package with version `0.12.0`, but the patch definition requires `^0.1.3`.

Changing the version doesn;t help because it's either not compatible or with 0.12.0 it gives the error

cannot have two `[patch]` entries which both resolve to `iced_widget v0.12.

The package your patch for 0.1.3 points to must still be semver compatible with that version. You have to submit a patch for 0.1.3 that has the a version >=0.1.3, <0.2.0. You can't patch it with your 0.12.0 patch, you need to create a second one (i.e. you could try to add another branch where you have your 0.12.0 code but with a different version in Cargo.toml, though it may cause other hazards when patching a way older version of iced_widget with a patch based on a newer version; in that case I guess you have to go back to version 0.1.3 and re-create the changes you've made to 0.12.0).

2 Likes

Ah I get it now. I'll give that a try.

0.12.0 is the next version after 0.1.3 so the change is not as big as it seems. The project is synchonizing the version numbers of all the different crates in the workspace, hence the large version jump.

1 Like

This works. As in, it uses the patched iced_widget dependency in iced_aw. iced_widget still depends on the v0.12.0 versions of several other iced crates so that obviously doesn't compile. With more patching I could probably get it to compile but I'm going to leave at this. Thanks for the suggestions!

You should also consider patching iced_aw so that it depends on 0.12.0 of iced_widget.