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.
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; }