static assert not printing out along the error diagnostic

someone someone at somewhere.com
Wed Jul 14 22:59:38 UTC 2021


On Wednesday, 14 July 2021 at 19:00:08 UTC, jfondren wrote:
> On Wednesday, 14 July 2021 at 18:04:44 UTC, someone wrote:
>> On Wednesday, 14 July 2021 at 06:28:37 UTC, jfondren wrote:
>>
>>> alternate 1:
>>> - pull tests out into a named enum template, like std.traits
>>> - always static assert enum, rather than conditionally 
>>> asserting false
>>> - always have the rest of the code
>>>
>>> ```d
>>> enum isString(T) = is(T == string) || is(T == wstring) || 
>>> is(T == dstring);
>>> // very similar to std.traits.isSomeString
>>>
>>> struct gudtUGC(T) {
>>>     static assert(isString!T, "error message");
>>>     // unconditional structure code
>>> }
>>> ```
>>
>> ... is it me or this isn't triggering the assert either ?
>
> This isn't a complete example. The same problem elsewhere in 
> your program can cause dmd to exit before getting to the static 
> assert here, for the same reason that the static assert in your 
> original code wasn't got to.
>
> Here's a complete example:
>
> ```d
> enum isString(T) = is(T == string) || is(T == wstring) || is(T 
> == dstring);
>
> struct gudtUGC(T) {
>     static assert(isString!T, "error message");
>     // unconditional structure code
> }
>
> unittest {
>     gudtUGC!int;
> }
> ```
>
> which fails with
>
> ```
> example.d(4): Error: static assert:  "error message"
> example.d(9):        instantiated from here: `gudtUGC!int`
> ```
>
> If you have the static assert there but then still follow up 
> with static ifs that only conditionally produce an alias, then 
> you have the same problem still.

Please, go to the bottom of the unittest block and uncomment one 
of those lines (DMD version here is DMD64 D Compiler v2.096.1):
```d
/// implementation-bugs [-] using foreach (with this structure) 
always misses the last grapheme‐cluster … possible phobos bug # 
20483 @ unittest's testUTFcommon() last line
/// implementation-bugs [-] static assert not firing

/// implementation‐tasks [✓] for the time being input parameters 
are declared const instead of in; eventually they'll be back to 
in when the related DIP was setted once and for all; but, 
definetely—not scope const
/// implementation‐tasks [✓] reconsider excessive cast usage as 
suggested by Ali: bypassing compiler checks could be potentially 
harmful … cast and integer promotion @ 
http://ddili.org/ders/d.en/cast.html
/// implementation‐tasks [-] reconsider making this whole UDT 
zero‐based as suggested by ag0aep6g—has a good point

/// implementation‐tasks‐possible [-] pad[L|R]
/// implementation‐tasks‐possible [-] replicate/repeat
/// implementation‐tasks‐possible [-] replace(string, string)
/// implementation‐tasks‐possible [-] translate(string, string) … 
same‐size strings matching one‐to‐one

/// usage: array slicing can be used for usual things like: 
left() right() substr() etc … mainly when grapheme‐clusters are 
not expected at all
/// usage: array slicing needs a zero‐based first range argument 
and a second one one‐based (or one‐past‐beyond; which it is 
somehow … counter‐intuitive

module fw.types.UniCode;

import std.algorithm : map, joiner;
import std.array : array;
import std.conv : to;
import std.range : walkLength, take, tail, drop, dropBack; /// 
repeat, padLeft, padRight
import std.stdio;
import std.uni : Grapheme, byGrapheme;

/// within this file: gudtUGC



shared static this() { }  /// the following will be executed 
only‐once per‐app:
static this() { }         /// the following will be executed 
only‐once per‐thread:
static ~this() { }        /// the following will be executed 
only‐once per‐thread:
shared static ~this() { } /// the following will be executed 
only‐once per‐app:



alias stringUGC = Grapheme;
alias stringUGC08 = gudtUGC!(stringUTF08);
alias stringUGC16 = gudtUGC!(stringUTF16);
alias stringUGC32 = gudtUGC!(stringUTF32);
alias stringUTF08 = string;  /// same as immutable(char )[];
alias stringUTF16 = wstring; /// same as immutable(wchar)[];
alias stringUTF32 = dstring; /// same as immutable(dchar)[];

     enum isTypeSupported(type) =
        is(type == stringUTF08) ||
        is(type == stringUTF16) ||
        is(type == stringUTF32)
        ;

/// mixin templateUGC!(stringUTF08, r"gudtUGC08"d);
/// mixin templateUGC!(stringUTF16, r"gudtUGC16"d);
/// mixin templateUGC!(stringUTF32, r"gudtUGC32"d);
/// template templateUGC (typeStringUTF, alias lstrStructureID) { 
/// if these were possible there will be no need for stringUGC## 
aliases in main()

public struct gudtUGC(typeStringUTF) { /// UniCode 
grapheme‐cluster‐aware string manipulation (implemented for 
one‐based operations)

        static assert(
           isTypeSupported!(typeStringUTF),
           r"ooops … gudtUGC structure requires 
[string|wstring|dstring] ≠ ["d ~ typeStringUTF.stringof ~ r"]"d
           ); /// meaning: this will halt compilation if this UDT 
was instantiated with a type other than the ones intended

        /// provides: public property size_t count

        /// provides: public size_t decode(typeStringUTF 
strSequence)
        /// provides: public typeStringUTF encode()

        /// provides: public gudtUGC!(typeStringUTF) take(size_t 
intStart, size_t intCount = 1)
        /// provides: public gudtUGC!(typeStringUTF) takeL(size_t 
intCount)
        /// provides: public gudtUGC!(typeStringUTF) takeR(size_t 
intCount)
        /// provides: public gudtUGC!(typeStringUTF) chopL(size_t 
intCount)
        /// provides: public gudtUGC!(typeStringUTF) chopR(size_t 
intCount)
        /// provides: public gudtUGC!(typeStringUTF) padL(size_t 
intCount, typeStringUTF strPadding = r" ")
        /// provides: public gudtUGC!(typeStringUTF) padR(size_t 
intCount, typeStringUTF strPadding = r" ")

        /// provides: public typeStringUTF takeasUTF(size_t 
intStart, size_t intCount = 1)
        /// provides: public typeStringUTF takeLasUTF(size_t 
intCount)
        /// provides: public typeStringUTF takeRasUTF(size_t 
intCount)
        /// provides: public typeStringUTF chopLasUTF(size_t 
intCount)
        /// provides: public typeStringUTF chopRasUTF(size_t 
intCount)
        /// provides: public typeStringUTF padL(size_t intCount, 
typeStringUTF strPadding = r" ")
        /// provides: public typeStringUTF padR(size_t intCount, 
typeStringUTF strPadding = r" ")

        /// usage; eg: stringUGC32("äëåčñœß … russian = русский 🇷🇺 
≠ 🇯🇵 日本語 = japanese"d).take(35, 3).take(1,2).take(1,1).encode(); 
/// 日
        /// usage; eg: stringUGC32("äëåčñœß … russian = русский 🇷🇺 
≠ 🇯🇵 日本語 = japanese"d).take(35).encode(); /// 日
        /// usage; eg: stringUGC32("äëåčñœß … russian = русский 🇷🇺 
≠ 🇯🇵 日本語 = japanese"d).takeasUTF(35); /// 日

        void popFront() { ++pintSequenceCurrent; }
        bool empty() { return pintSequenceCurrent == 
pintSequenceCount; }
        typeStringUTF front() { return 
takeasUTF(pintSequenceCurrent); }

        private stringUGC[] pugcSequence;
        private size_t pintSequenceCount = 0; @property public 
size_t count() { return pintSequenceCount; }
        private size_t pintSequenceCurrent = 0;

        this(
           const typeStringUTF lstrSequence
           ) {

           /// (1) given UTF‐encoded sequence

           this.decode(lstrSequence);

        }

        @safe public size_t decode( /// UniCode (UTF‐encoded → 
grapheme‐cluster) sequence
           const typeStringUTF lstrSequence
           ) {

           /// (1) given UTF‐encoded sequence

           size_t lintSequenceCount = 0;

           if (lstrSequence is null) {

              pugcSequence = null;
              pintSequenceCount = 0;
              pintSequenceCurrent = 0;

           } else {

              pugcSequence = lstrSequence.byGrapheme.array;
              pintSequenceCount = pugcSequence.walkLength;
              pintSequenceCurrent = 1;

              lintSequenceCount = pintSequenceCount;

           }

           return lintSequenceCount;

        }

        @safe public typeStringUTF encode() { /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence

           typeStringUTF lstrSequence = null;

           if (pintSequenceCount >= 1) {

              lstrSequence = pugcSequence
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 ;

           }

           return lstrSequence;

        }

        @safe public gudtUGC!(typeStringUTF) take( /// UniCode 
(grapheme‐cluster → grapheme‐cluster) sequence
           const size_t lintStart,
           const size_t lintCount = 1
           ) {

           /// (1) given start position >= 1
           /// (2) given count >= 1

           gudtUGC!(typeStringUTF) lugcSequence;

           if (lintStart >= 1 && lintCount >= 1) {

              /// eg#1: takeasUTF(1,3) → range#1=start-1=1-1=0 and 
range#2=range#1+count=0+3=3 → 0..3
              /// eg#1: takeasUTF(6,3) → range#2=start-1=6-1=5 and 
range#2=range#1+count=5+3=8 → 5..8

              /// eg#2: takeasUTF(01,1) → range#1=start-1=01-1=00 
and range#2=range#1+count=00+1=01 → 00..01
              /// eg#2: takeasUTF(50,1) → range#2=start-1=50-1=49 
and range#2=range#1+count=49+1=50 → 49..50

              size_t lintRange1 = lintStart - 1;
              size_t lintRange2 = lintRange1 + lintCount;

              if (lintRange2 <= pintSequenceCount) {

                 lugcSequence = 
gudtUGC!(typeStringUTF)(pugcSequence[lintRange1..lintRange2]
                    .map!((ref g) => g[])
                    .joiner
                    .to!(typeStringUTF)
                    );

              }

           }

           return lugcSequence;

        }

        @safe public gudtUGC!(typeStringUTF) takeL( /// UniCode 
(grapheme‐cluster → grapheme‐cluster) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           gudtUGC!(typeStringUTF) lugcSequence;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lugcSequence = gudtUGC!(typeStringUTF)(pugcSequence
                 .take(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 );

           }

           return lugcSequence;

        }

        @safe public gudtUGC!(typeStringUTF) takeR( /// UniCode 
(grapheme‐cluster → grapheme‐cluster) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           gudtUGC!(typeStringUTF) lugcSequence;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lugcSequence = gudtUGC!(typeStringUTF)(pugcSequence
                 .tail(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 );

           }

           return lugcSequence;

        }

        @safe public gudtUGC!(typeStringUTF) chopL( /// UniCode 
(grapheme‐cluster → grapheme‐cluster) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           gudtUGC!(typeStringUTF) lugcSequence;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lugcSequence = gudtUGC!(typeStringUTF)(pugcSequence
                 .drop(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 );

           }

           return lugcSequence;

        }

        @safe public gudtUGC!(typeStringUTF) chopR( /// UniCode 
(grapheme‐cluster → grapheme‐cluster) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           gudtUGC!(typeStringUTF) lugcSequence;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lugcSequence = gudtUGC!(typeStringUTF)(pugcSequence
                 .dropBack(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 );

           }

           return lugcSequence;

        }

        @safe public typeStringUTF takeasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintStart,
           const size_t lintCount = 1
           ) {

           /// (1) given start position >= 1
           /// (2) given count >= 1

           typeStringUTF lstrSequence = null;

           if (lintStart >= 1 && lintCount >= 1) { /// eg: see 
take()

              size_t lintRange1 = lintStart - 1;
              size_t lintRange2 = lintRange1 + lintCount;

              if (lintRange2 <= pintSequenceCount) {

                 lstrSequence = 
pugcSequence[lintRange1..lintRange2]
                    .map!((ref g) => g[])
                    .joiner
                    .to!(typeStringUTF)
                    ;

              }

           }

           return lstrSequence;

        }

        @safe public typeStringUTF takeLasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lstrSequence = pugcSequence
                 .take(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 ;

           }

           return lstrSequence;

        }

        @safe public typeStringUTF takeRasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lstrSequence = pugcSequence
                 .tail(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 ;

           }

           return lstrSequence;

        }

        @safe public typeStringUTF chopLasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lstrSequence = pugcSequence
                 .drop(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 ;

           }

           return lstrSequence;

        }

        @safe public typeStringUTF chopRasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount
           ) {

           /// (1) given count >= 1

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount <= pintSequenceCount) {

              lstrSequence = pugcSequence
                 .dropBack(lintCount)
                 .map!((ref g) => g[])
                 .joiner
                 .to!(typeStringUTF)
                 ;

           }

           return lstrSequence;

        }

        @safe public typeStringUTF padLasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount,
           const typeStringUTF lstrPadding = r" "
           ) {

           /// (1) given count >= 1
           /// [2] given padding (default is a single blank space)

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount > pintSequenceCount) {

              lstrSequence = null; /// pending

           }

           return lstrSequence;

        }

        @safe public typeStringUTF padRasUTF( /// UniCode 
(grapheme‐cluster → UTF‐encoded) sequence
           const size_t lintCount,
           const typeStringUTF lstrPadding = r" "
           ) {

           /// (1) given count >= 1
           /// [2] given padding (default is a single blank space)

           typeStringUTF lstrSequence = null;

           if (lintCount >= 1 && lintCount > pintSequenceCount) {

              lstrSequence = null; /// pending

           }

           return lstrSequence;

        }

}

unittest {

        void testUTFcommon( /// the following should be the same 
(regardless of the encoding being used) and is the whole point of 
this UDT being made:
           typeStringUTF,
           typeStringUGC
           )(
           const typeStringUTF lstrSequence3
           ) {

           typeStringUGC lugcSequence3 = 
typeStringUGC(lstrSequence3);

           with (lugcSequence3) {

              assert(encode() == lstrSequence3);

              assert(take(35, 3).take(1,2).take(1,1).encode() == 
r"日");

              assert(take(21).encode() == r"р");
              assert(take(27).encode() == r"й");
              assert(take(35).encode() == r"日");
              assert(take(37).encode() == r"語");
              assert(take(21, 7).encode() == r"русский");
              assert(take(35, 3).encode() == r"日本語");

              assert(takeasUTF(21) == r"р");
              assert(takeasUTF(27) == r"й");
              assert(takeasUTF(35) == r"日");
              assert(takeasUTF(37) == r"語");
              assert(takeasUTF(21, 7) == r"русский");
              assert(takeasUTF(35, 3) == r"日本語");

              assert(takeL(1).encode() == r"ä");
              assert(takeR(1).encode() == r"😎");
              assert(takeL(7).encode() == r"äëåčñœß");
              assert(takeR(16).encode() == r"日本語 = japanese 😎");

              assert(takeLasUTF(1) == r"ä");
              assert(takeRasUTF(1) == r"😎");
              assert(takeLasUTF(7) == r"äëåčñœß");
              assert(takeRasUTF(16) == r"日本語 = japanese 😎");

              assert(chopL(10).encode() == r"russian = русский 🇷🇺 ≠ 
🇯🇵 日本語 = japanese 😎");
              assert(chopR(21).encode() == r"äëåčñœß … russian = 
русский 🇷🇺");

              assert(chopLasUTF(10) == r"russian = русский 🇷🇺 ≠ 🇯🇵 
日本語 = japanese 😎");
              assert(chopRasUTF(21) == r"äëåčñœß … russian = 
русский 🇷🇺");

           }

           typeStringUTF lstrSequence3reencoded;

           for (
              size_t lintSequenceUGC = 1;
              lintSequenceUGC <= 
lstrSequence3.byGrapheme.walkLength;
              ++lintSequenceUGC
              ) {

              lstrSequence3reencoded ~= 
lugcSequence3.takeasUTF(lintSequenceUGC);

           }

           assert(lstrSequence3reencoded == lstrSequence3);

           lstrSequence3reencoded = null;

           foreach (typeStringUTF lstrSequence3UGC; lugcSequence3) 
{ lstrSequence3reencoded ~= lstrSequence3UGC; }

           //assert(lstrSequence3reencoded == lstrSequence3); /// 
ooops … always missing last grapheme‐cluster: possible bug # 20483

        }

        void testUTF08(
           const stringUTF08 lstrSequence1,
           const stringUTF08 lstrSequence2,
           const stringUTF08 lstrSequence3
           ) {

           assert(lstrSequence1.byGrapheme.walkLength == 50); /// 
checking UGC sizes; ie grapheme‐cluster count
           assert(lstrSequence2.byGrapheme.walkLength == 50);
           assert(lstrSequence3.byGrapheme.walkLength == 50);

           assert(lstrSequence1.walkLength == 50); /// checking 
UGA sizes; ie code‐point count
           assert(lstrSequence2.walkLength == 50);
           assert(lstrSequence3.walkLength == 52);

           assert(lstrSequence1.length == 50); /// checking UTF 
sizes; ie code‐unit count
           assert(lstrSequence2.length == 60);
           assert(lstrSequence3.length == 91);

           testUTFcommon!(stringUTF08, 
stringUGC08)(lstrSequence3); /// checking for correct string 
manipulation

        }

        void testUTF16(
           const stringUTF16 lstrSequence1,
           const stringUTF16 lstrSequence2,
           const stringUTF16 lstrSequence3
           ) {

           assert(lstrSequence1.byGrapheme.walkLength == 50); /// 
checking UGC sizes; ie grapheme‐cluster count
           assert(lstrSequence2.byGrapheme.walkLength == 50);
           assert(lstrSequence3.byGrapheme.walkLength == 50);

           assert(lstrSequence1.walkLength == 50); /// checking 
UGA sizes; ie code‐point count
           assert(lstrSequence2.walkLength == 50);
           assert(lstrSequence3.walkLength == 52);

           assert(lstrSequence1.length == 50); /// checking UTF 
sizes; ie code‐unit count
           assert(lstrSequence2.length == 50);
           assert(lstrSequence3.length == 57);

           testUTFcommon!(stringUTF16, 
stringUGC16)(lstrSequence3); /// checking for correct string 
manipulation

        }

        void testUTF32(
           const stringUTF32 lstrSequence1,
           const stringUTF32 lstrSequence2,
           const stringUTF32 lstrSequence3
           ) {

           assert(lstrSequence1.byGrapheme.walkLength == 50); /// 
checking UGC sizes; ie grapheme‐cluster count
           assert(lstrSequence2.byGrapheme.walkLength == 50);
           assert(lstrSequence3.byGrapheme.walkLength == 50);

           assert(lstrSequence1.walkLength == 50); /// checking 
UGA sizes; ie code‐point count
           assert(lstrSequence2.walkLength == 50);
           assert(lstrSequence3.walkLength == 52);

           assert(lstrSequence1.length == 50); /// checking UTF 
sizes; ie code‐unit count
           assert(lstrSequence2.length == 50);
           assert(lstrSequence3.length == 52);

           testUTFcommon!(stringUTF32, 
stringUGC32)(lstrSequence3); /// checking for correct string 
manipulation

        }

        testUTF08(
           r"12345678901234567890123456789012345678901234567890"c,
           r"1234567890АВГДЕЗИЙКЛABCDEFGHIJabcdefghijQRSTUVWXYZ"c,
           r"äëåčñœß … russian = русский 🇷🇺 ≠ 🇯🇵 日本語 = japanese 😎"c
           );

        testUTF16(
           r"12345678901234567890123456789012345678901234567890"w,
           r"1234567890АВГДЕЗИЙКЛABCDEFGHIJabcdefghijQRSTUVWXYZ"w,
           r"äëåčñœß … russian = русский 🇷🇺 ≠ 🇯🇵 日本語 = japanese 😎"w
           );

        testUTF32(
           r"12345678901234567890123456789012345678901234567890"d,
           r"1234567890АВГДЕЗИЙКЛABCDEFGHIJabcdefghijQRSTUVWXYZ"d,
           r"äëåčñœß … russian = русский 🇷🇺 ≠ 🇯🇵 日本語 = japanese 😎"d
           );

        //stringUGC32 lugcSequence3 = stringUGC32(cast(char) 'x');
        //stringUGC32 lugcSequence3 = stringUGC32(1);

}
```



More information about the Digitalmars-d-learn mailing list