Thread overview
Throwing exception in constructor
Aug 16, 2011
Stijn Herreman
Aug 16, 2011
Vijay Nayar
Aug 16, 2011
Stijn Herreman
Aug 16, 2011
Timon Gehr
Aug 16, 2011
Vijay Nayar
Aug 16, 2011
Stijn Herreman
August 16, 2011
Why is the return statement required, while nothing after the Exception is executed?
Error: one path skips constructor

	public this(string p1, string p2, string p3)
	{
		string json = download_string(...);
		
		if (json is null)
		{
			throw new Exception("404");
			writeln("test");
			return;
		}
		else
		{
			this(json);
		}
	}
	
	package this(string json)
	{
		...
	}
August 16, 2011
On Tue, 16 Aug 2011 19:08:53 +0200, Stijn Herreman wrote:

> Why is the return statement required, while nothing after the Exception
> is executed?
> Error: one path skips constructor
> 
> 	public this(string p1, string p2, string p3) {
> 		string json = download_string(...);
> 
> 		if (json is null)
> 		{
> 			throw new Exception("404");
> 			writeln("test");
> 			return;
> 		}
> 		else
> 		{
> 			this(json);
> 		}
> 	}
> 
> 	package this(string json)
> 	{
> 		...
> 	}

What compiler are you using?  Using DMD2 (DMD32 D Compiler v2.054), I have no problem with the example below.  I suspect the problem may not have anything to do with return statements.

import std.stdio;
import std.conv;

class Hambo {
    public int _value;

    public this(string value) {
        this(to!int(value));
    }

    public this(int value) {
        if (value < 10) {
            throw new Exception("Not high enough.");
        } else {
            _value = value;
        }
    }
}

void main() {
    // Throws: object.Exception@constructor.d(13): Not high enough.
    //Hambo ham1 = new Hambo("4");
    Hambo ham2 = new Hambo("14");
    writeln(ham2._value);
}
August 16, 2011
On 08/16/2011 07:08 PM, Stijn Herreman wrote:
> Why is the return statement required, while nothing after the Exception
> is executed?
> Error: one path skips constructor
>
> public this(string p1, string p2, string p3)
> {
> string json = download_string(...);
>
> if (json is null)
> {
> throw new Exception("404");
> writeln("test");
> return;
> }
> else
> {
> this(json);
> }
> }
>
> package this(string json)
> {
> ...
> }

The Exception has no influence, the following code will still get the error:

class JSON{
    public this(string p1, string p2, string p3)
    {
        string json = download_string(...);

        if (json is null)
        {
            ...
        }
        else
        {
            this(json);
        }
    }

    this(string json)
    {
        ...
    }
}

This is afaik by design (described somewhere in TDPL). The idea is that a constructor can either construct the value itself in all code paths or delegate construction to another constructor in all code paths. The fact that the code compiles with return but not with throw is probably a bug.
August 16, 2011
On 16/08/2011 19:24, Vijay Nayar wrote:
> On Tue, 16 Aug 2011 19:08:53 +0200, Stijn Herreman wrote:
>
>> Why is the return statement required, while nothing after the Exception
>> is executed?
>> Error: one path skips constructor
>>
>> 	public this(string p1, string p2, string p3) {
>> 		string json = download_string(...);
>> 		
>> 		if (json is null)
>> 		{
>> 			throw new Exception("404");
>> 			writeln("test");
>> 			return;
>> 		}
>> 		else
>> 		{
>> 			this(json);
>> 		}
>> 	}
>> 	
>> 	package this(string json)
>> 	{
>> 		...
>> 	}
>
> What compiler are you using?  Using DMD2 (DMD32 D Compiler v2.054), I
> have no problem with the example below.  I suspect the problem may not
> have anything to do with return statements.
>
> import std.stdio;
> import std.conv;
>
> class Hambo {
>      public int _value;
>
>      public this(string value) {
>          this(to!int(value));
>      }
>
>      public this(int value) {
>          if (value<  10) {
>              throw new Exception("Not high enough.");
>          } else {
>              _value = value;
>          }
>      }
> }
>
> void main() {
>      // Throws: object.Exception@constructor.d(13): Not high enough.
>      //Hambo ham1 = new Hambo("4");
>      Hambo ham2 = new Hambo("14");
>      writeln(ham2._value);
> }
It happens only when chaining constructors.

Doesn't compile:
class Hambo {
    public int _value;

    public this(string value) {
		if (value == "") {
			throw new Exception("Empty.");
		} else {
			this(to!int(value));
		}
    }

    public this(int value) {
        if (value < 10) {
            throw new Exception("Not high enough.");
        } else {
            _value = value;
        }
    }
}

Compiles:
class Hambo {
    public int _value;

    public this(string value) {
		if (value == "") {
			throw new Exception("Empty.");
			return;
		} else {
			this(to!int(value));
		}
    }

    public this(int value) {
        if (value < 10) {
            throw new Exception("Not high enough.");
        } else {
            _value = value;
        }
    }
}

Compiles:
class Hambo {
    public int _value;

    public this(string value) {
		if (value == "") {
			throw new Exception("Empty.");
		}
    }

    public this(int value) {
        if (value < 10) {
            throw new Exception("Not high enough.");
        } else {
            _value = value;
        }
    }
}
August 16, 2011
On Tue, 16 Aug 2011 19:33:06 +0200, Timon Gehr wrote:

> On 08/16/2011 07:08 PM, Stijn Herreman wrote:
>> Why is the return statement required, while nothing after the Exception
>> is executed?
>> Error: one path skips constructor
>>
>> public this(string p1, string p2, string p3) {
>> string json = download_string(...);
>>
>> if (json is null)
>> {
>> throw new Exception("404");
>> writeln("test");
>> return;
>> }
>> else
>> {
>> this(json);
>> }
>> }
>>
>> package this(string json)
>> {
>> ...
>> }
> 
> The Exception has no influence, the following code will still get the error:
> 
> class JSON{
>      public this(string p1, string p2, string p3) {
>          string json = download_string(...);
> 
>          if (json is null)
>          {
>              ...
>          }
>          else
>          {
>              this(json);
>          }
>      }
> 
>      this(string json)
>      {
>          ...
>      }
> }
> 
> This is afaik by design (described somewhere in TDPL). The idea is that a constructor can either construct the value itself in all code paths or delegate construction to another constructor in all code paths. The fact that the code compiles with return but not with throw is probably a bug.


Well I'll be a monkey's uncle.  I tried it out and sure enough you are correct.  I'm still reading TDPL, and now I'm curious to find the rationale.

   public this(string value) {
        if (value == "Hambo") {
            _value = 999;
        } else {
            this(to!int(value));
        }
    }
August 16, 2011
On 16/08/2011 19:33, Timon Gehr wrote:
> On 08/16/2011 07:08 PM, Stijn Herreman wrote:
>> Why is the return statement required, while nothing after the Exception
>> is executed?
>> Error: one path skips constructor
>>
>> public this(string p1, string p2, string p3)
>> {
>> string json = download_string(...);
>>
>> if (json is null)
>> {
>> throw new Exception("404");
>> writeln("test");
>> return;
>> }
>> else
>> {
>> this(json);
>> }
>> }
>>
>> package this(string json)
>> {
>> ...
>> }
>
> The Exception has no influence, the following code will still get the
> error:
>
> class JSON{
> public this(string p1, string p2, string p3)
> {
> string json = download_string(...);
>
> if (json is null)
> {
> ...
> }
> else
> {
> this(json);
> }
> }
>
> this(string json)
> {
> ...
> }
> }
>
> This is afaik by design (described somewhere in TDPL). The idea is that
> a constructor can either construct the value itself in all code paths or
> delegate construction to another constructor in all code paths. The fact
> that the code compiles with return but not with throw is probably a bug.
I found the passage you mentioned, you are correct.
I don't, however, understand the reason behind this design.