Having __value class instance variables in __nogc classes

E

Edward Diener

Why is it impossible to have a __value class instance variable in a __nogc
class when it is possible to have a built-in type instance variable in a
__nogc class ?

__value class X { int a; };
__nogc class Y { X b; int c;}; // compiler error
__nogc class Y { int c;}; // OK
 
R

Ronald Laeremans [MSFT]

It _would_ be possible to allow this if the value type does not directly or
indirectly contain any ref types. But the language design made the choice to
simplify this by not allowing any cases.

Ronald Laeremans
Visual C++ team
 
T

Tomas Restrepo \(MVP\)

Hi Ronald,
It _would_ be possible to allow this if the value type does not directly or
indirectly contain any ref types. But the language design made the choice to
simplify this by not allowing any cases.

Alas, this isn't entirely true, as this simple example shows:

#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;

[ StructLayout(LayoutType::Sequential) ]
__value struct X { int a; };
__nogc class Y { X x; int c; };


So, obviously, the rule is not quite as simple as reyected in all cases.
AFAIK, the rules are closer to this: It is allowed iif:
- X has no members of ref types
- X has explicitly been declared as sequential layout (which should be
unnecessary, actually)
- X is declared in the same assembly as Y (or maybe the same translation
unit? haven't checked that in detail).

But yes, for all intented purposes, one should consider this as forbidden ;)
 
E

Edward Diener

Ronald said:
It _would_ be possible to allow this if the value type does not
directly or indirectly contain any ref types. But the language design
made the choice to simplify this by not allowing any cases.

I can understand the rule against having any ref types but I don't
understand the simplifying choice. I have found it often valuable in mixed
mode MC++ development for the __nogc class to have a fairly simple __value
object as a member of the class. It is disappointing that this is not
allowed especially as built-in types are __value classes themselves and
__nogc classes can, of course, have a built-in object.
 
E

Edward Diener

Tomas said:
Hi Ronald,
It _would_ be possible to allow this if the value type does not
directly or indirectly contain any ref types. But the language
design made the choice to simplify this by not allowing any cases.

Alas, this isn't entirely true, as this simple example shows:

#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;

[ StructLayout(LayoutType::Sequential) ]
__value struct X { int a; };
__nogc class Y { X x; int c; };


So, obviously, the rule is not quite as simple as reyected in all
cases. AFAIK, the rules are closer to this: It is allowed iif:

Thanks for the following clarification. I did find the discusssion about
this in Mr. Grimes' book pp. 107-108 when I looked again. Evidently I had
forgotten about this when I asked the question.
- X has no members of ref types
- X has explicitly been declared as sequential layout (which
should be unnecessary, actually)

It is unnecessary in VC 7.1 and it is my error in thinking that it was
necessary.
- X is declared in the same assembly as Y (or maybe the same
translation unit? haven't checked that in detail).

In the same assembly I believe. Richard Grimes points out in his book that
this is because of a bug in Visual C++. This is the case which occured in my
code which led me to believe that the restriction existed.
But yes, for all intented purposes, one should consider this as
forbidden ;)

Evidently the intent was to allow it in VC++ 7.1 but not in VC 7. However
the cross-assembly bug which Mr. Grimes' mentions does not allow it in VC++
7.1 also when the __value class and the __nogc type are in different
assemblies. Also in my testing, while I can embed a __value class in a
__nogc type within the same assembly, I can not embed a __value enum in a
__nogc type in the same assembly, which is really anomalous.

My suggestion is that this really neeeds to be cleaned up and that the VC++
compiler should allow __value classes/structs/enums to be embedded in a
__nogc class as long as the former does not have a __gc instance.
 
T

Tomas Restrepo \(MVP\)

Hi Edward,
I can understand the rule against having any ref types but I don't
understand the simplifying choice.

I think he might've meant simplifying it for the compiler development, not
necessarily the end user ;)
It ain't exactly all that trivial to check, since the check would need to be
recursive (remember Ronald pointed out it applied to direct _and_ indirect
containment of handles to managed ref types), so there are a few ugly cases
that would need to be cared for, making things more complex than necessary.

Then again, it's just mho, I might be just missing the point ;)
 
R

Ronald Laeremans [MSFT]

Yes, we let some stuff slip through. I was simplifying the simplification.
;-)

Ronald

Tomas Restrepo (MVP) said:
Hi Ronald,
It _would_ be possible to allow this if the value type does not directly or
indirectly contain any ref types. But the language design made the
choice
to
simplify this by not allowing any cases.

Alas, this isn't entirely true, as this simple example shows:

#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;

[ StructLayout(LayoutType::Sequential) ]
__value struct X { int a; };
__nogc class Y { X x; int c; };


So, obviously, the rule is not quite as simple as reyected in all cases.
AFAIK, the rules are closer to this: It is allowed iif:
- X has no members of ref types
- X has explicitly been declared as sequential layout (which should be
unnecessary, actually)
- X is declared in the same assembly as Y (or maybe the same translation
unit? haven't checked that in detail).

But yes, for all intented purposes, one should consider this as forbidden ;)
 
R

Ronald Laeremans [MSFT]

We are working on alternate ways to address this in the next release. I
don't think we have a final resolution yet on exactly what that will be.

Ronald
 
R

Ronald Laeremans [MSFT]

Some additional background:

The restriction of it needing to be in the same assembly of the current rule
is because we do not read metadata for private members, and so a ref type
could be hiding there.

And the restriction of needing sequential or explicit layout is because the
CLR decision to have all value types have sequential layout by default came
pretty late in the 7.0 cycle. We didn't consider any of this important
enough to revisit for 7.1.

Ronald
 
E

Edward Diener

Ronald said:
Some additional background:

The restriction of it needing to be in the same assembly of the
current rule is because we do not read metadata for private members,
and so a ref type could be hiding there.

I understand this, but the metadata for private members is generated, is it
not, so when the compiler sees an embedded __value type in a __nogc type
which exists in another assembly, it could read it ( and on recursively if
necessary ). Of course for non-embedded value types in a __nogc type it
doesn't need to do so.
And the restriction of needing sequential or explicit layout is
because the CLR decision to have all value types have sequential
layout by default came pretty late in the 7.0 cycle. We didn't
consider any of this important enough to revisit for 7.1.

This one seems easier. Since the default is sequential layout for value
types, the compiler should automatically know this. But in 7.1 it actually
does according to my tests as long as the value type is in the same
assembly, or did I miss something ?
 
E

Edward Diener

Ronald said:
Some additional background:

The restriction of it needing to be in the same assembly of the
current rule is because we do not read metadata for private members,
and so a ref type could be hiding there.

And the restriction of needing sequential or explicit layout is
because the CLR decision to have all value types have sequential
layout by default came pretty late in the 7.0 cycle. We didn't
consider any of this important enough to revisit for 7.1.

Why does a restriction also apply to variables of __value enum embedded in
__nogc types ? Clearly these follow neither the first explanation above,
about hidden ref types nor the second about sequential layout. Yet if I try
to embed a __value enum variable in a __nogc class the compiler gives me an
error saying that I can not do it.
 
R

Ronald Laeremans [MSFT]

Probably because we special cased value types and forgot about value enum
types.

Ronald
 
R

Ronald Laeremans [MSFT]

Yes, it could read the private meta data. I was just saying that we did not.

And we might have addressed the second issue in 7.1. My best recollection
was that we didn't.

Trying to find the edges of this might end up being frustrating though.

Ronald
 
E

Edward Diener

Ronald said:
Probably because we special cased value types and forgot about value
enum types.

Programmers, like elephants, never forget <g> .

I hope I have given enough for you to think about and fix in the next
release regarding this area.
 
E

Edward Diener

Ronald said:
Yes, it could read the private meta data. I was just saying that we
did not.

And we might have addressed the second issue in 7.1. My best
recollection was that we didn't.

Trying to find the edges of this might end up being frustrating
though.

Seems pretty clearcut to me, at least what should be done, to make it easier
to use __nogc and __value types together. A difficult issue should never be
an excuse for not being creative enough. Please revisit this issue for the
next release and fix the inconsistencies. Thank you !
 
R

Ronald Laeremans [MSFT]

Hi Edward,

As I said in another reply, the solution for Whidbey is probably going to be
along different lines altogether than what we have for 7.x altogether, and
it isn't settled enough yet so I can't comment on the new design for that
part here.

Ronald

Edward Diener said:
Ronald said:
Probably because we special cased value types and forgot about value
enum types.

Programmers, like elephants, never forget <g> .

I hope I have given enough for you to think about and fix in the next
release regarding this area.
Ronald

Edward Diener said:
Ronald Laeremans [MSFT] wrote:
Some additional background:

The restriction of it needing to be in the same assembly of the
current rule is because we do not read metadata for private members,
and so a ref type could be hiding there.

And the restriction of needing sequential or explicit layout is
because the CLR decision to have all value types have sequential
layout by default came pretty late in the 7.0 cycle. We didn't
consider any of this important enough to revisit for 7.1.

Why does a restriction also apply to variables of __value enum
embedded in __nogc types ? Clearly these follow neither the first
explanation above, about hidden ref types nor the second about
sequential layout. Yet if I try to embed a __value enum variable in
a __nogc class the compiler gives me an error saying that I can not
do it.


Ronald

Hi Edward,

I can understand the rule against having any ref types but I don't
understand the simplifying choice.

I think he might've meant simplifying it for the compiler
development, not necessarily the end user ;)
It ain't exactly all that trivial to check, since the check would
need to be recursive (remember Ronald pointed out it applied to
direct _and_ indirect containment of handles to managed ref types),
so there are a few ugly cases that would need to be cared for,
making things more complex than necessary.

Then again, it's just mho, I might be just missing the point ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top