August 25th, 2021

The Windows Runtime PassArray is a read-only array, even though it isn’t declared const

As I noted some time ago, the Windows Runtime PassArray pattern passes a read-only non-owning counted array which is nevertheless not declared as const.

Indeed, if you try to force the array type to be const in your IDL declaration:

HRESULT SetData([in] UINT32 dataSize, [in, size_is(dataSize)] const INT32* data);

The const is ignored, and the resulting metadata declares the parameter as non-const.

There are a few reasons for this, partly intentional, and partly a technicality.

The technicality is that the const attribute is lost because Windows Runtime methods are described by metadata that physically takes the form of an ECMA-335 assembly (though restricted to a very limited subset of full ECMA-335), and ECMA-335 does not have const. Therefore Windows Runtime metadata cannot have const.

Mind you, this is an unsatisfying explanation since it’s semi-circular. Windows Runtime metadata doesn’t have const because the designers chose a format that doesn’t support const, and it’s okay to have chosen a format that doesn’t support const because Windows Runtime metadata doesn’t use const.

But really, if they really wanted const, then they would have chosen some other file format that does support const.

The Windows Runtime does not have const because the concept cannot be expressed in most programming languages,¹ and the Windows Runtime intends to be language-independent. Limiting the feature set of the Windows Runtime type system makes it more likely that it can be consumed by a broad range of programming languages.

¹ Indeed, it’s really only C, C++ and now Rust that have such a concept. The C++ projections do represent the array as const: It is a const Platform::Array in C++/CX, and it is a winrt::array_view<T const> in C++/WinRT. Similarly, the Rust projection represents the array as an immutable reference.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

10 comments

Discussion is closed. Login to edit/delete existing comments.

  • Fabian Schmied

    The ECMA-335 metadata format can actually express “const” via its concept of “custom modifiers”.

    Quoting from ECMA-335, Partition II, 7.1.1: “For example, the const qualifier in the C programming language can be modelled with an optional modifier […].”

    • IS4

      Indeed. This is heavily used by C++/CLI assemblies, where you can easily find modreq(System.Runtime.CompilerServices.IsConst).

  • Paulo Pinto

    D, Delphi and Swift also have such concept.

    And if we stray from mainstream path, languages like ML family, Active Oberon and Modula-3 also do have such concept.

    • jahns@chemie.uni-hamburg.de

      I'm not sure what Raymond meant by the concept, because const is in some ways extremely specific. But many languages that borrow from Fortran and Fortran itself have <code> argument (what C calls parameters) declarations. Those have mostly the same implications as const for non-nested types and are a bit more strict for stuff containing pointers. While C-derived languages don't mind modifications to pointers passed as members of const declared structs, Fortran would disallow that.

      It...

      Read more
    • Virgo Pärna

      I’m not sure about Delphi. In Delphi const means, that value of pointer cannot be changed, pointed value can be changed. So Delphi

      const data: PINT

      would be more like C

      int * const data
      • Paulo Pinto

        In Delphi it is more like,

        function SetData(dataSize: UINT32; const data: array of INT32): HRESULT;
      • Virgo Pärna

        In pure Delphi that dataSize would be superfluous.

        And you cannot use open arrays on API functions that you want to be exported for use in another languages or when importing from C (as far as i know).

      • Paulo Pinto

        Of course it would be superfluous, the whole point of writing like that was to match the example being described, as per COM ABI.

        Now, if there was a Delphi Projection generator for WinRT types, then eventually it might be smart enough to get rid of dataSize, which isn't anyway the point I was making.

        Everything that Delphi can is accessible to C++, via C++ Builder as VCL is mostly written in Delphi, including the new COM...

        Read more
    • Daniel Sturm

      Swift’s idea of const is as I understand it pretty much the same as const in c# or java but not the same concept as c++ has.

      I assume the same is true for the other languages listed, at least I don’t remember const correctness ever being an issue when we learned Delphi in highschool (boy I’m getting old)

      • Paulo Pinto

        Swift is immutable by default, so actually is the same const as ML languages, which you also find in Rust.

        <code>

        If you wanted to be able to change data, then it would be

        <code>

        Delphi in 2021 is a bit different than those highschool days, similarly with the proper type alias it would be,

        <code>

        Read more