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