Skip to content

Instantly share code, notes, and snippets.

@lydia-duncan
Created August 24, 2022 21:43
Show Gist options
  • Save lydia-duncan/ca4d886b05d950fd8d67e9cc6aedb435 to your computer and use it in GitHub Desktop.
Save lydia-duncan/ca4d886b05d950fd8d67e9cc6aedb435 to your computer and use it in GitHub Desktop.
Owned/shared activity notes
------
Helped answer some questions from other team members
------
Activity itself:
One thing that immediately occurs to me as a source of confusion is if the default management style for variables does not
match the default management style for fields.
test/classes/delete-free/undecorated-generic/generic-management-field.chpl
My instinct is that if this code really was translated to this:
```chapel
class FieldClass {
var x: int;
}
record storesField {
var f: shared FieldClass;
}
proc main() {
var fc1 = new owned FieldClass(3);
writeln(fc1);
var sf1 = new storesField(fc1);
writeln(sf1);
}
```
Then we will get the error that explicit code generates today:
```
generic-management-field.chpl:9: In function 'main':
generic-management-field.chpl:13: error: unresolved call 'storesField.init(owned FieldClass)'
generic-management-field.chpl:5: note: this candidate did not match: storesField.init(f: shared FieldClass)
generic-management-field.chpl:13: note: because actual argument #1 with type 'owned FieldClass'
generic-management-field.chpl:6: note: is passed to formal 'in f: shared FieldClass'
```
(This is the same error we get if line 24 instead relies on the default management, just for completeness)
That's not to say that `shared` on its own is a bad default for fields, just that variable declarations should probably
end up with the same default management style as fields if we think it is really important to change the management style
for fields from being generic.
Alternatively, we could provide initializer overloads that make the translation from owned into shared occur by default, but it
might be annoying if a user wants to write their own to now suddenly not be able to support that for their classes.
Test of initializer written with default management type:
test/classes/delete-free/undecorated-generic/generic-management-field2.chpl
Modifying it like this to mock up "shared-as-field-default" gives a warning because we're deprecating the assignment operator
between owned and shared:
```chapel
class FieldClass {
var x: int;
}
record storesField {
var f: shared FieldClass;
proc init(in field: FieldClass) {
f = field;
writeln("In the explicit initializer");
}
}
proc main() {
var fc1 = new FieldClass(3);
writeln(fc1);
var sf1 = new storesField(fc1);
writeln(sf1);
}
```
```
generic-management-field2.chpl:10: In initializer:
generic-management-field2.chpl:11: warning: assigning owned class to shared class is deprecated.
generic-management-field2.chpl:20: called as storesField.init(field: owned FieldClass)
```
I don't think it's wrong to deprecate the assignment in other circumstances, but it seems unfortunate in this one because the
user didn't explicit choose to use different management styles for the initializer and the field. To me, that indicates that
the generic default for the field is less likely to lead to frustration.
> Can anyone show me an example where we are able to take advantage of generic fields
They'll certainly result in different patterns if users use the class in different ways. But I'm not seeing anything about
them that means we can't use them in a way that's appropriate for each management type. But it's hard to come up with examples
on the fly - it seems likely that something that would be useful in an Expression Tree context wouldn't be necessarily as
useful in a LinkedList for instance in addition to the shared/owned concerns, but that's not the scope of all problems. It's
impossible to prove a negative.
Anyways, a couple of the tests I made use the same backbone code but with different management styles.
test/classes/delete-free/undecorated-generic/generic-management-field2-unmanaged.chpl
test/classes/delete-free/undecorated-generic/generic-management-field2-borrow.chpl
And here's a test with all of them in the same one (but it's very much a toy):
test/classes/delete-free/undecorated-generic/generic-management-field-multiple.chpl
Wrote this code to try and mock up a linked list with a generic field type but using it with shared:
```chapel
class ListNode {
var next: ListNode?;
var x: int;
proc init(val: int) {
next = nil: ListNode?; // RIP
x = val;
}
proc init(node: ListNode, val: int) {
next = node;
x = val;
}
proc deinit() {
writeln("Cleaning up x=", x);
}
}
class List {
var head: ListNode?;
proc deinit() {
while head != nil {
var headTmp = head;
head = head.next;
headTmp.next = nil;
}
}
}
proc main() {
var list = new List(new shared ListNode(3));
list.head.next = new shared ListNode(2, new shared ListNode(1));
writeln(list);
}
```
But encountered this failure:
```
linkedListExample.chpl:5: In initializer:
linkedListExample.chpl:6: error: cannot default-initialize a variable with generic type
linkedListExample.chpl:6: note: '<temporary>' has generic type 'ListNode?'
linkedListExample.chpl:6: note: cannot find initialization point to split-init this variable
linkedListExample.chpl:6: note: '<temporary>' is used here before it is initialized
```
I believe this means that you can't maintain the genericness of the field and give it nil without asking the user to be the
one to provide nil. But it doesn't seem like the user can provide it either:
```chapel
class ListNode {
var next: ListNode?;
var x: int;
proc init(node: ListNode?, val: int) {
next = node;
x = val;
}
proc deinit() {
writeln("Cleaning up x=", x);
}
}
class List {
var head: ListNode?;
proc deinit() {
while head != nil {
var headTmp = head;
head = head.next;
headTmp.next = nil;
}
}
}
proc main() {
var list = new List(new shared ListNode(nil: shared ListNode?, 3)); // RIP
list.head.next = new shared ListNode(2, new shared ListNode(nil: shared ListNode?, 1));
writeln(list);
}
```
Here's the failure message:
```
linkedListExample.chpl:28: In function 'main':
linkedListExample.chpl:29: error: illegal cast from nil to a generic shared type
```
I was able to get a version working that explicitly had shared as the type for the field, but it did require adding a few `?`s
to the user declarations I was passing in, which was a bit annoying. It lives here:
test/classes/delete-free/shared/linkedListExample.chpl
Tests are checked in on this branch:
https://github.com/chapel-lang/chapel/compare/main...lydia-duncan:hackathonExperiment?expand=1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment