sonar-delphi icon indicating copy to clipboard operation
sonar-delphi copied to clipboard

Support `unmanaged` generic constraint

Open cirras opened this issue 3 months ago • 5 comments

Prerequisites

  • [x] This improvement has not already been suggested.
  • [x] This improvement would be generally useful, not specific to my code or setup.

Engine area

Delphi language support

Improvement description

Delphi 13 has added a new unmanaged constraint for generic types.

The use-case is somewhat unclear, but this constraint ensures the type is a "simple type" and should apparently (sometimes?) be used in place of the record constraint. It's being advertised as a "partial replacement" of the record constraint.

See

Rationale

Delphi 13 support.

cirras avatar Sep 11 '25 03:09 cirras

In 12.3 a record type with managed fields was no longer considered compatible with the record constraint, the motivation probably being to save the compiler from having to generate the memory management code.

This was raised on the QP several times, e.g. RSS-3156), where Embarcadero said that it was working as intended, but after a lot of criticism they did then revert it in the April Patch.

I suspect that this unmanaged constraint is a reimplementation of the unpatched 12.3 record constraint, while keeping the "old" record constraint for its existing semantics.

fourls avatar Sep 11 '25 06:09 fourls

That being said, this comment in the documentation is very confusing:

The unmanaged constraint can be used for generic types that are placed in the variant section of a record. The unmanaged constraint is the response when the record constraint no longer allows the ones with managed fields.

I have no idea what that means.

fourls avatar Sep 11 '25 06:09 fourls

I suspect that this unmanaged constraint is a reimplementation of the unpatched 12.3 record constraint, while keeping the "old" record constraint for its existing semantics.

Agreed, that seems to make the most sense.

The unmanaged constraint can be used for generic types that are placed in the variant section of a record. The unmanaged constraint is the response when the record constraint no longer allows the ones with managed fields.

Yeah, I also found that documentation incoherent. Looks like it's calling out some super specific scenario that prompted the existence of the new constraint (probably related to the QP issues you mentioned.) But without some examples, it's just useless words.

cirras avatar Sep 11 '25 06:09 cirras

The first part of that quote is talking about how there was previously (pre 12.3) a bug when you used a managed type as the type parameter (with a record constraint) in the variant part of a record. When such a record is used, the compiler couldn't possibly know whether to generate code for managed types at the place of usage, because the record only has the potential to contain a managed type (and the tag for the variant part is not required).

In Delphi 12.3 they tried to fix this by disallowing managed types as record constraints, but got a lot of negative feedback. I think now the unmanaged constraint is the same as record, but it has this additional guarantee that makes it safe to use inside a variant record.

zaneduffield avatar Sep 11 '25 06:09 zaneduffield

Ah, that makes sense, I think that's exactly what's happened. I couldn't quite remember the details of why they changed record in 12.3 but that rings a bell.

I wonder if the compiler now prevents you from using record in the variant part of a record?

fourls avatar Sep 11 '25 07:09 fourls