Thread overview
Strange error when compiling with dmd, not with ldc
Nov 29, 2017
Fra Mecca
Nov 29, 2017
user1234
Nov 29, 2017
user1234
November 29, 2017
I have this struct:

immutable struct Configuration {
    string title;
    string baseurl;
    string url;
    string email;
    string author;
    string parser;
    string target;
    string urlFormat;
    string urlFormatCmd;

    short port;

    string[] ignore;
    string[] extensions;

    @property string toString()
    {
        auto urlF = (urlFormatCmd ? "url_format_cmd: " ~ urlFormatCmd : "") ~ "\n";
        return
        "title: "        ~ title ~ "\n" ~
        "baseurl: "      ~ baseurl ~ "\n" ~
        "url: "          ~ url ~ "\n" ~
        "email: "        ~ email ~ "\n" ~
        "author: "       ~ author ~ "\n" ~
        "parser: "       ~ parser ~ "\n" ~
        "target: "       ~ target ~ "\n" ~
        "url_format: "   ~ urlFormat ~ "\n" ~
        "ignore: "       ~ to!string(ignore)[1 .. $ - 1] ~ "\n" ~
        "extensions: "   ~ to!string(extensions)[1 .. $ - 1] ~ "\n" ~
        urlF;
    }
}

and this function:

void show_config()
{
    writef("%s", parse_config(
                exists("config.sdl") ? "config.sdl" : "").toString);
}


Whenever I compile with ldc2 I get no errors, while with dmd I get:

source/configuration.d(105,27): Error: immutable method configuration.Configuration.toString is not callable using a mutable object


What is the problem?
November 29, 2017
On Wednesday, 29 November 2017 at 06:18:09 UTC, Fra Mecca wrote:
> I have this struct:
>
> immutable struct Configuration {
>     string title;
>     string baseurl;
>     string url;
>     string email;
>     string author;
>     string parser;
>     string target;
>     string urlFormat;
>     string urlFormatCmd;
>
>     short port;
>
>     string[] ignore;
>     string[] extensions;
>
>     @property string toString()
>     {
>         auto urlF = (urlFormatCmd ? "url_format_cmd: " ~ urlFormatCmd : "") ~ "\n";
>         return
>         "title: "        ~ title ~ "\n" ~
>         "baseurl: "      ~ baseurl ~ "\n" ~
>         "url: "          ~ url ~ "\n" ~
>         "email: "        ~ email ~ "\n" ~
>         "author: "       ~ author ~ "\n" ~
>         "parser: "       ~ parser ~ "\n" ~
>         "target: "       ~ target ~ "\n" ~
>         "url_format: "   ~ urlFormat ~ "\n" ~
>         "ignore: "       ~ to!string(ignore)[1 .. $ - 1] ~ "\n" ~
>         "extensions: "   ~ to!string(extensions)[1 .. $ - 1] ~ "\n" ~
>         urlF;
>     }
> }
>
> and this function:
>
> void show_config()
> {
>     writef("%s", parse_config(
>                 exists("config.sdl") ? "config.sdl" : "").toString);
> }
>
>
> Whenever I compile with ldc2 I get no errors, while with dmd I get:
>
> source/configuration.d(105,27): Error: immutable method configuration.Configuration.toString is not callable using a mutable object
>
>
> What is the problem?

You must also use a type constructor later, when a Configuration is declared:

```
immutable(Configuration) config;
config.toString.writeln; // okay this time
```

What happens is that all the member functions have the `immutable` attribute, but the instance you declared was not itself `immutable`.

actually this:

```
immutable struct Configuration {
    @property string toString(){return "";}
}
```

is like:

```
struct Configuration {
    @property string toString() immutable {return "";}
}
```

I would personally prefer the second form. Why ? Because the variable members will be set immutable anyway when an instance is declared.
November 29, 2017
On Wednesday, 29 November 2017 at 10:55:35 UTC, user1234 wrote:
> On Wednesday, 29 November 2017 at 06:18:09 UTC, Fra Mecca wrote:
>> [...]
>
> You must also use a type constructor later, when a Configuration is declared:
>
> ```
> immutable(Configuration) config;
> config.toString.writeln; // okay this time
> ```
>
> What happens is that all the member functions have the `immutable` attribute, but the instance you declared was not itself `immutable`.
>
> actually this:
>
> ```
> immutable struct Configuration {
>     @property string toString(){return "";}
> }
> ```
>
> is like:
>
> ```
> struct Configuration {
>     @property string toString() immutable {return "";}
> }
> ```
>
> I would personally prefer the second form. Why ? Because the variable members will be set immutable anyway when an instance is declared.

And about the DMD vs LDC thing, i thing that the difference can be simply explained by the fact that LDC uses a slightly older compiler front end version, meaning that after 1 or 2 updates, the same error would happen.

Now i don't know which change in particular has been made recently in the front-end. Maybe the semantic of the leading qualifier when "immutable struct {}" is used but i would bet too much on that.