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

New lints: Opt-in minor lints for added functionality #949

Open
37 tasks
obi1kenobi opened this issue Sep 26, 2024 · 0 comments
Open
37 tasks

New lints: Opt-in minor lints for added functionality #949

obi1kenobi opened this issue Sep 26, 2024 · 0 comments
Labels
A-lint Area: new or existing lint E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: Mentorship is available for this issue.

Comments

@obi1kenobi
Copy link
Owner

obi1kenobi commented Sep 26, 2024

By default, Rust isn't particularly prescriptive about the difference between a minor and a patch version bump. But many libraries and maintainers may choose to offer stronger guarantees about which kinds of changes should go patches vs minor versions. For example, they may prefer to publish new functionality (new public APIs) in minor versions while keeping patches reserved for bugfixes or other small changes that aren't noticeable at the API level.

Just like detecting removals of public APIs, cargo-semver-checks lints can also be used to detect additions to public APIs. This issue is about writing such lints.

These lints should be opt-in rather than opt-out. They should have defaults of required_update: Minor and lint_level: Allow in their definition files, and users can opt into them by increasing the lint level (e.g. to "warn") as per their preference.

Keep in mind that some API additions are major breaking changes and we already have lints for them, such as adding a variant to an exhaustive enum. New lints added here should take care to not overlap with such major lints — we never want to simultaneously flag the same change as both major and minor, since that would be very confusing to our users!

Lints in this category:

  • adding a new public API struct that is not #[non_exhaustive] and has no non-public fields: Implement new_struct_added lint #495
    • Here we may want to suggest that users add #[non_exhaustive] to the struct, since adding new fields or #[non_exhaustive] itself later on is a major breaking change.
  • adding a new #[non_exhaustive] public API struct (one of two complements of the above lint)
  • adding a new public API struct that has a non-public field and no #[non_exhaustive] (the remaining complement of the top lint)
  • adding a new public API enum that is not #[non_exhaustive]
    • Here we may want to suggest that users add #[non_exhaustive] to the enum, since adding new variants or #[non_exhaustive] itself later on is a major breaking change.
  • adding a new #[non_exhaustive] public API enum (the complement of the above lint)
  • adding a new public API union
  • public API type has gained a new auto-trait implementation
    • type = struct / enum / union — collectively ImplOwner in our schema
  • adding a new public field to a public API struct — multiple lints here:
    • If the struct could be constructed with a literal, then the field addition is a major breaking change. We use separate lints to cover the different ways in which struct literal construction may be disabled:
      • adding a new public field to a #[non_exhaustive] public API struct
      • adding a new public field to an exhaustive public API struct that has at least one private field
  • adding a new variant to a #[non_exhaustive] public API enum — multiple lints here:
    • If the enum did not have #[non_exhaustive] then this would be a major breaking change instead.
    • The new variant may itself be #[non_exhaustive], or not. Adding that #[non_exhaustive] later, or adding new fields to the variant, are both major breaking changes, so having a lint users can use to recommend newly-added variants be #[non_exhaustive] could be useful.
    • We cover the cases with multiple lints:
      • adding a new #[non_exhaustive] variant
      • adding a new plain variant that is not #[non_exhaustive]
      • adding a new tuple variant that is not #[non_exhaustive]
      • adding a new struct variant that is not #[non_exhaustive]
  • adding a new field to an existing #[non_exhaustive] tuple variant of a public API enum
    • If the variant was not #[non_exhaustive], then this would be a major breaking change instead.
  • adding a new field to an existing #[non_exhaustive] struct variant of a public API enum
    • If the variant was not #[non_exhaustive], then this would be a major breaking change instead.
  • removing #[non_exhaustive] from a public API struct that has no non-public fields
    • The new functionality here is that the struct is now newly constructible with a struct literal: MyStruct { field: 0 }
  • removing #[non_exhaustive] from a public API enum
  • removing #[non_exhaustive] from a variant of a public API enum
  • adding a new field to a public API union
  • adding a new method to a type's own impl block (a so-called "inherent method")
  • adding new associated items to a trait — multiple lints here:
    • Adding new associated items that break downstream crates' implementations of the trait is a major breaking change. We use separate lints to cover the different ways in which item additions may be non-breaking:
      • adding a new associated constant to a sealed trait (sealed trait = "downstream crate cannot impl the trait")
      • adding a new associated constant with a default value to a non-sealed trait (non-sealed so we don't overlap with the above lint, default value means downstream impls aren't affected)
      • adding a new associated type to a sealed trait (same logic as above)
      • adding a new associated type with a default value to a non-sealed trait (same logic as above)
      • adding a new trait method to a sealed trait (same logic as above)
      • adding a new trait method with a default impl to a non-sealed trait (same logic as above)
  • public API function has newly become const
  • public method in a public API type's own impl block has newly become const
  • public API function has stopped being unsafe
  • public method in a public API type's own impl block has stopped being unsafe
  • adding a new public API static item
  • adding a new public API const item
  • public API type adding a new public associated const item
  • repr(C) added on a public API type that previously did not have any repr
  • repr(transparent) added on a public API type that previously did not have any repr
  • integer repr (e.g. repr(i8)) newly added to a public API enum that previously did not have any repr
  • a new function name is now exported in the ABI (look at the export_name property, populated by e.g. #[no_mangle])

Taking a look at the existing major lints for each area is recommended, since the corresponding minor lints will likely be quite similar in implementation. For example, the "enum added" lint here will be similar to the enum missing lint, albeit with some logic flipped.

Make sure to check out our contributing guide, and take a look at what prior lints' merged PRs looked like so you know what to expect. It's easier than you think!

If you start working on one of the lint checkboxes, please post a message here to temporarily claim it (for ~a week or two, I'll follow up with you) so we don't have multiple people working on the same lint. I'll associate your name and PR with the appropriate checkbox.

@obi1kenobi obi1kenobi added A-lint Area: new or existing lint E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: Mentorship is available for this issue. labels Sep 26, 2024
@obi1kenobi obi1kenobi changed the title New lints: opt-in minor lints for added functionality New lints: Opt-in minor lints for added functionality Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: new or existing lint E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: Mentorship is available for this issue.
Projects
None yet
Development

No branches or pull requests

1 participant