Search code examples
ddynamic-typing

why D's variant seems confusing


I experiment with the D language, and find the std.variant cool.

But then I find it confusing.

For example,

import std.stdio;
void main()
{
  string x = "";
  x ~= 'v';
  writeln(x);
}

This does what is expected.

But this,

import std.stdio;
import std.variant;
void main()
{
  Variant x = "";
  x ~= 'v';
  writeln(x);
}

gives a hard-to-decipher RUNTIME error.

Why is that?

Here is the message.

std.variant.VariantException@std/variant.d(1675): Variant: attempting to use incompatible types char and immutable(char)[]
----------------
??:? inout @property inout(immutable(char)[]) std.variant.VariantN!(32uL).VariantN.get!(immutable(char)[]).get() [0x106f84654]
??:? long std.variant.VariantN!(32uL).VariantN.handler!(immutable(char)[]).handler(std.variant.VariantN!(32uL).VariantN.OpID, ubyte[32]*, void*) [0x106f7559d]
??:? std.variant.VariantN!(32uL).VariantN std.variant.VariantN!(32uL).VariantN.opOpAssign!("~", char).opOpAssign(char) [0x106f84a1d]
??:? _Dmain [0x106f74d8d]

Solution

  • This seems like a bug in std.variant.Variant. The problem here is char and immutable(char) are two different types, and Variant doesn't know that they're closely related. There are two different workaround to this: Either make x hold a char[] instead of immutable(char)[] (also known as string), or make 'v' an immutable(char):

    import std.stdio;
    import std.variant;
    void main()
    {
      Variant x = "".dup; // Duplicate the string to make it a heap-allocated, mutable string.
      x ~= 'v';
      writeln(x);
    }
    

    or

    import std.stdio;
    import std.variant;
    void main()
    {
      Variant x = "";
      x ~= cast(immutable)'v'; // Make 'v' explicitly immutable.
      writeln(x);
    }