Perplexion with Reduction expressions

Not sure why this works:

   function Hash (S : String) return Character is
      (S'Reduce (Character'Max, 'a'));

…and this works:

   type Hash_Tracker is record
      Value : Hash_Value;
   end record;

   function Hash_Character (Accumulator: Hash_Value; Symbol: Character) return Hash_Value is
      (Accumulator : Hash_Tracker; Symbol : Character) return Hash_Tracker is
      ((Value => ((Accumulator.Value + Character'Pos (Symbol)) * 17) mod 256));

   function Hash (S : String) return Hash_Value is
      (Hash_Tracker'(S'Reduce (Hash_Character, (Value => 0))).Value);

…when this does not:

   function Hash_Character (Accumulator: Hash_Value; Symbol: Character) return Hash_Value is
      (((Accumulator + Character'Pos (Symbol)) * 17) mod 256);

   function Hash (S : String) return Hash_Value is
      (S'Reduce (Hash_Character, 0));

gnat 13.2.1 complains: (file, lines, column omitted)

[...] error: missing argument for parameter "Accumulator" in call to "Hash_Character" declared at line [...]

The only thing that’s changed is the type passed to Hash_Character, and it’s consistent. What am I doing wrong?

edited an oops

Works for me on msys2 gnat 13.2.0, godbolt gnat 13.1, godbolt gnat 13.2, but doesn’t appear to work on godbolt trunk. Maybe a compiler regression?

1 Like

Just wonder where Hash_Value was defined?

I didn’t think it mattered, but it was defined earlier:

subtype Hash_Value is Natural range 0 .. 255;

I was wondering that. Didn’t think of using Godbold to look into it. Guess I’ll report it via the usual channel.

It works fine on my Windows 10 running GNAT Community 2021 (20210519-103) targeting x86_64-w64-mingw32

I discovered that the problem did not appear when I ran it with gnat, only with alr. The error is caused by the switch -gnatVa, which alr activates by default. Godbolt suggests the error goes back at least to 10.2 (the point where I quit trying – I had to switch from pragma Ada_2022 to -gnatX somewhere in there).

According to the gnat manual, -gnatVa performs all validity checks. The one that sets this off is
-gnatVo
‘Validity checks for operator and attribute operands.’
Scalar arguments for predefined operators and for attributes are validity checked. This includes all operators in package Standard, the shift operators defined as intrinsic in package Interfaces and operands for attributes such as Pos. Checks are also made on individual component values for composite comparisons, and on the expressions in type conversions and qualified expressions. Checks are also made on explicit ranges using .. (e.g., slices, loops etc).
I’ll report that this is the error.

GCC 14.0.1 of 20240114 fails, without -gnatVa, with

    10.    function Hash (S : String) return Hash_Value is
    11.      (S'Reduce (Hash_Character, 0));
               |
        >>> error: expected type "Hash_Value" defined at line 4
        >>> error: found type "Standard.Character"

GCC 14.0.0 of 20231120 didn’t fail, with or without -gnatVa.

Thanks; I updated the bug report.