Skip to content

Commit cc044e6

Browse files
committed
Respect self-constraints on recursive extras
1 parent b1fdfc8 commit cc044e6

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

crates/uv-resolver/src/resolver/mod.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,10 +1609,30 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
16091609
}
16101610
};
16111611
if name == Some(&requirement.name) {
1612+
let Requirement {
1613+
name,
1614+
extras,
1615+
groups,
1616+
marker,
1617+
source,
1618+
origin,
1619+
} = requirement;
1620+
1621+
// Add the constraints for that extra, i.e., if `project[foo]` includes `project[bar]>1.0`,
1622+
// as a dependency, we need to propagate `project>1.0`, in addition to transitively
1623+
// expanding `project[bar]`.
1624+
requirements.push(Cow::Owned(Requirement {
1625+
name,
1626+
extras: vec![],
1627+
groups,
1628+
marker,
1629+
source,
1630+
origin,
1631+
}));
1632+
16121633
// Add each transitively included extra.
16131634
queue.extend(
1614-
requirement
1615-
.extras
1635+
extras
16161636
.iter()
16171637
.cloned()
16181638
.map(|extra| (extra, requirement.marker)),
@@ -1625,7 +1645,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
16251645
}
16261646

16271647
// Drop all the self-requirements now that we flattened them out.
1628-
requirements.retain(|req| name != Some(&req.name));
1648+
requirements.retain(|req| name != Some(&req.name) || req.extras.is_empty());
16291649

16301650
requirements
16311651
}

crates/uv/tests/it/lock.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19131,6 +19131,10 @@ fn lock_recursive_extra() -> Result<()> {
1913119131
lock, @r###"
1913219132
version = 1
1913319133
requires-python = ">=3.12"
19134+
resolution-markers = [
19135+
"python_full_version >= '3.13' or sys_platform != 'darwin'",
19136+
"python_full_version < '3.13' and sys_platform == 'darwin'",
19137+
]
1913419138

1913519139
[options]
1913619140
exclude-newer = "2024-03-25T00:00:00Z"
@@ -19585,12 +19589,15 @@ fn lock_self_extra_to_extra_incompatible() -> Result<()> {
1958519589
)?;
1958619590

1958719591
uv_snapshot!(context.filters(), context.lock(), @r###"
19588-
success: true
19589-
exit_code: 0
19592+
success: false
19593+
exit_code: 1
1959019594
----- stdout -----
1959119595

1959219596
----- stderr -----
19593-
Resolved 2 packages in [TIME]
19597+
× No solution found when resolving dependencies:
19598+
╰─▶ Because project[foo] depends on your project and your project requires project[foo], we can conclude that your project's requirements are unsatisfiable.
19599+
19600+
hint: The package `project[foo]` depends on itself. This is likely a mistake. Consider removing the dependency.
1959419601
"###);
1959519602

1959619603
let lock = context.read("uv.lock");

0 commit comments

Comments
 (0)