How to initialize immutable variables with an expression that throws an exception to catch?

Steven Schveighoffer schveiguy at gmail.com
Fri Apr 3 14:12:06 UTC 2020


On 4/3/20 9:21 AM, Atila Neves wrote:
> On Friday, 3 April 2020 at 06:56:27 UTC, FeepingCreature wrote:
>> Consider the following code:
>>
>> struct S { }
>> ...
>>   S s = void;
>>   try
>>     s = fun();
>>   catch (Exception)
>>     return;
>>   call(s);
>>
>> Now you change S to be immutable.
>>
>> How are you supposed to initialize s? You can't assign to it anymore.
>>
>> Assume that we explicitly don't want to pull the call into the try 
>> body, for instance because we want exceptions from call to not be caught.
>>
>> The only way I've found is to make fun() return Algebraic!(S, 
>> Exception) but that's kind of ugly and bypasses a basic language feature.
>>
>> Maybe D could allow to initialize an immutable variable from the try{} 
>> body if the catch{} body is statically known to exit by return/throw?
> 
> --------------------
> immutable struct S { }
> 
> void main() {
>      S impl() {
>          try
>              return fun();
>          catch (Exception) {
>              S s = void;
>              return s;
>          }
>      }
> 
>      call(impl);
> }
> 
> 
> void call(S s) {
> 
> }
> 
> S fun() {
>      return S();
> }
> 
> --------------------

That's not the same. The original code does not call `call` with a 
void-initialized S.

However, this might do the trick:

void main() {
    bool voided = false;
    S impl() {
      try
          return fun();
      catch (Exception) {
          voided = true;
          S s = void;
          return s;
      }
    }
    auto s = impl();
    if(!voided) call(s);
}

But there is a catch here. Assigning an S to a void-initialized S is 
still copying stuff. It's not the same as never touching that memory.

-Steve


More information about the Digitalmars-d mailing list