Skip to content

Can't generate feature gated code from a proc macro in a reliable way when used by both normal/build dependencies with resolver="2" #14415

Open
@weiznich

Description

@weiznich

Problem

Consider the following example:

  • There is a crate "a" and "a_derives". These are separate as proc macros are required to live in a separate crate.
  • Crate "a" uses "a_derives" internally and offers a set of additive features (lets call them "x", "y", "z").
  • Crate "a_derives" has the same feature set and crate "a" forwards the features to "a_derives".
  • Crate "a_derives" generates code based on this features assuming that crate "a" contains the relevant helper code
  • Now a user of crate "a" adds it as dependency and as build-dependency to their own crate "c". The for the normal dependency they enable feature "x" and for the build dependency feature "y".

Assuming that host and target match:

  • Cargo with resolver="2" now builds crate "a_derive" once with the features "x" and "y". It will build crate "a" twice once with the features "a" and once with "b", which will both fail as both variants of crate "a" do not contain all the relevant code
  • Cargo with resolver="1" will build "a_derive" and "a" once with both features "x" and "y" enabled.

Given this situation: How do I resolve that while supporting both resolver versions. If the answer is: You cannot, then resolver = "2" is a breaking change and should have been marked as such (== shipping rust 2.0). I fully understand that it is far to late to roll back that change but I would like to see the cargo team to at least acknowledge that they broke something and that they should prioritizing working on a fix (and maybe more than working on implementing new features!).

Steps

For a real word example try to build the following crate:

[package]
name = "test_resolver"
version = "0.1.0"
edition = "2021"

[dependencies]
diesel = { version = "=2.2.2", features = ["postgres"] }

[build-dependencies]
diesel = { version = "=2.2.1", features = ["sqlite"] }

This breaks diesel as we cannot encapsulate the proc-macros and the main crate as "one" unit.

Possible Solution(s)

  • Do not unify features for proc macros between build-dependencies and normal dependencies
  • Do unify not only the proc macro dependencies but also the normal crates between build dependencies and normal dependencies (i.e resolver="1" behavior.)

Notes

See the offtopic part of #14406 for more discussion on this topic

Version

cargo 1.80.0 (376290515 2024-07-16)
release: 1.80.0
commit-hash: 37629051518c3df9ac2c1744589362a02ecafa99
commit-date: 2024-07-16
host: x86_64-unknown-linux-gnu
libgit2: 1.7.2 (sys:0.18.3 vendored)
libcurl: 8.6.0-DEV (sys:0.4.72+curl-8.6.0 vendored ssl:OpenSSL/1.1.1w)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: Fedora 40.0.0 [64-bit]

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-features2Area: issues specifically related to the v2 feature resolverA-proc-macroArea: compiling proc-macrosC-bugCategory: bugS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions