Chromium Chronicle image

The Chromium Chronicle #24: StrongAlias, IdType, and TokenType

Published on

Episode 24: by Łukasz Anforowicz in Bellevue, WA (August, 2021)
Previous episodes

Can you spot the bug in the code below? Would you see the bug in a code review, when looking only at the callsite?

Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());

The same type may sometimes represent values from incompatible domains. This usually happens for non-specific data types like integers or strings. The example above illustrates how this can cause bugs. Fortunately, Chromium's //base makes it easy to introduce explicit, distinct types:

#include "base/types/strong_alias.h"

// The first template argument of StrongAlias is a "tag" type.
// The "tag" type is used to distinguish between different
// StrongAlias types.
using CommandData = base::StrongAlias<class CommandDataTag, int>;
using CommandBufferId = base::StrongAlias<class CommandBufferIdTag, int>;

Token CreateToken(CommandData command_data, CommandBufferId buffer_id);

Separate types improve readability. Additionally, StrongAlias catches type mix-ups at compile time:

test.cc:456:16: error: no matching function for call to 'CreateToken'
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
^~~~~~~~~~~
test.cc:123:7: note: candidate function not viable: no known conversion from
'StrongAlias<class CommandBufferIdTag, [...]>' to
'StrongAlias<class CommandDataTag, [...]>' for 1st argument
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
^

The compiler sees that the types are incompatible, because they have a different "tag" type. StrongAlias accepts any type as the "tag" type. The example shows that the "tag" type doesn't even need a type definition anywhere—an in-place forward declaration of a non-existent class works fine.

In the future, instead of a non-specific type (for example, a bool, an int, a string), consider these alternatives:

  • Use base::IdType32<TagType> instead of using int32_t as an identifier.
  • Use base::TokenType<TagType> instead of a non-specific base::UnguessableToken.
  • Use an enum class instead of a bool (for example, kForReload, kNotForReload instead of true, false).
  • Replace other non-specific types with base::StrongAlias<TagType, SomeWrappedType>.

Published on Improve article

Back

Deprecations and removals in Chrome 94

Next

[OUTDATED] First-Party Sets and the SameParty attribute

This site uses cookies to deliver and enhance the quality of its services and to analyze traffic. If you agree, cookies are also used to serve advertising and to personalize the content and advertisements that you see. Learn more about our use of cookies.