Thread overview
'in' storage class
Sep 05, 2007
Funog
Sep 05, 2007
Nathan Reed
Sep 05, 2007
Funog
Sep 05, 2007
Nathan Reed
Sep 05, 2007
Funog
Sep 05, 2007
Robert Fraser
Sep 06, 2007
Funog
Sep 06, 2007
Jason House
Sep 08, 2007
torhu
September 05, 2007
'in' is equivalent to final const scope.
I can't understand the point of making the variable 'final' if it's already 'const' ?

September 05, 2007
Funog wrote:
> 'in' is equivalent to final const scope.
> I can't understand the point of making the variable 'final' if it's already 'const' ?
> 

In D 2.0, 'final' represents 'head-const', while 'const' means 'tail-const'.  This makes a difference when talking about arrays: 'final' will make the array reference itself const, so you can't change it to refer to a different array, while 'const' makes the contents of the array const - you can change the variable to point to another array or slice, but you can't edit any array through that reference.

Thanks,
Nathan Reed
September 05, 2007
Nathan Reed Wrote:

> Funog wrote:
> > 'in' is equivalent to final const scope.
> > I can't understand the point of making the variable 'final' if it's already 'const' ?
> > 
> 
> In D 2.0, 'final' represents 'head-const', while 'const' means 'tail-const'.  This makes a difference when talking about arrays: 'final' will make the array reference itself const, so you can't change it to refer to a different array, while 'const' makes the contents of the array const - you can change the variable to point to another array or slice, but you can't edit any array through that reference.
> 
> Thanks,
> Nathan Reed



It's true for const(uint[]) or const(uint)[], but we are talking of const uint[], which forbid any change.



void testFinal(final int[] foo)
{
    foo[0] = 10;        //OK
    foo = new int[20];  //ERROR
}
void testConst(const int[] foo)
{
    foo[0] = 10;        //ERROR
    foo = new int[20];  //ERROR
}
void testFinalConst(final const int[] foo)
{
    foo[0] = 10;        //ERROR
    foo = new int[20];  //ERROR
}


So what is the difference between 'const' and 'final const' ?

September 05, 2007
Funog wrote:
> void testFinal(final int[] foo)
> {
>     foo[0] = 10;        //OK
>     foo = new int[20];  //ERROR
> }
> void testConst(const int[] foo)
> {
>     foo[0] = 10;        //ERROR
>     foo = new int[20];  //ERROR
> }
> void testFinalConst(final const int[] foo)
> {
>     foo[0] = 10;        //ERROR
>     foo = new int[20];  //ERROR
> }
> 
> 
> So what is the difference between 'const' and 'final const' ?
> 

I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.

Thanks,
Nathan Reed
September 05, 2007
Nathan Reed Wrote:

> Funog wrote:
> > void testFinal(final int[] foo)
> > {
> >     foo[0] = 10;        //OK
> >     foo = new int[20];  //ERROR
> > }
> > void testConst(const int[] foo)
> > {
> >     foo[0] = 10;        //ERROR
> >     foo = new int[20];  //ERROR
> > }
> > void testFinalConst(final const int[] foo)
> > {
> >     foo[0] = 10;        //ERROR
> >     foo = new int[20];  //ERROR
> > }
> > 
> > 
> > So what is the difference between 'const' and 'final const' ?
> > 
> 
> I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.
> 
> Thanks,
> Nathan Reed



I agree... But then, what is the point of having 'in' equivalent to 'final const scope' rather than just 'const scope' ?

September 05, 2007
Funog Wrote:

> Nathan Reed Wrote:
> 
> > Funog wrote:
> > > void testFinal(final int[] foo)
> > > {
> > >     foo[0] = 10;        //OK
> > >     foo = new int[20];  //ERROR
> > > }
> > > void testConst(const int[] foo)
> > > {
> > >     foo[0] = 10;        //ERROR
> > >     foo = new int[20];  //ERROR
> > > }
> > > void testFinalConst(final const int[] foo)
> > > {
> > >     foo[0] = 10;        //ERROR
> > >     foo = new int[20];  //ERROR
> > > }
> > > 
> > > 
> > > So what is the difference between 'const' and 'final const' ?
> > > 
> > 
> > I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.
> > 
> > Thanks,
> > Nathan Reed
> 
> 
> 
> I agree... But then, what is the point of having 'in' equivalent to 'final const scope' rather than just 'const scope' ?
> 

The difference is easier for me to grasp when talking about class references than arrays.

class Foo { int bar; }

final Foo baz;
baz.bar = 5; // Okay
baz = quux; // Illegal

const Foo quux; // Equivilent, I _think_ to const(Foo) quux;
quux.bar = 5; // Illegal
quux = baz; //Okay

In other words, for a class reference, head-const (final) means that the reference can't be changed to point to something else, but the data can be changed. Head-const is not transitive. Tail-const (const or invariant, in the case of a class reference) means that the thing being pointed to cannot be changed, but the reference can be.

This is generalized to array references and pointers.
September 06, 2007
Robert Fraser Wrote:

> Funog Wrote:
> 
> > Nathan Reed Wrote:
> > 
> > > Funog wrote:
> > > > void testFinal(final int[] foo)
> > > > {
> > > >     foo[0] = 10;        //OK
> > > >     foo = new int[20];  //ERROR
> > > > }
> > > > void testConst(const int[] foo)
> > > > {
> > > >     foo[0] = 10;        //ERROR
> > > >     foo = new int[20];  //ERROR
> > > > }
> > > > void testFinalConst(final const int[] foo)
> > > > {
> > > >     foo[0] = 10;        //ERROR
> > > >     foo = new int[20];  //ERROR
> > > > }
> > > > 
> > > > 
> > > > So what is the difference between 'const' and 'final const' ?
> > > > 
> > > 
> > > I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.
> > > 
> > > Thanks,
> > > Nathan Reed
> > 
> > 
> > 
> > I agree... But then, what is the point of having 'in' equivalent to 'final const scope' rather than just 'const scope' ?
> > 
> 
> The difference is easier for me to grasp when talking about class references than arrays.
> 
> class Foo { int bar; }
> 
> final Foo baz;
> baz.bar = 5; // Okay
> baz = quux; // Illegal
> 
> const Foo quux; // Equivilent, I _think_ to const(Foo) quux;
> quux.bar = 5; // Illegal
> quux = baz; //Okay
> 


It isn't... Both lines are illegal. quux = baz is legal for const(Foo) quux.
If nobody can tell the difference between "const scope" and "in" ( = final const scope ), should we report it as a bug ? xD

September 06, 2007
Funog wrote:
> Robert Fraser Wrote:
> 
>> Funog Wrote:
>>
>>> Nathan Reed Wrote:
>>>
>>>> Funog wrote:
>>>>> void testFinal(final int[] foo)
>>>>> {
>>>>>     foo[0] = 10;        //OK
>>>>>     foo = new int[20];  //ERROR
>>>>> }
>>>>> void testConst(const int[] foo)
>>>>> {
>>>>>     foo[0] = 10;        //ERROR
>>>>>     foo = new int[20];  //ERROR
>>>>> }
>>>>> void testFinalConst(final const int[] foo)
>>>>> {
>>>>>     foo[0] = 10;        //ERROR
>>>>>     foo = new int[20];  //ERROR
>>>>> }
>>>>>
>>>>>
>>>>> So what is the difference between 'const' and 'final const' ?
>>>>>
>>>> I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.
>>>>
>>>> Thanks,
>>>> Nathan Reed
>>>
>>>
>>> I agree... But then, what is the point of having 'in' equivalent to 'final const scope' rather than just 'const scope' ?
>>>
>> The difference is easier for me to grasp when talking about class references than arrays.
>>
>> class Foo { int bar; }
>>
>> final Foo baz;
>> baz.bar = 5; // Okay
>> baz = quux; // Illegal
>>
>> const Foo quux; // Equivilent, I _think_ to const(Foo) quux;
>> quux.bar = 5; // Illegal
>> quux = baz; //Okay
>>
> 
> 
> It isn't... Both lines are illegal. quux = baz is legal for const(Foo) quux.
> If nobody can tell the difference between "const scope" and "in" ( = final const scope ), should we report it as a bug ? xD
> 

If I understand stuff right, "quux = baz;" should be legal.  Use of quux thereafter, including reassigning quux, does not invalidate baz's use of final.  I have not tested this with a compiler, of course...
September 08, 2007
Funog wrote:
> Robert Fraser Wrote:
> 
>> Funog Wrote:
>> 
>> > Nathan Reed Wrote:
>> > 
>> > > Funog wrote:
>> > > > void testFinal(final int[] foo)
>> > > > {
>> > > >     foo[0] = 10;        //OK
>> > > >     foo = new int[20];  //ERROR
>> > > > }
>> > > > void testConst(const int[] foo)
>> > > > {
>> > > >     foo[0] = 10;        //ERROR
>> > > >     foo = new int[20];  //ERROR
>> > > > }
>> > > > void testFinalConst(final const int[] foo)
>> > > > {
>> > > >     foo[0] = 10;        //ERROR
>> > > >     foo = new int[20];  //ERROR
>> > > > }
>> > > > 
>> > > > 
>> > > > So what is the difference between 'const' and 'final const' ?
>> > > > 
>> > > 
>> > > I suppose there's no practical difference in that case since you're using the transitive const.  Note that final const(int)[] foo is different from const(int)[] foo though.
>> > > 
>> > > Thanks,
>> > > Nathan Reed
>> > 
>> > 
>> > 
>> > I agree... But then, what is the point of having 'in' equivalent to 'final const scope' rather than just 'const scope' ?
>> > 
>> 
>> The difference is easier for me to grasp when talking about class references than arrays.
>> 
>> class Foo { int bar; }
>> 
>> final Foo baz;
>> baz.bar = 5; // Okay
>> baz = quux; // Illegal
>> 
>> const Foo quux; // Equivilent, I _think_ to const(Foo) quux;
>> quux.bar = 5; // Illegal
>> quux = baz; //Okay
>> 
> 
> 
> It isn't... Both lines are illegal. quux = baz is legal for const(Foo) quux.
> If nobody can tell the difference between "const scope" and "in" ( = final const scope ), should we report it as a bug ? xD
> 

I tried this:

---
void f(const int* p)
{
	int y = 9;
	
	*p = 7;	 // line 5
	p = &y;  // line 6
}

void main()
{
	int x = 5;

	f(&x);
}
---
dmd -run inargs
inargs.d(5): Error: *p is not mutable
inargs.d(6): variable inargs.f.p cannot modify final/const/invariant variable 'p'


Adding 'final' doesn't change anything.  So it would seem that this feature isn't finalized yet.  'scope' doesn't seem to work either.  If I use 'final const(int)*' instead, I get the same errors.

Barring optimizations, a function's arguments are not known a compile-time.  So I don't know if giving them the const or invariant storage class makes much sense.  Maybe the idea was that const in a parameter list would always mean const as a type constructor.  For other declarations, 'final const(int)*' allows run-time (by a constructor) initialization, while 'const int*' does not.  So maybe the latter one should be disallowed in parameter lists.