Skip to content

Add attributes to std::bitflags, use bitflags for std::io::FilePermission #13897

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

Merged
merged 3 commits into from
May 6, 2014

Conversation

aturon
Copy link
Member

@aturon aturon commented May 2, 2014

The std::bitflags::bitflags! macro did not provide support for
adding attributes to the generates structure, due to limitations in
the parser for macros. This patch works around the parser limitations
by requiring a flags keyword in the bitflags! invocations:

bitflags!(
    #[deriving(Hash)]
    #[doc="Three flags"]
    flags Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100
    }
)

The intent of std::bitflags is to allow building type-safe wrappers
around C-style flags APIs. But in addition to construction these flags
from the Rust side, we need a way to convert them from the C
side. This patch adds a from_bits function, which is unsafe since
the bits in question may not represent a valid combination of flags.

Finally, this patch changes std::io::FilePermissions from an exposed
u32 representation to a typesafe representation (that only allows valid
flag combinations) using the std::bitflags.

Closes #6085.

@aturon
Copy link
Member Author

aturon commented May 2, 2014

/cc @bjz

#[macro_export]
macro_rules! bitflags(
($BitFlags:ident: $T:ty {
($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe this flags keyword should be struct?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good idea, since the documentation already reveals that the generated type is a struct.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, on second thought, I'm not so sure about this -- it might be confusing. Consider:

bitflags!(
    struct Flags: u32 {
        FlagA = 1,
        FlagB = 2
    }
)

The problem is that the stuff inside { ... } doesn't look very struct-like. (If anything, it looks more like our current enums.) So having a distinct pseudo keyword like flags may be the best approach.

Copy link
Member

Choose a reason for hiding this comment

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

That's a good point, flags sounds good to me.

@alexcrichton
Copy link
Member

Also, can you re-word the commits that have breaking changes to follow these guidelines? It basically just needs to include "[breaking-change]" somewhere.

@aturon
Copy link
Member Author

aturon commented May 2, 2014

@alexcrichton This should be good to go.

@brendanzab
Copy link
Member

Looks great. 👍

@alexcrichton
Copy link
Member

It looks like this also closes #2623, could you add that to the commit message?

@aturon
Copy link
Member Author

aturon commented May 5, 2014

@alexcrichton I don't think that's right: #2623 is also specifically talking about the fact that the exposed API is in Unix style, and does not currently translate to/make sense for Windows. So I think there's more work to be done to close that issue, potentially changing the API again...

@alexcrichton
Copy link
Member

Oh hm, I see, I will comment on that issue.

aturon added 3 commits May 5, 2014 15:24
The `std::bitflags::bitflags!` macro did not provide support for
adding attributes to the generated structure or flags, due to
limitations in the parser for macros. This patch works around the
parser limitations by requiring a `flags` keyword in the overall
`bitflags!` invocation, and a `static` keyword for each flag:

    bitflags!(
        #[deriving(Hash)]
        #[doc="Three flags"]
        flags Flags: u32 {
            #[doc="The first flag"]
            static FlagA       = 0x00000001,
            static FlagB       = 0x00000010,
            static FlagC       = 0x00000100
        }
    )
The intent of `std::bitflags` is to allow building type-safe wrappers
around C-style flags APIs. But in addition to construction these flags
from the Rust side, we need a way to convert them from the C
side. This patch adds a `from_bits` function, which is unsafe since
the bits in question may not represent a valid combination of flags.
This patch changes `std::io::FilePermissions` from an exposed `u32`
representation to a typesafe representation (that only allows valid
flag combinations) using the `std::bitflags`, thus ensuring a greater
degree of safety on the Rust side.

Despite the change to the type, most code should continue to work
as-is, sincde the new type provides bit operations in the style of C
flags. To get at the underlying integer representation, use the `bits`
method; to (unsafely) convert to `FilePermissions`, use
`FilePermissions::from_bits`.

Closes rust-lang#6085.

[breaking-change]
bors added a commit that referenced this pull request May 6, 2014
The `std::bitflags::bitflags!` macro did not provide support for
adding attributes to the generates structure, due to limitations in
the parser for macros. This patch works around the parser limitations
by requiring a `flags` keyword in the `bitflags!` invocations:

    bitflags!(
        #[deriving(Hash)]
        #[doc="Three flags"]
        flags Flags: u32 {
            FlagA       = 0x00000001,
            FlagB       = 0x00000010,
            FlagC       = 0x00000100
        }
    )

The intent of `std::bitflags` is to allow building type-safe wrappers
around C-style flags APIs. But in addition to construction these flags
from the Rust side, we need a way to convert them from the C
side. This patch adds a `from_bits` function, which is unsafe since
the bits in question may not represent a valid combination of flags.

Finally, this patch changes `std::io::FilePermissions` from an exposed
`u32` representation to a typesafe representation (that only allows valid
flag combinations) using the `std::bitflags`.

Closes #6085.
@bors bors closed this May 6, 2014
@bors bors merged commit 8d1d7d9 into rust-lang:master May 6, 2014
@alexcrichton
Copy link
Member

🍬

@@ -114,6 +127,12 @@ macro_rules! bitflags(
self.bits
}

/// Convert from underlying bit representation. Unsafe because the
/// bits are not guaranteed to represent valid flags.
pub unsafe fn from_bits(bits: $T) -> $BitFlags {
Copy link
Member

Choose a reason for hiding this comment

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

Couldn't there be a safe version of this that just makes sure it's a valid combination of bits?

Copy link
Member Author

Choose a reason for hiding this comment

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

@cmr Yeah, that's a good point. I'll add this after #14009 lands.

aturon added a commit to aturon/rust that referenced this pull request May 14, 2014
Previously, the `from_bits` function in the `std::bitflags::bitflags`
macro was marked as unsafe, as it did not check that the bits being
converted actually corresponded to flags.

This patch changes the function to check against the full set of
possible flags and return an `Option` which is `None` if a non-flag bit
is set. It also adds a `from_bits_truncate` function which simply zeros
any bits not corresponding to a flag.

This addresses the concern raised in rust-lang#13897
alexcrichton pushed a commit to alexcrichton/rust that referenced this pull request May 15, 2014
Previously, the `from_bits` function in the `std::bitflags::bitflags`
macro was marked as unsafe, as it did not check that the bits being
converted actually corresponded to flags.

This patch changes the function to check against the full set of
possible flags and return an `Option` which is `None` if a non-flag bit
is set. It also adds a `from_bits_truncate` function which simply zeros
any bits not corresponding to a flag.

This addresses the concern raised in rust-lang#13897
bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

os::mkdir and friends should maybe not take u32
5 participants