-
Notifications
You must be signed in to change notification settings - Fork 425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with runtime type and default initialization #15929
Comments
`Map.map` ran into issue chapel-lang#15929 . As a workaround, we can avoid the default initializer and initialize with new instead. Also, fix an typo where a method was called without the receiver argument.
Unfortunately the workaround isn't working for maps of classes. After doing the workaround on the use Map;
class C {
var i: int;
}
var m = new map(int, owned C?);
m.add(1, new owned C?(1)); $CHPL_HOME/modules/standard/Map.chpl:74: internal error: invalid attempt to get reference type [AST/primitive.cpp:235] With this diff from master: diff --git a/modules/standard/Map.chpl b/modules/standard/Map.chpl
index 9f1a67136e..29b4676628 100644
--- a/modules/standard/Map.chpl
+++ b/modules/standard/Map.chpl
param parSafe = false;
pragma "no doc"
- var table: chpl__hashtable(keyType, valType);
+ var table = new chpl__hashtable(keyType, valType);
pragma "no doc"
var _lock$ = if parSafe then new _LockWrapper() else none; |
@daviditen - I'd suspect that is a different issue but I'm not seeing this problem with revision 27f25b4 and your patch applied on my system. |
Strange. I'm currently fully updated and see it on my Mac laptop, chapcs11, and the travis build of mason for PR #15932 . |
@daviditen - I've checked out your branch on chapcs11 and I'm not seeing the same issue. Is it possible that there is an error in the test program pasted above? Works for me on my Mac too.
I do see the error when building mason. Here it looks like the problem is that the compiler is trying to resolve PRIM_ADDR_OF with a chpl__hashtable variable that has generic type. I'm pretty sure that is a separate error and I would appreciate it if you are able to make a small reproducer and issue. I went ahead and tried a different workaround in Map. I applied this patch (to your branch):
and after that, |
Huh. Somehow the code from my comment is passing for me too now. I guess I copied the wrong thing. Sorry.
But then we're back into the problem this issue is about and |
Reformat .future files to look like: bug: problem with x of arrays chapel-lang#15929
Retire old map future and add new future to replace it [ reviewed by @daviditen ] PR #18523 added a new in the initializer for the chpl__hashtable in map, which caused this future test that was failing due to #15929 to be resolved, even though the underlying issue wasn't fixed, which is a known issue with default initializing a record with type that isn’t known until runtime. I spoke with David and decided to retire the old future and add a new one to keep tracking the underlying issue. The setOfArray future is unrelated and is failing due to #16033, a compiler issue.
Fix some problems in sets / hash tables of arrays [reviewed by @bmcdonald3, helped along by @mppf] This fixes support for sets of arrays by fixing a `==`-based key comparison and using an explicit `new` call to create the underlying hash table rather than relying on default initialization (contributed by @mppf). Specifically, we were using `key == key` to look for existing keys before, but for an array type, this will generate an array of bools rather than a single bool as we require here. So this PR pushes the test into a helper routine to compute it, which is sufficient to get the setOfArray.chpl future working. I then extended setOfArray.chpl to see if we could actually work with the set, and it turned out that we couldn't due to #15929 until we applied the workaround in that issue to ensure that the set's element type's runtime type was established properly (thanks to @mppf). While working on this, I added a pair of futures that demonstrate that a generic record instantiated with an array doesn't work: `genericRecordOfArray*.chpl` which seem related to: * #15929 * #13808 and/or * #11549 but felt simpler than any futures I quickly found for those cases. Resolves #16033.
@mppf: I just slammed back into this while trying to write a new test to lock something in and took an embarrassingly long time to debug it given that I've been working around it for the past few workdays (though I guess it is a Monday). Anyway, it made me wonder what we might be able to do to catch and complain about such cases rather than having them go through and result in unexpected behavior. But so far all I've done is wonder rather than actually think about it, so I'm putting this here to see what it jogs for you or remind myself to think about it more. |
I wouldn't expect it to be hard to emit an error or warning for it. The things that seem hard to me are to get it working comprehensively in all of these cases. |
@bradcray - here is a patch that adds a warning for the whole block of code that is problematic. We see the warning for the test in this issue but not for hello world. A reasonable next step would be to run testing with it to see if we have cases relying on it today. (I suspect that there used to be, especially within the array implementation, but that these have been gradually migrated away from this pattern).
|
OK, thanks! I suspect I can run a paratest against this this afternoon if you don't get to it first. |
The result was 29 failures, the vast majority of which had the output:
(where the main other cases were tests that created sync/single of array or the like—not currently supported, but generate the error). I haven't dug into this at all yet, but with this quick look wonder whether—if we were to replace the immediate warning with an insertion of a |
I suppose that those errors are indicating that there's probably code you could write with array-of-record-containing-array that would lead to memory errors. Perhaps we could/should silence the warning for internal modules in the near term though. |
Just ran into this again in #19118. For the pattern This doesn't happen in For the code: record foo {
type T;
proc doSomething(in val: T) {
writeln(val);
}
}
proc test() {
var obj: foo(domain(3));
obj.doSomething({0..1, 2..3, 4..5});
}
test(); Coming at you with DavidL levels of excessive detail, now, because I need input on my idea. The logged AST before resolve looks like this:
When the compiler goes to resolve This is what causes the runtime type to be lost. I think we could opt to not postfold these type instantiation calls at all, or conditionally not fold them if they contain a runtime type. Either way would work, I think? When resolving the default-init we can consult the call and compute the type symbol later if we need to in the same fashion as postfold. This would allow the default-init to just use the runtime type as it appears in the code instead of constructing an empty temp. Thoughts? Another option would be to walk backwards from the default-init and look for a specific pattern, but I am less confident about that idea. |
So I ran with my idea a bit and came up with something that actually works for my test case above, but As I was working on this, I kept asking "why do we replace type constructor calls with SymExprs to the type at all"? It seems like the situation would be handled naturally if we just didn't do that, because for (Well, it's also kind of the normalizer's fault, because the situation would be even better if we could just see |
…ic-record-rtt Fix generic record initialization when substitution is a runtime type Attempt to recover runtime types used in the type construction of default initialized records. This fixes some cases where a default initialized record containing an array or domain field would halt at runtime when said field was used. Resolves #19118. Resolves #20167. The parent issue for this effort is: #15929. Also consider: #19292, #20424 This PR does not fix all bugs related to default initialization of aggregates that contain runtime types. The bug persists when a type constructor containing a runtime type is obfuscated by indirection (e.g, it is returned by a function, or uses 2+ levels of type alias). See the added future `RuntimeTypeEscapes.chpl` for an example. Reviewed by @vasslitvinov. Thanks! TESTING - [x] `ALL` on `linux64`, `standard` Signed-off-by: David Longnecker <dlongnecke-cray@users.noreply.github.com>
After PR #15869, a problem came up in nightly testing that can be reproduced by the following code:
What happens is that the access
rr.t
ends up pointing to uninitialized memory. This is because the compiler computes the type expressionR(A.type)
separately from initializingrr
. In particular, increateGenericRecordVarDefaultInitCall
, it creates an uninitialized temporary storing the runtime type (see the code creating a variable nameddefault_runtime_temp
and the related comment).A workaround is to use e.g.
var rr = new R(A.type)
.I can see two ways we might be able to fix the bug:
type t = R(A.type); var rr: t
and in that event the only way to get the valueA.type
at runtime intorr
is if thet
variable stores the runtime type for its field. This might be relatively straightforward for records but might become untenable or impossible to do with classes. (But maybe that is a restriction we could document). This has been a long-term todo - see handle record and class types with runtime types #11549.var rr: R(A.type);
more directly. In particular, this might involve adjusting PRIM_DEFAULT_INIT_VAR to accept extra arguments for runtime types of fields.The text was updated successfully, but these errors were encountered: