PyO3 / pyproject-toml-rs

pyproject.toml parser in Rust
MIT License
19 stars 8 forks source link

breaking change in v0.8.2: pep440_rs 0.3 → 0.4 despite being in the public API #17

Closed decathorpe closed 7 months ago

decathorpe commented 7 months ago

I updated the Fedora Linux package for pyproject-toml to the latest version today, and our CI started complaining that maturin now fails to build:

  error[E0308]: mismatched types
     --> src/metadata.rs:139:32
      |
  139 |                 self.version = version.clone();
      |                 ------------   ^^^^^^^^^^^^^^^ expected `pep440_rs::Version`, found `pep440_rs::version::Version`
      |                 |
      |                 expected due to the type of this binding
      |
      = note: `pep440_rs::version::Version` and `pep440_rs::Version` have similar names, but are actually distinct types
  note: `pep440_rs::version::Version` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.4.0/src/version.rs:263:1
      |
  263 | pub struct Version {
      | ^^^^^^^^^^^^^^^^^^
  note: `pep440_rs::Version` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.3.12/src/version.rs:268:1
      |
  268 | pub struct Version {
      | ^^^^^^^^^^^^^^^^^^
      = note: perhaps two different versions of crate `pep440_rs` are being used?
  error[E0308]: mismatched types
     --> src/metadata.rs:181:45
      |
  181 |                 self.requires_python = Some(requires_python.clone());
      |                                        ---- ^^^^^^^^^^^^^^^^^^^^^^^ expected `VersionSpecifiers`, found a different `VersionSpecifiers`
      |                                        |
      |                                        arguments to this enum variant are incorrect
      |
      = note: `VersionSpecifiers` and `VersionSpecifiers` have similar names, but are actually distinct types
  note: `VersionSpecifiers` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.4.0/src/version_specifier.rs:58:1
      |
  58  | pub struct VersionSpecifiers(Vec<VersionSpecifier>);
      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  note: `VersionSpecifiers` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.3.12/src/version_specifier.rs:58:1
      |
  58  | pub struct VersionSpecifiers(Vec<VersionSpecifier>);
      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      = note: perhaps two different versions of crate `pep440_rs` are being used?
  help: the type constructed contains `pep440_rs::version_specifier::VersionSpecifiers` due to the type of the argument passed
     --> src/metadata.rs:181:40
      |
  181 |                 self.requires_python = Some(requires_python.clone());
      |                                        ^^^^^-----------------------^
      |                                             |
      |                                             this argument influences the type of `Some`
  note: tuple variant defined here
     --> /builddir/build/BUILD/rustc-1.75.0-src/library/core/src/option.rs:577:5
  error[E0308]: mismatched types
     --> src/pyproject_toml.rs:325:52
      |
  325 |                     if !version_specifier.contains(&self_version) {
      |                                           -------- ^^^^^^^^^^^^^ expected `pep440_rs::version::Version`, found `pep440_rs::Version`
      |                                           |
      |                                           arguments to this method are incorrect
      |
      = note: `pep440_rs::Version` and `pep440_rs::version::Version` have similar names, but are actually distinct types
  note: `pep440_rs::Version` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.3.12/src/version.rs:268:1
      |
  268 | pub struct Version {
      | ^^^^^^^^^^^^^^^^^^
  note: `pep440_rs::version::Version` is defined in crate `pep440_rs`
     --> /usr/share/cargo/registry/pep440_rs-0.4.0/src/version.rs:263:1
      |
  263 | pub struct Version {
      | ^^^^^^^^^^^^^^^^^^
      = note: perhaps two different versions of crate `pep440_rs` are being used?
  note: method defined here
     --> /usr/share/cargo/registry/pep440_rs-0.4.0/src/version_specifier.rs:70:12
      |
  70  |     pub fn contains(&self, version: &Version) -> bool {
      |            ^^^^^^^^

It looks like types from pep440_rs are part of the public API of pyproject-toml, and it was updated from v0.3 to v0.4 between release v0.8.1 and v0.8.2. This is a breaking change (since pep440_rs is part of the public API of pyproject-toml), and should probably have been released as v0.9.0.

wolfv commented 7 months ago

I think this might be fixed with #18 ?

decathorpe commented 7 months ago

I don't think so - maturin itself depends on pyproject-toml 0.8.1, pep440_rs 0.3.6, and pep508_rs 0.2.1: https://github.com/PyO3/maturin/blob/v1.4.0/Cargo.toml#L65-L76

Updating the pep508_rs dependency in pyproject-toml makes pyproject-toml compatible with the latest version of pep440_rs, but that doesn't help for any projects that depend on pyproject-toml ^0.8 and pep440_rs ^0.3 - there are types from pep440_rs that leak into the public API of pyproject-toml, for example:

Which is why bumping the dependency on pep440_rs to a semver-incompatible version is in itself a semver-incompatible change in pyproject-toml (as it was in pep508_rs), even if it might not be obvious.

decathorpe commented 7 months ago

Side note: Bumping the dependency on pep508_rs from 0.2.1 to 0.3.0 in your linked PR would cause a similar problem, since types from pep508_rs also leak into the public API of this crate (see previous comment for an example).