Skip to content

auto-inline: an annotated block literal inlines anyway, and the splice drops its annotations #3752

Description

@borisbat

The two auto-inline tiers treat annotations asymmetrically (src/ast/ast_inline.cpp):

  • Functions are conservative: isAnnotated (~line 590) refuses best-effort inlining for any annotation other than export / unused_argument, on the stated ground that annotations may carry call-site semantics (verifyCall, transform, per-call codegen) that splicing the call away would bypass.
  • Block literals are permissive: canBlockInline (~line 1631) checks only for [never_inline] among the block's annotations. Any other block annotation does not decline the splice, and the InvokeBlock arm then executes bodyClone->annotations.clear() (~line 2582) — the annotation and whatever semantics it carried vanish silently.

So a block literal carrying a semantic block annotation (a macro-attached AstBlockAnnotation, or any future block-level marker) is inlined with the annotation discarded, with no diagnostic. The function tier's own comment states exactly why this is unsound.

Expected: the block tier should mirror the function tier — refuse to inline a block whose annotation list contains anything beyond known-inert markers, or at minimum refuse instead of clearing.

Found while working around a related constraint in the same pass (a [never_inline] marker was needed on MSL helper functions so the auto-inliner would not fold them back into a template method whose value-position splice requires a single-return body).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions