www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - potential behavior of nested structs

reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  Branched off since this seems appropriate.

  Currently nested structs are illegal, since having them on the 
stack passing them with a context pointer would result in illegal 
code or undefined behavior.

   struct Outer {
     struct Inner {
       string innerString;
       string getOuterString() { return outerString; }
     }

     string outerString;
     Inner innerInstance;
   }

   auto func(Outer x) {
     return x.innerInstance;
   }

   //inner needs outer instance, is not immediately usable.
   Outer.Inner inner;
   Outer outer;

   //points to temporary 'x' from func, likely garbage
   inner = func(outer);


  If Outer had been a class, then being on the heap the problem 
goes away, plus the class is always by reference.

  Considering behavior for making nested structs legal, it would 
require a few extra rules to ensure it would be safe to use.

  1) It cannot return a nested struct outside of it's level of 
control where it can ensure it exists. Alternatively returning a 
nested struct (outside of it's own implementation) could be 
downright illegal, but that seems too limiting.

   //error, x is a temporary
   Inner func(Outer x){return x.innerInstance; }

   //Inner still valid after call.
   Inner func(ref Outer x){return x.innerInstance; }

  2) Nested structs need context pointers, however with being able 
to swap structs at a whim having an address as part of the 
struct's contents is impractical. In this case the structs being 
passed has to silently pass in the function call the related 
pointers. If it's nested multiple levels, each level would have 
to be referenced.  If you don't/can't return it outside a 
function receiving it (or it's parent), then it's as safe as ref 
is.

   struct Outer {
     struct Inner {}
     void func(Inner x) {}

//translates to
     void func(ref Outer this, ref Outer xPtr, Inner x) {}
   }

  3) If the nested struct has no data then it's more a name-space 
for behavior (and an alias for the outer/parent struct). If the 
nested struct does not actually use it's parents data in any 
methods, then it can in turn be copied/returned without any extra 
context pointers.

  4) Nested structs's may rely on their parent's data, but the 
parents don't have to rely on the nested struct's data (If they 
do, then opAssign would be needed, or postblit to handle the 
changes). An example of this is potentially in a DB environment 
where a struct holding a text query can be replaced by a compiled 
version of that query, the parent doesn't need to know.

   struct Dog {
     string dogName;
     struct Tail {
       string colorOf = "Black"; //just data.
       string name() { return dogName; }
     }
     Tail tail;

     void func(ref Dog rhs) {
       //tail2 retains context pointer to rhs.
       Tail tail2 = rhs.tail;

       writeln(tail.name());   //Scruffy
       writeln(tail2.name());  //Spike
     }

     //ref, otherwise illegal to return
     Tail doesSomething(ref Outer rhs) {
       return rhs.tail;
     }
   }

   Dog dog1 = Dog("Scruffy");
   Dog dog2 = Dog("Spike"); dog2.tail.colorOf = "White";

   dog1.func(dog2);

   //context pointer to dog2 thrown away after copy,
   //unless opAssign declared and does something.
   //so dog1's tail belongs to dog1, not dog2
   dog1.tail = dog2.tail;

   assert(dog1.dogName == "Scruffy");     //untouched
   assert(dog1.tail.name == "Scruffy");   //dog1 owns tail, not 
dog2
   assert(dog1.tail.colorOf == "White");  //data copied for tail.


  Thoughts and ideas?
Feb 03 2013
next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Monday, 4 February 2013 at 00:26:10 UTC, Era Scarecrow wrote:
  Branched off since this seems appropriate.

  Currently nested structs are illegal, since having them on the 
 stack passing them with a context pointer would result in 
 illegal code or undefined behavior.
Strictly speaking they are not illegal, they just do not have context pointer which points to enclosing struct. Thus, even if you manage to return outer struct data from inner, this would not work if nested struct is created alone, without outer struct.
  Thoughts and ideas?
I do not think there are problems with how nested structs with context pointer should be defined. I consider implementation to be a serious problem since we often have <100 messages in forum and no practice steps. What I expect to be a problem is storing pointer to outer struct in nested struct. The problem is that most structs are stack allocated and stack pointer can be invalidated. Example http://d.puremagic.com/issues/show_bug.cgi?id=9352
Feb 03 2013
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 4 February 2013 at 07:15:47 UTC, Maxim Fomin wrote:
 Strictly speaking they are not illegal, they just do not have 
 context pointer which points to enclosing struct. Thus, even if 
 you manage to return outer struct data from inner, this would 
 not work if nested struct is created alone, without outer 
 struct.
I'm aware of that. With nested structs we know they will be part of a larger structure so making & using them outside of their parent struct just doesn't work; At best you can move them as storage but couldn't instantiate them yourself.
 Thoughts and ideas?
I do not think there are problems with how nested structs with context pointer should be defined. I consider implementation to be a serious problem since we often have <100 messages in forum and no practice steps. What I expect to be a problem is storing pointer to outer struct in nested struct. The problem is that most structs are stack allocated and stack pointer can be invalidated. Example http://d.puremagic.com/issues/show_bug.cgi?id=9352
Yes I know, this is why returning a struct beyond it's level or where it may be invalidated wouldn't be allowed, which combats this (or even removes it altogether). But as much as I think on the matter of nested structs, I keep coming back to that they are an implementation detail of the parent structs and not really intended to leave them.
Feb 04 2013
prev sibling parent reply "Dicebot" <m.strashun gmail.com> writes:
Nested types with hidden context pointers is one of D features I 
do not like at all.
Please leave me at least my structs. :(
Feb 04 2013
next sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 4 February 2013 at 14:37:29 UTC, Dicebot wrote:
 Nested types with hidden context pointers is one of D features 
 I do not like at all.
 Please leave me at least my structs. :(
They already exist for classes though; Or so I understand. They would be rare; But I've had the need for them with non-classes (say a sorting algorithm that's also a range) it's an annoyance to manually do it using pointers and then having to update said pointers. It can be done... It's just ugly and doesn't feel like I should have to.
Feb 04 2013
parent reply "Zach the Mystic" <reachBUTMINUSTHISzach gOOGLYmail.com> writes:
On Monday, 4 February 2013 at 22:17:04 UTC, Era Scarecrow wrote:
 On Monday, 4 February 2013 at 14:37:29 UTC, Dicebot wrote:
 Nested types with hidden context pointers is one of D features 
 I do not like at all.
 Please leave me at least my structs. :(
They already exist for classes though; Or so I understand. They would be rare; But I've had the need for them with non-classes (say a sorting algorithm that's also a range) it's an annoyance to manually do it using pointers and then having to update said pointers. It can be done... It's just ugly and doesn't feel like I should have to.
Hey I've been working on this. Thanks for holding the fort down.
Feb 04 2013
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 4 February 2013 at 22:42:52 UTC, Zach the Mystic wrote:
 On Monday, 4 February 2013 at 22:17:04 UTC, Era Scarecrow wrote:
 They already exist for classes though; Or so I understand.

 They would be rare; But I've had the need for them with 
 non-classes (say a sorting algorithm that's also a range) it's 
 an annoyance to manually do it using pointers and then having 
 to update said pointers. It can be done... It's just ugly and 
 doesn't feel like I should have to.
Hey I've been working on this. Thanks for holding the fort down.
After reading your post (Atoms, protons, neurons) I can see we're thinking a lot on the same lines; Although yours doesn't get into limitations of when not to return a nested struct, But if the implementation never leaves the outer/parent struct then it doesn't matter. This would be something for someone to try incorporating into a test version of the front end and just see how it works. Kinda like the property problem, some things you just gotta try yourself with an implementation before you know if it's a good design. Thankfully if it is allowed it couldn't possibly break code (as they aren't allowed right now). But that's up to Andrei and Walter to decide if it's allowed, we don't want to have create/break specs and split the community.
Feb 04 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/04/2013 03:37 PM, Dicebot wrote:
 Nested types with hidden context pointers is one of D features I do not
 like at all.
 Please leave me at least my structs. :(
Use 'static'. Anyway, there is nothing wrong with those.
Feb 04 2013
parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 5 February 2013 at 00:19:19 UTC, Timon Gehr wrote:
 On 02/04/2013 03:37 PM, Dicebot wrote:
 Nested types with hidden context pointers is one of D features 
 I do not
 like at all.
 Please leave me at least my structs. :(
Use 'static'. Anyway, there is nothing wrong with those.
You are my savior. Didn't know this was defined. Will switch.
Feb 05 2013