Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

warn less about non-exhaustive in ffi #116863

Merged

Conversation

workingjubilee
Copy link
Member

@workingjubilee workingjubilee commented Oct 17, 2023

Bindgen allows generating #[non_exhaustive] #[repr(u32)] enums. This results in nonintuitive nonlocal improper_ctypes warnings, even when the types are otherwise perfectly valid in C.

Adjust for actual tooling expectations by avoiding warning on simple enums with only unit variants.

Closes #116831

@rustbot
Copy link
Collaborator

rustbot commented Oct 17, 2023

r? @petrochenkov

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 17, 2023
@rust-log-analyzer

This comment has been minimized.

@@ -27,3 +27,14 @@ pub enum NonExhaustiveVariants {
#[non_exhaustive] Tuple(u32),
#[non_exhaustive] Struct { field: u32 }
}

// Note the absence of repr(C): it's not necessary, and recent C code can now use repr hints too.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs don't make explicit that the ABI matches C's - https://doc.rust-lang.org/reference/type-layout.html#primitive-representation-of-field-less-enums - my sense is that's probably just an oversight?

But as-is it's not clear to me that this is accurate.

Copy link
Member Author

@workingjubilee workingjubilee Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typedef enum Name: uint8_t {
    /* fields */
} Name;

is legal C code as-of C23 and must, by brute force of logic, match

#[repr(u8)]
enum Name {
    /* fields */
}

or fail to compile, according to my understanding. (There simply isn't any other valid representation for the two types in either language's rules, if the Rust variants are data-free: they must match.)

Copy link
Member Author

@workingjubilee workingjubilee Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy to revise the wording but

  • it would be inconsistent with improper_ctypes as-is to warn on u32 in FFI
  • the inadequacy of the docs is a preexisting issue it seems
  • if I had my druthers I would yeet the entire idea of linting on another crate's types in a crate that isn't the declaring crate from the lint, because it seems absurd, especially when in an extern "C" block that is only declaring a binding against C functions, not declaring a new Rust function (thus the bound function implicitly exists anyway), and this is very much the most-lamented lint in terms of false positives.

@workingjubilee workingjubilee force-pushed the non-exhaustive-is-not-ffi-unsafe branch from 2ce1399 to 34094d0 Compare October 17, 2023 23:04
@workingjubilee
Copy link
Member Author

I suppose some tests might depend on not having their imports formatted, but this is silly...

@workingjubilee workingjubilee force-pushed the non-exhaustive-is-not-ffi-unsafe branch from 34094d0 to 25e2128 Compare October 17, 2023 23:23
@petrochenkov
Copy link
Contributor

When I started reading #116831 my first reaction was "if NodeTag is so special, then it's fine to use allow", but the problem is that you cannot actually apply allow to the single location where it would be most appropriate - enum NodeTag definition.

From the issue it looks like what you want to express is "this enum is non_exhaustive, but I guarantee that no future variant additions will change its ABI, so it's fine to use it in C interfaces and improper_ctypes should not be reported".

Maybe non_exhaustive can be enhanced with some markers describing what we promise not to add, and it would be useful in other situations too, not just in improper_ctypes.
In the meantime the lint could be relaxed.

@petrochenkov
Copy link
Contributor

Warning on #[repr(C)] #[non_exhaustive] was an explicit lang team decision, so I'll send this back to lang team for reconsidering.

@petrochenkov petrochenkov added T-lang Relevant to the language team, which will review and decide on the PR/issue. S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 25, 2023
@workingjubilee
Copy link
Member Author

When I started reading #116831 my first reaction was "if NodeTag is so special, then it's fine to use allow", but the problem is that you cannot actually apply allow to the single location where it would be most appropriate - enum NodeTag definition.

Correct, if the... approximately entire linting system was reworked, as I understand it, I guess the allow-site could be in the upstream crate?

@petrochenkov
Copy link
Contributor

Well, not allow specifically, something else.
allow is supposed to be placed on the location where something suspicious happens, e.g. a FFI-unsafe type is used in FFI (i.e. fn rdb_read_page in the linked issue).
What we want here is to mark NodeTag as FFI-safe, so it's never suspicious when used in any location.

@workingjubilee
Copy link
Member Author

Right, an arbitrary #[no_really_let_me_promise_a_semistable_abi_yet_nonexhaustive_for_reasons_that_are_really_long_to_explain] technically also works. That solution does not "spark joy", I think, but I can accept it.

@bors
Copy link
Contributor

bors commented Apr 30, 2024

☔ The latest upstream changes (presumably #124558) made this pull request unmergeable. Please resolve the merge conflicts.

@workingjubilee
Copy link
Member Author

uhhhh
r? lang

@rustbot rustbot assigned scottmcm and unassigned petrochenkov May 14, 2024
@scottmcm scottmcm added the I-lang-nominated Nominated for discussion during a lang team meeting. label Jun 12, 2024
@traviscross
Copy link
Contributor

@rustbot labels -I-lang-nominated

We discussed this issue in the meeting on 2024-06-12. Our consensus was as follows:

  • The intent of "non-exhaustive" (on enums) is to say "ensure that code will continue to compile if new variants are added".
    • For lints, we generally try to ensure that you also won't get new lints.
    • But lints are lints, we can say it's ok if "there exists extensions that would be legal" and "the ones that would get you a new lint are unlikely".
  • In the case:
    • We judge that adding a new data-carrying variant to an existing C-like enum that is passed to C is "unlikely", so we don't need the lint to account for it.
      • E.g. going from enum Foo { A, B, C } to enum Foo { A, B, C, D(u32) }.
  • Additional consensus items:
    • Non-exhaustive currently means code must be prepared for:
      • On enums: new variants with any set of fields, public or private, etc.
      • On structs or enum variants themselves: can add new fields with any type, public or private, etc.
    • You cannot have values of an enum outside of the declared variants regardless of #[non_exhaustive], that would require a fresh feature.
  • Possible future work:
    • Extensions or revamped non-exhaustive that lets you be more specific about the range of future changes.
    • A way to say that an enum may have variants not listed (e.g., due to C code).

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label Jul 3, 2024
@workingjubilee
Copy link
Member Author

Thank you, I will rebase this shortly and write about-as-much down into rustc_lint.

@traviscross traviscross added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). labels Aug 19, 2024
Bindgen allows generating `#[non_exhaustive] #[repr(u32)]` enums.
This results in nonintuitive nonlocal `improper_ctypes` warnings,
even when the types are otherwise perfectly valid in C.

Adjust for actual tooling expectations by avoiding warning on
simple enums with only unit variants.
Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from the minor nit, and based on the T-lang decision prior to this, this looks reasonable to me. Feel free to r=me after slightly expanding on what "really tagged union" means in the comment.

@jieyouxu jieyouxu added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 18, 2024
@jieyouxu
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Oct 19, 2024

📌 Commit 64f5736 has been approved by jieyouxu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 19, 2024
Extracting this logic into a module makes it easier to write down, and
more importantly, later find, the actual decisions we've made.
@workingjubilee workingjubilee force-pushed the non-exhaustive-is-not-ffi-unsafe branch from 64f5736 to 62aa8f0 Compare October 19, 2024 05:01
@workingjubilee
Copy link
Member Author

er!
@bors r-

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Oct 19, 2024
@workingjubilee
Copy link
Member Author

@bors r=jieyouxu

@bors
Copy link
Contributor

bors commented Oct 19, 2024

📌 Commit 62aa8f0 has been approved by jieyouxu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 19, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 19, 2024
…ot-ffi-unsafe, r=jieyouxu

warn less about non-exhaustive in ffi

Bindgen allows generating `#[non_exhaustive] #[repr(u32)]` enums. This results in nonintuitive nonlocal `improper_ctypes` warnings, even when the types are otherwise perfectly valid in C.

Adjust for actual tooling expectations by avoiding warning on simple enums with only unit variants.

Closes rust-lang#116831
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 19, 2024
…iaskrgr

Rollup of 12 pull requests

Successful merges:

 - rust-lang#116863 (warn less about non-exhaustive in ffi)
 - rust-lang#127675 (Remove invalid help diagnostics for const pointer)
 - rust-lang#131772 (Remove `const_refs_to_static` TODO in proc_macro)
 - rust-lang#131789 (Make sure that outer opaques capture inner opaques's lifetimes even with precise capturing syntax)
 - rust-lang#131795 (Stop inverting expectation in normalization errors)
 - rust-lang#131920 (Add codegen test for branchy bool match)
 - rust-lang#131921 (replace STATX_ALL with (STATX_BASIC_STATS | STATX_BTIME) as former is deprecated)
 - rust-lang#131925 (Warn on redundant `--cfg` directive when revisions are used)
 - rust-lang#131931 (Remove unnecessary constness from `lower_generic_args_of_path`)
 - rust-lang#131932 (use tracked_path in rustc_fluent_macro)
 - rust-lang#131936 (feat(rustdoc-json-types): introduce rustc-hash feature)
 - rust-lang#131939 (Get rid of `OnlySelfBounds`)

Failed merges:

 - rust-lang#131181 (Compiletest: Custom differ)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit b2d132f into rust-lang:master Oct 20, 2024
6 checks passed
@rustbot rustbot added this to the 1.84.0 milestone Oct 20, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 20, 2024
Rollup merge of rust-lang#116863 - workingjubilee:non-exhaustive-is-not-ffi-unsafe, r=jieyouxu

warn less about non-exhaustive in ffi

Bindgen allows generating `#[non_exhaustive] #[repr(u32)]` enums. This results in nonintuitive nonlocal `improper_ctypes` warnings, even when the types are otherwise perfectly valid in C.

Adjust for actual tooling expectations by avoiding warning on simple enums with only unit variants.

Closes rust-lang#116831
@workingjubilee workingjubilee deleted the non-exhaustive-is-not-ffi-unsafe branch October 20, 2024 01:36
tgross35 added a commit to tgross35/rust that referenced this pull request Nov 5, 2024
…ler-errors

More tests for non-exhaustive C-like enums in FFI

Add a few more tests for the `improper_ctypes` lint as found with the [varnish-rs](https://github.com/gquintard/varnish-rs) project.

This follows up on rust-lang#116831, fixed in rust-lang#116863 by `@workingjubilee` - I have been seeing these fail with the bindgen-generated non-exhaustive enums inside other structs. Seems the issue does not exist in the primary branch, so this PR just makes sure more cases are covered for the future.
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Nov 5, 2024
…ler-errors

More tests for non-exhaustive C-like enums in FFI

Add a few more tests for the `improper_ctypes` lint as found with the [varnish-rs](https://github.com/gquintard/varnish-rs) project.

This follows up on rust-lang#116831, fixed in rust-lang#116863 by ``@workingjubilee`` - I have been seeing these fail with the bindgen-generated non-exhaustive enums inside other structs. Seems the issue does not exist in the primary branch, so this PR just makes sure more cases are covered for the future.
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 5, 2024
Rollup merge of rust-lang#132303 - nyurik:non-exhaustive-err, r=compiler-errors

More tests for non-exhaustive C-like enums in FFI

Add a few more tests for the `improper_ctypes` lint as found with the [varnish-rs](https://github.com/gquintard/varnish-rs) project.

This follows up on rust-lang#116831, fixed in rust-lang#116863 by ``@workingjubilee`` - I have been seeing these fail with the bindgen-generated non-exhaustive enums inside other structs. Seems the issue does not exist in the primary branch, so this PR just makes sure more cases are covered for the future.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dubious improper_ctypes firing on recursive non-local containment?