From 580bc9d079e149d61f92c7f51c368c64372573e3 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 4 Sep 2025 08:34:53 -0400 Subject: [PATCH] Avoid erroring when `match-runtime` target is optional (#15671) ## Summary If the package that has the `match-runtime` dependency itself isn't being installed, we should avoid erroring if the package it _depends on_ isn't in the resolution. Closes https://github.com/astral-sh/uv/issues/15661. --- .../src/build_requires.rs | 2 + crates/uv/tests/it/sync.rs | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/crates/uv-distribution-types/src/build_requires.rs b/crates/uv-distribution-types/src/build_requires.rs index 18d885f8e..6f4194aaa 100644 --- a/crates/uv-distribution-types/src/build_requires.rs +++ b/crates/uv-distribution-types/src/build_requires.rs @@ -83,6 +83,8 @@ impl ExtraBuildRequires { /// Apply runtime constraints from a resolution to the extra build requirements. pub fn match_runtime(self, resolution: &Resolution) -> Result { self.into_iter() + .filter(|(_, requirements)| !requirements.is_empty()) + .filter(|(name, _)| resolution.distributions().any(|dist| dist.name() == name)) .map(|(name, requirements)| { let requirements = requirements .into_iter() diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index a3de53e30..f7113e419 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -13360,6 +13360,44 @@ fn reject_unmatched_runtime() -> Result<()> { Ok(()) } +#[test] +fn match_runtime_optional() -> Result<()> { + let context = TestContext::new("3.12").with_exclude_newer("2025-01-01T00:00Z"); + + let pyproject_toml = context.temp_dir.child("pyproject.toml"); + pyproject_toml.write_str( + r#" + [project] + name = "foo" + version = "0.1.0" + requires-python = ">=3.12" + dependencies = [] + + [project.optional-dependencies] + bar = ["iniconfig", "typing-extensions"] + + [tool.uv.sources] + typing-extensions = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz" } + + [tool.uv.extra-build-dependencies] + typing-extensions = [{ requirement = "iniconfig", match-runtime = true }] + "#, + )?; + + uv_snapshot!(context.filters(), context.sync(), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning. + Resolved 3 packages in [TIME] + Audited in [TIME] + "); + + Ok(()) +} + #[test] fn sync_extra_build_dependencies_cache() -> Result<()> { let context = TestContext::new("3.12");