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

Split generated code into two types #282

Merged
merged 12 commits into from Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/rust.yml
Expand Up @@ -46,8 +46,17 @@ jobs:
profile: minimal
toolchain: ${{ matrix.channel }}-${{ matrix.rust_target }}

- name: Tests
run: cargo test --features example_generated
- name: Install cargo-hack
run: cargo install cargo-hack

- name: Powerset
run: cargo hack test --feature-powerset --lib --optional-deps "serde" --depth 3 --skip rustc-dep-of-std

- name: Docs
run: cargo doc --features example_generated

- name: Smoke test
run: cargo run --manifest-path tests/smoke-test/Cargo.toml

embedded:
name: Build (embedded)
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Expand Up @@ -16,16 +16,16 @@ categories = ["no-std"]
description = """
A macro to generate structures which behave like bitflags.
"""
exclude = ["bors.toml"]
exclude = ["tests", ".github"]

[dependencies]
core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' }
compiler_builtins = { version = '0.1.2', optional = true }
serde = { version = "1.0", optional = true }
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
compiler_builtins = { version = "0.1.2", optional = true }

[dev-dependencies]
trybuild = "1.0"
rustversion = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

Expand Down
35 changes: 22 additions & 13 deletions src/bitflags_trait.rs
@@ -1,8 +1,5 @@
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};

#[doc(hidden)]
pub trait ImplementedByBitFlagsMacro {}

/// A trait that is automatically implemented for all bitflags.
///
/// It should not be implemented manually.
Expand All @@ -25,16 +22,7 @@ pub trait BitFlags: ImplementedByBitFlagsMacro {
fn from_bits_truncate(bits: Self::Bits) -> Self;
/// Convert from underlying bit representation, preserving all
/// bits (even those not corresponding to a defined flag).
///
/// # Safety
///
/// The caller of the `bitflags!` macro can chose to allow or
/// disallow extra bits for their bitflags type.
///
/// The caller of `from_bits_unchecked()` has to ensure that
/// all bits correspond to a defined flag or that extra bits
/// are valid for this bitflags type.
unsafe fn from_bits_unchecked(bits: Self::Bits) -> Self;
fn from_bits_retain(bits: Self::Bits) -> Self;
/// Returns `true` if no flags are currently stored.
fn is_empty(&self) -> bool;
/// Returns `true` if all flags are currently set.
Expand All @@ -53,9 +41,22 @@ pub trait BitFlags: ImplementedByBitFlagsMacro {
fn set(&mut self, other: Self, value: bool);
}

/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro.
///
/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their
/// manual implementations won't break between non-breaking releases.
#[doc(hidden)]
pub trait ImplementedByBitFlagsMacro {}

// Not re-exported
pub trait Sealed {}

// Private implementation details
//
// The `Bits`, `PublicFlags`, and `InternalFlags` traits are implementation details of the `bitflags!`
// macro that we're free to change here. They work with the `bitflags!` macro to separate the generated
// code that belongs to end-users, and the generated code that belongs to this library.

/// A private trait that encodes the requirements of underlying bits types that can hold flags.
///
/// This trait may be made public at some future point, but it presents a compatibility hazard
Expand Down Expand Up @@ -107,3 +108,11 @@ impl_bits! {
u64, i64,
u128, i128,
}

pub trait PublicFlags {
type InternalFlags;
}

pub trait InternalFlags {
type PublicFlags;
}
31 changes: 30 additions & 1 deletion src/example_generated.rs
Expand Up @@ -9,6 +9,35 @@ bitflags! {
const A = 0b00000001;
const B = 0b00000010;
const C = 0b00000100;
const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
const ABC = Self::A.bits() | Self::B.bits() | Self::C.bits();
}
}

/// This is the same internal field available as `self.0` on bitflags types.
/// These types aren't reachable by callers of `bitflags!`, they don't appear in the API of your
/// crate, but you can still interact with them through `self.0` in the module that defines the
/// bitflags type.
///
/// You can use this example as a reference for what methods are available to all internal bitflags
/// fields if you want to add custom functionality to your bitflags types.
///
/// Note that this struct is just for documentation purposes only, it must not be used outside
/// this crate.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct FlagsField {
bits: u32,
}

__impl_internal_bitflags! {
FlagsField: u32 {
A;
B;
C;
ABC;
}
}

impl crate::__private::InternalFlags for FlagsField {
type PublicFlags = Flags;
}