Skip to content

Replace bitflags! in the style crate with a lean crate-local macro - #5

Draft
nicoburns wants to merge 1 commit into
mainfrom
devin/1785855337-lean-bitflags
Draft

Replace bitflags! in the style crate with a lean crate-local macro#5
nicoburns wants to merge 1 commit into
mainfrom
devin/1785855337-lean-bitflags

Conversation

@nicoburns

Copy link
Copy Markdown
Member

Summary

Replaces the bitflags 2.x dependency of the style crate with a lean crate-local bitflags! macro (style/flags.rs) that generates only the API subset the crate actually uses. The macro keeps the same name and invocation syntax (both the struct-defining and impl-only forms), so all 55 call sites are unchanged apart from:

  • struct-form sites that had #[derive(Debug)] inside the invocation drop that derive — the macro always generates a Debug impl that lists contained flag names (matching bitflags' output, e.g. RestyleHint(RESTYLE_SELF | RECASCADE_SELF));
  • servo/restyle_damage.rs replaces <ServoRestyleDamage as bitflags::Flags>::Bits::MAX with u16::MAX.

Per type, the macro generates the flag consts, a private (name, flags) table, empty/all/bits/from_bits/from_bits_truncate/from_bits_retain/is_empty/is_all/intersects/contains/intersection/union/difference/symmetric_difference/complement/insert/remove/toggle/set/iter/iter_names, and the 9 bitwise operator impls — ~120 expanded lines instead of bitflags' ~2,500 (no hidden internal type, forwarding macros, iterator types, Binary/Octal/Hex impls, from_name parsing, or serde/arbitrary/bytemuck hooks). all()/Debug are table-driven so #[cfg]-gated flags keep working.

Only the style crate is converted; selectors/, style_traits/ and stylo_dom/ still use the bitflags crate (which also remains a transitive dependency via cssparser), but bitflags is removed from style/Cargo.toml.

Measurements

Environment: Linux x86_64 VM, rustc 1.99.0-nightly (504869653 2026-08-03), CARGO_INCREMENTAL=0, default (servo) features, dependencies pre-built, touch style/lib.rs between runs, 3 runs each.

-Zmacro-stats for the style crate (sum of all bitflags-related macro rows):

Uses Expanded lines Expanded bytes
before (bitflags 2.13.1) ~9,900 135,768 5,063,114
after (local macro) 100 11,810 492,312
delta −91.3% −90.3%

Wall times for the stylo crate itself (deps warm):

before (median of 3) after (median of 3)
cargo +nightly check -p stylo 19.87s (19.71 / 19.87 / 32.07) 19.42s (19.34 / 19.42 / 19.95)
cargo +nightly build -p stylo (debug) 39.26s (39.19 / 39.26 / 39.38) 38.46s (38.27 / 38.46 / 39.28)

Honest takeaway: despite the ~90% reduction in macro-expanded code (~124k lines / ~4.6 MB less for the compiler to expand, parse and type-check), the wall-time impact is small — roughly 0.5–1s (~2%) on both check and build, at or near run-to-run noise on this machine. Macro expansion/parsing of the bitflags output evidently isn't a dominant cost for this crate; the bulk of the time goes elsewhere (type checking the crate's own code, codegen, linking metadata).

Testing

  • cargo +nightly check -p stylo and cargo check --workspace pass.
  • cargo check --all-targets -p stylo has 10 pre-existing errors on main (test code referencing PseudoElement::MozRubyText/FirstLine); the same errors, and no new ones, occur with this change.
  • The gecko feature can't be built locally (needs mozbuild); the gecko-cfg'd sites (url/gecko.rs, gecko/*.rs, gecko-only flags in values/specified/text.rs) were converted textually with care, but are unverified by the compiler.

Link to Devin session: https://app.devin.ai/sessions/d53d0b1a1f36492486a5ce4537362adc
Requested by: @nicoburns

@nicoburns nicoburns self-assigned this Aug 4, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

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.

1 participant