name: webrtc/include-tracking-bug-in-deprecated-attribute description: When deprecating declarations or struct fields, annotate with [[deprecated(“...”)]] with replacement guidance or bug URL, or ABSL_DEPRECATE_AND_INLINE(), avoiding comments alone or bare attributes rubric: readability severity: blocking

Rule. When deprecating functions, methods, constructors, classes, type aliases, or configuration fields in options/settings structs, annotate declarations with active [[deprecated("...")]] specifying explicit replacement guidance or a tracking bug URL (e.g., [[deprecated("Use NewMethod instead; see b/12345")]]). Either delete dead or obsolete fields/declarations completely, or annotate them if temporarily retained for downstream compatibility. Do not leave deprecation attributes commented out, do not rely solely on informal // DEPRECATED or TODO comments without compiler annotations, avoid bare [[deprecated]] attributes lacking migration guidance, and omit redundant // Deprecated comment banners above annotated declarations.

For trivial wrapper functions or type aliases defined inline in header files, annotate them with ABSL_DEPRECATE_AND_INLINE() to enable automated downstream migration. Conversely, use [[deprecated("...")]] (not ABSL_DEPRECATE_AND_INLINE()) for out-of-line declarations or functions containing non-trivial implementation logic (such as raw casts or complex operations) that refactoring tools should not inline into callers.

Why. Informal comments (such as // DEPRECATED) and commented-out attributes are not enforced by the compiler, misleading callers into believing dead options or functions are still supported. Bare [[deprecated]] attributes produce uninformative compiler diagnostics without migration direction, while redundant comment banners add maintenance clutter.

Providing explicit replacement guidance or tracking bug URLs in active [[deprecated("...")]] attributes ensures compile-time errors in WebRTC and actionable warnings for downstream projects. Completely removing dead struct fields keeps configuration interfaces clean. Using ABSL_DEPRECATE_AND_INLINE() on trivial inline wrappers and type aliases enables automated refactoring tooling to inline or rewrite call sites across codebases while inline definitions prevent ODR violations, whereas [[deprecated("...")]] on non-trivial functions prevents tooling from mechanically inlining raw casts or unsafe logic into callers.

Examples

Bad:

// 1. Informal comment on deprecated struct/config field:
struct DcsctpOptions {
  // DEPRECATED: See `zero_checksum_alternate_error_detection_method`.
  bool enable_zero_checksum = false;

  ZeroChecksumAlternative zero_checksum_alternate_error_detection_method =
      ZeroChecksumAlternative::kNone;
};

// 2. Bare [[deprecated]], commented-out attribute, or comment-only deprecation:
// [[deprecated("Use Encode(clip, bitrate) instead")]]
virtual RTCErrorOr<std::string> Encode2(const TestClip& clip,
                                        DataRate bitrate);

// Deprecated... Use SetPacerConfig.
[[deprecated]]
void SetSendBurstInterval(TimeDelta burst_interval);

// 3. Plain [[deprecated]] on trivial inline wrapper or alias where automated inlining is desirable:
[[deprecated("Use sdesc->Clone()")]]
inline std::unique_ptr<SessionDescriptionInterface> CloneSessionDescription(
    const SessionDescriptionInterface* sdesc) {
  return sdesc->Clone();
}

// 4. Using ABSL_DEPRECATE_AND_INLINE on non-trivial implementation logic:
ABSL_DEPRECATE_AND_INLINE()
inline void Set8(void* memory, size_t offset, uint8_t v) {
  static_cast<uint8_t*>(memory)[offset] = v;
}

Good:

// 1. Active [[deprecated]] on retained config field, or remove dead fields:
struct DcsctpOptions {
  [[deprecated("Use zero_checksum_alternate_error_detection_method")]]
  bool enable_zero_checksum = false;

  ZeroChecksumAlternative zero_checksum_alternate_error_detection_method =
      ZeroChecksumAlternative::kNone;
};

// 2. Active [[deprecated]] with replacement guidance/bug URL and no redundant comment banner:
[[deprecated("Use Encode(clip, bitrate) instead; see b/12345")]]
virtual RTCErrorOr<std::string> Encode2(const TestClip& clip,
                                        DataRate bitrate);

[[deprecated("Use SetPacerConfig instead; see b/446768451")]]
void SetSendBurstInterval(TimeDelta burst_interval);

// 3. Inlined definition with ABSL_DEPRECATE_AND_INLINE enables automated refactoring:
ABSL_DEPRECATE_AND_INLINE()
inline std::unique_ptr<SessionDescriptionInterface> CloneSessionDescription(
    const SessionDescriptionInterface* sdesc) {
  return sdesc->Clone();
}

using OldSessionDescription ABSL_DEPRECATE_AND_INLINE() =
    SessionDescriptionInterface;

// 4. Use [[deprecated("...")]] when callers should migrate without inlining raw logic:
[[deprecated("Use version with ArrayView")]]
inline void Set8(void* memory, size_t offset, uint8_t v) {
  static_cast<uint8_t*>(memory)[offset] = v;
}