# 28. `defer` et nettoyage ## 28.1 `defer` — V1 REQUIS — FIGÉ `defer` est lié au scope lexical dans lequel il est atteint. Il enregistre un cleanup exécuté à toute sortie de ce scope. Exemple : ```text { acquireA(); defer { releaseA(); } acquireB(); defer { releaseB(); } work(); } ``` Les `defer` d'un même scope s'exécutent en ordre LIFO : ```text releaseB(); releaseA(); ``` Un `defer` n'est actif que si son statement a réellement été atteint pendant l'exécution. Les sorties qui déclenchent les `defer` du scope traversé comprennent notamment : ```text fin normale return throw Fault propagé break continue emit quittant le scope concerné ``` La valeur d'un `return` ou d'un `emit` est déterminée avant l'exécution des cleanups nécessaires ; les `defer` ne peuvent pas la remplacer. ## 28.2 Unwind et ordre avec `catch` / `finally` — V1 REQUIS — FIGÉ Lorsqu'une `Exception` ou un `Fault` capturable quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant, sous réserve des détails d'unwind de `Fault` encore à fermer avec le runtime. Ordre conceptuel : ```text throw / Fault propagé -> unwind des scopes quittés -> defer de ces scopes, LIFO -> catch correspondant éventuel -> defer du scope catch, LIFO -> finally éventuel -> continuation normale ou propagation ``` Chaque scope imbriqué possède sa propre pile LIFO et est entièrement déroulé avant de poursuivre le scope parent. L'ordre exact entre `defer` et les futurs destructeurs automatiques sera finalisé avec le modèle mémoire/lifecycle, sans modifier la règle de scope LIFO propre à `defer`. ## 28.3 `defer` non-escaping — V1 REQUIS — FIGÉ Comme `finally`, un bloc `defer` ne doit jamais remplacer une sortie déjà en cours. Sont interdits dans un `defer` lorsqu'ils quittent le bloc : ```text return throw fault break continue emit ``` Aucune `Exception` non capturée ne peut sortir indirectement d'un `defer`. Une callable appelée depuis un `defer` et susceptible de lancer une `Exception` doit voir cette exception entièrement gérée à l'intérieur du bloc `defer`. Un `fault` explicite est interdit dans un `defer` pour la même raison qu'un `throw` explicite : le cleanup ne doit pas volontairement remplacer une sortie déjà en cours. Un `Fault` dynamique produit indirectement reste possible car il est unchecked ; son interaction exacte avec l'unwind/destruction fait partie du modèle mémoire encore à fermer. Un `ResultError` reste une simple valeur : un appel retournant `Result` est autorisé dans un `defer`, sous réserve des règles normales de traitement de cette valeur. ## 28.4 `finally` versus `defer` — V1 REQUIS — FIGÉ `defer` sert au cleanup lexical lié à une acquisition ou à un scope local. `finally` sert au bloc commun final d'une vraie construction `try/catch`. Un `try/finally` sans `catch` est interdit précisément parce que `defer` couvre le besoin de cleanup systématique sans introduire une construction d'exception inutile. ## 28.5 `errdefer` — REJETÉ Pas de `errdefer` séparé en V1. `catch` gère les chemins d'`Exception` et de `Fault`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme dédié uniquement à l'échec serait redondant.