Skip to content

Commit

Permalink
feat: identify invalid captures (and other improvements) (#1743)
Browse files Browse the repository at this point in the history
Following up on #1682 to identify cases where we cannot infer which operations are performed on a captured resource.

See positive/negative tests for examples.

Rewrite the algorithm which analyzes the expressions captured by inflight methods so that it is able to identify more cases and emit errors when captures cannot be qualified (i.e. a resource is captured but we cannot determine which operations are performed on it without static analysis).

For each method, we identify all expressions that start with `this.xxx` and break them down into parts (using nested references). Then, we traverse the list of parts and split the expression into *preflight* and *inflight*. The preflight part is what we are capturing and the first inflight component qualifies which operations are performed on the captured object.

Reorganized capture tests into `resource_captures` (both under valid and invalid).

This does not address #76 but it explicitly identifies these cases. We will follow up at some point with a way to allow users to explicitly qualify the reference.

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Monada Contribution License](https://docs.winglang.io/terms-and-policies/contribution-license.html)*.
  • Loading branch information
eladb authored Mar 15, 2023
1 parent 48b2cde commit c217ea1
Show file tree
Hide file tree
Showing 36 changed files with 1,058 additions and 551 deletions.
60 changes: 60 additions & 0 deletions examples/tests/invalid/inflight_ref_explicit_ops.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
bring cloud;

resource Another {
my_queue: cloud.Queue;
another_str: str;

init () {
this.my_queue = new cloud.Queue();
this.another_str = "bang";
}

inflight inflight_returns_resource(): cloud.Queue {
return this.my_queue;
// ^^^^^^^^ Cannot qualify which operations are performed on resource
}
}

resource Test {
just_bucket: cloud.Bucket;
b: cloud.Bucket;
another: Another;
array: Array<cloud.Bucket>;
just_str: str;

init() {
this.b = new cloud.Bucket() as "b1";
this.just_bucket = new cloud.Bucket() as "b2";
this.another = new Another();
this.array = [new cloud.Bucket() as "a1", new cloud.Bucket() as "a2"];
this.just_str = "hello";
}

inflight test1() {
let x = this.b;
// ^ Cannot qualify which operations are performed on resource
x.put("hello", "world");
assert(this.just_str == "hello");
this.just_bucket.put("hello", "world");
}

inflight test2() {
let q = this.another.inflight_returns_resource();
q.push("push!");
}

inflight test3() {
let b = this.array.at(1);
assert(b.list().length == 0);
}

inflight test4() {
assert(this.another.another_str == "bang");
}
}

let f = new Test();
new cloud.Function(inflight () => { f.test1(); }) as "test1";
new cloud.Function(inflight () => { f.test2(); }) as "test2";
new cloud.Function(inflight () => { f.test3(); }) as "test3";
new cloud.Function(inflight () => { f.test4(); }) as "test4";
17 changes: 0 additions & 17 deletions examples/tests/invalid/inflight_ref_invalid.w

This file was deleted.

34 changes: 0 additions & 34 deletions examples/tests/invalid/inflight_ref_resource_sub_field.w

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// NOTE: this test is supposed to fail once https://github.com/winglang/wing/pull/1610 is complete

bring cloud;

resource Another {
Expand All @@ -11,6 +9,7 @@ resource Another {

inflight inflight_returns_resource(): cloud.Queue {
return this.my_queue;
// ^^^^^^^^ Cannot qualify which operations are performed on resource "this.my_queue"
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// NOTE: this test is supposed to fail once https://github.com/winglang/wing/pull/1610 is complete

bring cloud;

resource Test {
Expand All @@ -11,9 +9,10 @@ resource Test {

inflight test() {
let x = this.b;
// ^ Cannot qualify which operations are performed on resource
x.put("hello", "world");
}
}

let f = new Test();
new cloud.Function(inflight () => { f.test(); }) as "test";
new cloud.Function(inflight () => { f.test(); }) as "test";
22 changes: 22 additions & 0 deletions examples/tests/invalid/preflight_from_inflight.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
bring cloud;

resource MyResource {
init() {

}

my_preflight() { }
}

resource Test {
r: MyResource;

init() {
this.r = new MyResource();
}

inflight test() {
this.r.my_preflight();
// ^^^^^^^^^^^^^^^^^^^^^^ Cannot call into preflight phase while inflight
}
}
29 changes: 29 additions & 0 deletions examples/tests/invalid/resource_captures.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
bring cloud;

resource Foo {
bucket: cloud.Bucket;
mut_array: MutArray<str>;
var reassignable: num;
collection_of_resources: Array<cloud.Bucket>;

init() {
this.mut_array = MutArray<str>[];
this.mut_array.push("hello");
this.reassignable = 42;
this.collection_of_resources = Array<cloud.Bucket>[];
}

inflight test() {
print("${this.reassignable}");
// ^^^^^^^^^^^^^^^^^ Cannot capture reassignable field 'reassignable'
print(this.mut_array.at(0));
// ^^^^^^^^^ Unable to reference "this.mut_array" from inflight method "test" because type MutArray<str> is not capturable

let b = this.bucket;
// ^^^^^^^^^^^ Unable to qualify which operations are performed on 'this.bucket' of type 'Bucket'. This is not supported yet.
b.put("hello", "world");

this.collection_of_resources.at(0).put("hello", "world");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Capturing collection of resources is not supported yet (type is 'Array<Bucket>')
}
}
2 changes: 1 addition & 1 deletion examples/tests/valid/capture_resource_with_no_inflight.w
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ resource A {

let a = new A();
new cloud.Function(inflight () => {
assert("hey" == a.field);
assert("hey" == a.field);
}) as "test";
20 changes: 0 additions & 20 deletions examples/tests/valid/inflight_ref_external.w

This file was deleted.

23 changes: 0 additions & 23 deletions examples/tests/valid/inflight_ref_inflight_field.w

This file was deleted.

24 changes: 0 additions & 24 deletions examples/tests/valid/inflight_ref_primitive.w

This file was deleted.

16 changes: 0 additions & 16 deletions examples/tests/valid/inflight_ref_resource.w

This file was deleted.

18 changes: 0 additions & 18 deletions examples/tests/valid/inflight_ref_resource_collection.w

This file was deleted.

16 changes: 0 additions & 16 deletions examples/tests/valid/inflight_ref_resource_field.w

This file was deleted.

25 changes: 0 additions & 25 deletions examples/tests/valid/inflight_ref_resource_userdefined.w

This file was deleted.

Loading

0 comments on commit c217ea1

Please sign in to comment.