diff --git a/esphome/automation.py b/esphome/automation.py index 996181f50b..7b1d6ceca1 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -671,7 +671,7 @@ async def build_callback_automation( callback_method: str, args: TemplateArgsType, config: ConfigType, - forwarder: MockObjClass | None = None, + forwarder: MockObj | MockObjClass | None = None, ) -> None: """Build an Automation and register it as a callback on the parent. diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 35f9e9bf38..fc2cad99be 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -494,12 +494,14 @@ template class Automation { /// Callback forwarder that triggers an Automation directly. /// One operator() instantiation per Automation signature, shared across all call sites. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. template struct TriggerForwarder { Automation *automation; void operator()(const Ts &...args) const { this->automation->trigger(args...); } }; /// Callback forwarder that triggers an Automation<> only when the bool arg is true. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. struct TriggerOnTrueForwarder { Automation<> *automation; void operator()(bool state) const { @@ -509,6 +511,7 @@ struct TriggerOnTrueForwarder { }; /// Callback forwarder that triggers an Automation<> only when the bool arg is false. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. struct TriggerOnFalseForwarder { Automation<> *automation; void operator()(bool state) const { @@ -517,4 +520,13 @@ struct TriggerOnFalseForwarder { } }; +// Ensure forwarders fit in Callback::ctx_ (pointer-sized inline storage). +// If these fail, the forwarder would heap-allocate in Callback::create(). +static_assert(sizeof(TriggerForwarder<>) <= sizeof(void *)); +static_assert(sizeof(TriggerOnTrueForwarder) <= sizeof(void *)); +static_assert(sizeof(TriggerOnFalseForwarder) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v>); +static_assert(std::is_trivially_copyable_v); +static_assert(std::is_trivially_copyable_v); + } // namespace esphome