Skip to content

Simplify and improve explicitness of the check-cfg syntax #636

Closed
rust-lang/rust
#111072

Description

Proposal

This proposal is a spawned of work started in this PR. Current documentation for check-cfg can be found in the unstable book.

Old proposal

This proposal wants to adds a new simpler and more explicit syntax for check-cfg. It would consist of two new form [detailed doc]:

  1. --check-cfg exhaustive(...) enables some exhaustive checking
  2. --check-cfg configure(...) enables checking the values within list-valued conditions.

The exhaustive(...) form

The exhaustive(...) form tell the compiler if it should be exhaustive about it's checking.

It currently has two exhaustiveness:

  • names: permist the compiler to check every config name by adding it's list of well-known names
  • values: permist the compiler to check it's well-known cfg values by adding it's list of well-known values

The configure(...) form

The configure(...) form enables checking the values within list-valued conditions. It has this form:

rustc --check-cfg `configure(name1, ..., nameN, "value1", "value2", ... "valueN")'

To enable checking of values, but to provide an empty set of valid values, use this form:

rustc --check-cfg `configure(name1, ..., nameN)`

The --check-cfg configure(...) option can be repeated, both for the same condition name and for different names. If it is repeated for the same condition name, then the sets of values for that condition are merged together.

Why?

The preview forms names(...) and values(...) have implicit meaning that are not strait-forward. In particular values(foo)&values(bar) and names(foo, bar) are not equivalent which has created some confusions.

Also the names() and values() form are not clear either and again created some confusions where peoples believed that values()&values(foo) could be reduced to just values(foo).

To fix that the two new forms are made to be explicit and simpler. See the table of correspondence:

  • names() -> exhaustive(names)
  • values() -> exhaustive(values)
  • names(foo) -> exhaustive(names)&configure(foo)
  • values(foo) -> configure(foo)
  • values(feat, "foo", "bar") -> configure(feat, "foo", "bar")
  • values(foo)&values(bar) -> configure(foo, bar)
  • names()&values()&values(my_cfg) -> exhaustive(names, values)&configure(my_cfg)

The two previous forms would be deprecated and will would be removed once cargo and beta rustc have the necessary support.

Open questions

  • Naming of configure (comment):

    --check-cfg configure(...) also sounds tautological, cfg already means "configure", values was a better name for this semantic, IMO.

    Could be kept as values(...) without too much difficulties, having a different name seemed clearer that it was different.

  • Naming of exhaustive:
    Too different from names to re-use the same name.

This proposal is based on the previous proposal above and the summary work done by @wesleywiser in https://hackmd.io/@wesleywiser/rJlumbfep.

This MCP proposes to:

  • remove the names() and values() form of --check-cfg (with at least one release of deprecation)
  • replace those two forms by new unified form one called cfg() (to remove most of un-intuitiveness of the previous syntax)

The cfg(...) form

The cfg(...) form enables checking the values within list-valued conditions. It has this form:

rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'

To enable checking of values, but to provide an empty set of expected values, use these forms:

rustc --check-cfg 'cfg(name1, ..., nameN)'
rustc --check-cfg 'cfg(name1, ..., nameN, values())'

To enable checking of name but not values (i.e. unknown expected values), use this form:

rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))'

To disable checking of name, use this form:

rustc --check-cfg 'cfg(any())'

The --check-cfg cfg(...) option can be repeated, both for the same condition name and for different names. If it is repeated for the same condition name, then the sets of values for that condition are merged together.

Built-in names and values

  • Built-in values checking would always be activated as long as a --check-cfg argument is present
  • Built-in names checking would always be activated as long as a --check-cfg argument is present unless if any cfg(any()) arg is passed
  • If one want to enable values and names checking without having any cfg to declare, one can use an empty cfg()

Why?

The preview forms names(...) and values(...) have implicit meaning that are not strait-forward. In particular values(foo)&values(bar) and names(foo, bar) are not equivalent which has created some confusions.

Also the names() and values() form are not clear either and again created some confusions where peoples believed that values()&values(foo) could be reduced to just values(foo).

To fix that the two new forms are made to be explicit and simpler. See the table of correspondence:

  • names() -> enable-by-default by any use of --check-cfg useless given cfg(any())
  • values() -> enable-by-default by any use of --check-cfg
  • names(foo) -> cfg(foo, any())
  • values(foo) -> cfg(foo)
  • values(feat, "foo", "bar") -> cfg(feat, values("foo", "bar"))
  • values(foo)&values(bar) -> cfg(foo, bar)
  • names()&values()&values(my_cfg) -> cfg(my_cfg)

The two previous forms would be deprecated and will would be removed once cargo and beta rustc have the necessary support.

Open questions

  • Naming of cfg form (comment):

    --check=cfg(...). I had this thought as well but was struggling to think of other things it could be extended to. It also seemed like users might think rustc --check ... is equivalent to cargo check. Need to think about this more...

    rustdoc already has a --check argument making --check=cfg(...) impossible

Mentors or Reviewers

@petrochenkov for reviewing and my-self for the implementation work

Process

The main points of the Major Change Process are as follows:

  • File an issue describing the proposal.
  • A compiler team member or contributor who is knowledgeable in the area can second by writing @rustbot second.
    • Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a -C flag, then full team check-off is required.
    • Compiler team members can initiate a check-off via @rfcbot fcp merge on either the MCP or the PR.
  • Once an MCP is seconded, the Final Comment Period begins. If no objections are raised after 10 days, the MCP is considered approved.

You can read more about Major Change Proposals on forge.

Comments

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    T-compilerAdd this label so rfcbot knows to poll the compiler teammajor-changeA proposal to make a major change to rustcmajor-change-acceptedA major change proposal that was accepted

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions