Hi Orian / all --

Following up on yesterday's mail, I just filed issue 5358 as a placeholder for the semantic question about whether we want to prevent overloads of assignment on class types:

        https://github.com/chapel-lang/chapel/issues/5358

-Brad


On Mon, 13 Feb 2017, Brad Chamberlain wrote:



Hi Orian --

I haven't had a lot of time to dig into your example today, but wanted to make sure we got you a response before the end of the day. Others on the team who are more expert with this part of the compiler/language may tag onto what I say here. I also want to thank my colleague Vass for a lot of help in creating this response.

I think your code is running afoul of a few things which the Chapel compiler should be helping to guard you against but, unfortunately, isn't at present.

First, as background, I want to make sure it's clear that if you're coming from a C/C++ world, you should think of a Chapel record as being like a struct/class and a Chapel class as being like a pointer to a struct/class.

The first issue that made me nervous in your code is that it hasn't been our intention to support assignment overloads between Chapel class variables. However, there is also currently nothing in the compiler that prevents it. Personally, I get nervous that if assignment between classes means anything other than "copy the rhs object pointer/ref into the lhs one" that it could cause problems with core capabilities like compiler-inserted temps/copies and type inference. By analogy, I believe it's the case that while C++ permits assignment overloads between structs, it doesn't support assignment overloads for pointers-to-structs (by analogy, Chapel _does_ permit assignment overloads for records).

So one way you could proceed would be to create an 'assign()' function that took the LHS not by-ref. This would be similar to the '=' overload you created that generated the warning.

[As a sidebar, one of the ways we often work around this in our own code is to create a record type that wraps a variable of the class type in order to support assignment overloads, automatic memory management, and the like on the record type without giving up the reference/identity semantics that the class variable provides. We're working on some features for the next release that will permit users to tap into such record-wrapped-class patterns without having to write all the wrapper code themselves].


The second issue may relate to how you declare your FockMatrix variable (which is code that I don't think you included in your mail (?), so I'm guessing at this point). Specifically, if FockMatrix was declared this way:

        var myMat = new FockMatrix();

then the Chapel compiler will infer the _static_ type of myMat to be FockMatrix rather than SymmMatrix. And even though FockMatrix is a subclass of SymmMatrix, this in itself is insufficient to support passing a variable of static type FockMatrix to a formal of type ref-to-SymmMatrix (as in C++). In order for that to be legal, you would also need to make sure that 'myMat' has static type of SymmMatrix, as follows:

        var myMat: SymmMatrix = new FockMatrix();

Here's a simple example that Vass put together that works:

        class C    { proc foo() { writeln("C::foo"); } }
        class D: C { proc foo() { writeln("D::foo"); } }

        proc bar (ref x: C) { x.foo(); x = new C(); x.foo(); }

        proc main {
          var myC: C = new D();
          myC.foo();
          bar(myC);
          myC.foo();
        }

whereas if the declaration of myC is changed to:

          var myC = new D();

then the C compilation step fails with messages similar to the ones you report. Vass also provides an example showing why this should be problematic, if it's not obvious:

        class C    { }
        class D: C { proc print { writeln(); } }

        proc test(ref lhs: C) { lhs = new C(); }

        var d = new D();
        test(d);
        d.print;  // doesn't make sense when 'd' is actually a 'C'!

This is the second way that the Chapel compiler is failing you. It should complain loudly about passing a variable of static type 'D' to a 'ref' formal of type 'C' rather than letting it pass silently and having the C compilation step blow up. Vass opened an issue and test to track this problem today:

        https://github.com/chapel-lang/chapel/issues/5353
        https://github.com/chapel-lang/chapel/pull/5352

(and we should open one for assignment overloads on class types as well).

So, I'll be curious whether this is how you declared your SymmMatrix variable, and if so, whether giving it a static type fixes the issue (but then I'll still remain nervous about overloading assignment on it...).


Turning to some of the specific questions in your mail:

The origin of the problem seems to be that the compiler expect a SymmMatrix not a FockMatrix (even if SymmMatrix is the superclass). But then I don’t understand why I have a double pointer structure (struct chpl_SymmMatrix_chpl_s **) vs a single pointer structure (struct chpl_FockMatrix_chpl_s *).

It may be clearer by this point that one of these '*'s comes from the 'class' type ("pointer to struct" in C) and the other comes from the 'ref' argument intent.


I am assuming that the overloaded operators of the superclass are valid for the child classes.
Am I right?

Only if the child class variables have the superclass static type.


Hope this is helpful,
-Brad
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users

Reply via email to