From 96e26a82d4491ae11ea18a9c3ff96b6043869d5d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 5 Feb 2019 10:17:46 +0100 Subject: [PATCH 1/5] Add blocks to the testcase for #103 so that we see all error messages, and not just the first. --- test/fail/issue103.as | 24 ++++++++++++++++-------- test/fail/ok/issue103.tc.ok | 4 +++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/test/fail/issue103.as b/test/fail/issue103.as index 0e3f23522cc..2b60aa7d48c 100644 --- a/test/fail/issue103.as +++ b/test/fail/issue103.as @@ -1,19 +1,27 @@ // A (non-shared) function is not sharable -func invalid1 (f : shared (() -> Nat) -> ()) { - f (func foo() : Nat = 1) +{ + func invalid1 (f : shared (() -> Nat) -> ()) { + f (func foo() : Nat = 1) + }; }; // An object with function fields is not sharable -func invalid2 (f : shared {foo : () -> Nat} -> ()) { - f (new { foo() : Nat = 1; }) +{ + func invalid2 (f : shared {foo : () -> Nat} -> ()) { + f (new { foo() : Nat = 1; }) + }; }; // Cannot return a function in an async -func invalid3 () : (async (() -> Nat)) { - async { func foo() : Nat = 1 } +{ + func invalid3 () : (async (() -> Nat)) { + async { func foo() : Nat = 1 } + }; }; // Cannot return an object with function fields in an async -func invalid4 () : (async ({foo : () -> Nat})) { - async { new { foo() : Nat = 1; } } +{ + func invalid4 () : (async ({foo : () -> Nat})) { + async { new { foo() : Nat = 1; } } + }; }; diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index e01110ef026..1740e3ce0e3 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -1,2 +1,4 @@ -issue103.as:2.27-2.38: type error, shared function has non-shared parameter type +issue103.as:3.29-3.40: type error, shared function has non-shared parameter type + () -> Nat +issue103.as:17.29-17.40: type error, async type has non-shared parameter type () -> Nat From ce45a51f8690244012d7a88302e16f3b67832130 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 6 Feb 2019 10:23:18 +0100 Subject: [PATCH 2/5] Remove the concept of a shared objects previously, objects might have had a class identity that is not valid across different actors, so we distinguished between shared and non-shared objects. With `is` removed (#145), we no longer that distinction; an object is a subtype of `Shared` if and only if all fields are (same as for tuples, as one would expect). This removes a bunch of code. It might be that Andreas could have implemented this faster on his own than reviewing this PR, but I wanted to sieze the opportunity to learn more about the type chekcker etc. It is one of the clean-ups menionted in #81 (there are more left though). It fixes #103. --- src/arrange.ml | 2 +- src/arrange_type.ml | 2 +- src/check_ir.ml | 11 +++++------ src/compile.ml | 2 +- src/definedness.ml | 2 +- src/desugar.ml | 2 +- src/parser.mly | 23 +++++++++-------------- src/type.ml | 21 ++++++++++----------- src/type.mli | 2 +- src/typing.ml | 8 ++++---- test/run/for.as | 20 -------------------- test/run/ok/for.run-ir.ok | 2 +- test/run/ok/for.run-low.ok | 2 +- test/run/ok/for.run.ok | 2 +- 14 files changed, 37 insertions(+), 64 deletions(-) diff --git a/src/arrange.ml b/src/arrange.ml index 4d658d0d1d0..3e2ecd91181 100644 --- a/src/arrange.ml +++ b/src/arrange.ml @@ -106,7 +106,7 @@ and control c = match c with | Type.Promises -> "Promises" and obj_sort' s = match s with - | Type.Object sh -> Atom ("Object " ^ sharing sh) + | Type.Object -> Atom "Object" | Type.Actor -> Atom "Actor" and obj_sort s = obj_sort' s.it diff --git a/src/arrange_type.ml b/src/arrange_type.ml index 6740fea0ebe..f9b2621037a 100644 --- a/src/arrange_type.ml +++ b/src/arrange_type.ml @@ -15,7 +15,7 @@ and control c = match c with | Type.Promises -> "Promises" and obj_sort s = match s with - | Type.Object sh -> Atom ("Object " ^ sharing sh) + | Type.Object -> Atom "Object" | Type.Actor -> Atom "Actor" and func_sort s = match s with diff --git a/src/check_ir.ml b/src/check_ir.ml index dad25f85ebf..64c30ccc318 100644 --- a/src/check_ir.ml +++ b/src/check_ir.ml @@ -200,8 +200,8 @@ and check_typ_field env s typ_field : unit = (s <> T.Actor || T.is_func (T.promote env.cons typ)) "actor field has non-function type"; check env no_region - (s = T.Object T.Local || T.sub env.cons typ T.Shared) - "shared object or actor field has non-shared type" + (s <> T.Actor || T.sub env.cons typ T.Shared) + "actor field has non-shared type" and check_typ_binds env typ_binds : T.con list * con_env = @@ -656,10 +656,9 @@ and type_exp_field env s (tfs, ve) field : T.field list * val_env = is_func_exp exp) "public actor field is not a function"; check env field.at - (if (s <> T.Object T.Local && priv.it = Syntax.Public) - then T.sub env.cons t T.Shared - else true) - "public shared object or actor field has non-shared type"; + ((s = T.Actor && priv.it = Syntax.Public) ==> + T.sub env.cons t T.Shared) + "public actor field has non-shared type"; let ve' = T.Env.add id.it t ve in let tfs' = if priv.it = Syntax.Private diff --git a/src/compile.ml b/src/compile.ml index 5b5e04d5def..00e1566682d 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -3428,7 +3428,7 @@ and compile_exp (env : E.t) exp = StackRep.unit, compile_exp_vanilla env e ^^ Var.set_val env name.it - | NewObjE ({ it = Type.Object _ (*sharing*); _}, fs, _) -> + | NewObjE ({ it = Type.Object; _}, fs, _) -> StackRep.Vanilla, let fs' = List.map (fun (name, id) -> (name, fun env -> Var.get_val_ptr env id.it)) diff --git a/src/definedness.ml b/src/definedness.ml index 0214dcb02d5..25fe376c0ab 100644 --- a/src/definedness.ml +++ b/src/definedness.ml @@ -93,7 +93,7 @@ let rec exp msgs e : f = match e.it with let f = close (exp_fields msgs efs) // i.it in begin match s.it with | Type.Actor -> eagerify f - | Type.Object _ -> f + | Type.Object -> f end | DotE (e, _t, i) -> exp msgs e | AssignE (e1, e2) -> exps msgs [e1; e2] diff --git a/src/desugar.ml b/src/desugar.ml index 393c5994ae2..1a5b0d8b8f2 100644 --- a/src/desugar.ml +++ b/src/desugar.ml @@ -104,7 +104,7 @@ and field_to_obj_entry (f : S.exp_field) = and obj at s class_id self_id es obj_typ = match s.it with - | Type.Object _ -> build_obj at None s self_id es obj_typ + | Type.Object -> build_obj at None s self_id es obj_typ | Type.Actor -> I.ActorE (self_id, exp_fields es, obj_typ) and build_obj at class_id s self_id es obj_typ = diff --git a/src/parser.mly b/src/parser.mly index 6f1d3ab6993..4b44f89ffce 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -24,7 +24,7 @@ let (@?) it at = {it; at; note = empty_typ_note} let (@!) it at = {it; at; note = Type.Pre} let (@=) it at = {it; at; note = None} -let dummy_obj_sort() = ref (Type.Object Type.Local) +let dummy_obj_sort() = ref Type.Object let dup_var x = VarE (x.it @@ x.at) @? x.at @@ -58,8 +58,6 @@ let assign_op lhs rhs_f at = let share_typ t = match t.it with - | ObjT ({it = Type.Object Type.Local; _} as s, tfs) -> - { t with it = ObjT ({s with it = Type.Object Type.Sharable}, tfs)} | FuncT ({it = Type.Call Type.Local; _} as s, tbs, t1, t2) -> { t with it = FuncT ({s with it = Type.Call Type.Sharable}, tbs, t1, t2)} | _ -> t @@ -75,8 +73,6 @@ let share_dec d = let share_exp e = match e.it with - | ObjE ({it = Type.Object Type.Local; _} as s, x, efs) -> - ObjE ({s with it = Type.Object Type.Sharable}, x, efs) @? e.at | DecE (d, ot) -> DecE (share_dec d, ot) @? e.at | _ -> e @@ -173,13 +169,12 @@ seplist1(X, SEP) : | VAR { Var @@ at $sloc } %inline obj_sort : - | NEW { Type.Object Type.Local @@ at $sloc } - | OBJECT { Type.Object Type.Local @@ at $sloc } - | SHARED { Type.Object Type.Sharable @@ at $sloc } + | NEW { Type.Object @@ at $sloc } + | OBJECT { Type.Object @@ at $sloc } | ACTOR { Type.Actor @@ at $sloc } %inline obj_sort_opt : - | (* empty *) { Type.Object Type.Local @@ no_region } + | (* empty *) { Type.Object @@ no_region } | s=obj_sort { s } %inline shared_opt : @@ -208,7 +203,7 @@ typ_nullary : | LBRACKET m=var_opt t=typ RBRACKET { ArrayT(m, t) @! at $sloc } | tfs=typ_obj - { ObjT(Type.Object Type.Local @@ at $sloc, tfs) @! at $sloc } + { ObjT(Type.Object @@ at $sloc, tfs) @! at $sloc } typ_un : | t=typ_nullary @@ -225,7 +220,7 @@ typ_pre : { AsyncT(t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = - if s.it = Type.Object Type.Local + if s.it = Type.Object then tfs else List.map share_typfield tfs in ObjT(s, tfs') @! at $sloc } @@ -443,7 +438,7 @@ exp_nonvar : | s=obj_sort xf=id_opt EQ? efs=obj_body { let anon = if s.it = Type.Actor then "actor" else "object" in let efs' = - if s.it = Type.Object Type.Local + if s.it = Type.Object then efs else List.map share_expfield efs in ObjE(s, xf anon $sloc, efs') @? at $sloc } @@ -539,7 +534,7 @@ dec_nonvar : | s=obj_sort_opt CLASS xf=id_opt tps=typ_params_opt p=pat_nullary xefs=class_body { let x, efs = xefs in let efs' = - if s.it = Type.Object Type.Local + if s.it = Type.Object then efs else List.map share_expfield efs in @@ -557,7 +552,7 @@ dec : (* TODO(andreas): move to dec_nonvar once other production is gone *) | s=obj_sort id_opt=id? EQ? efs=obj_body { let efs' = - if s.it = Type.Object Type.Local + if s.it = Type.Object then efs else List.map share_expfield efs in diff --git a/src/type.ml b/src/type.ml index c290ddc726f..58bf21f9285 100644 --- a/src/type.ml +++ b/src/type.ml @@ -3,7 +3,7 @@ type con = Con.t type control = Returns | Promises (* Returns a computed value or immediate promise *) type sharing = Local | Sharable -type obj_sort = Object of sharing | Actor +type obj_sort = Object | Actor type func_sort = Call of sharing | Construct type eff = Triv | Await @@ -84,7 +84,7 @@ let prim = function | _ -> raise (Invalid_argument "Type.prim") let iter_obj t = - Obj (Object Local, + Obj (Object, [{name = "next"; typ = Func (Call Local, Returns, [], [], [Opt t])}]) let array_obj t = @@ -97,8 +97,8 @@ let array_obj t = let mut t = immut t @ [ {name = "set"; typ = Func (Call Local, Returns, [], [Prim Nat; t], [])} ] in match t with - | Mut t' -> Obj (Object Local, List.sort compare_field (mut t')) - | t -> Obj (Object Local, List.sort compare_field (immut t)) + | Mut t' -> Obj (Object, List.sort compare_field (mut t')) + | t -> Obj (Object, List.sort compare_field (immut t)) (* Shifting *) @@ -275,7 +275,7 @@ let as_prim_sub p env t = match promote env t with let rec as_obj_sub name env t = match promote env t with | Obj (s, tfs) -> s, tfs | Array t -> as_obj_sub name env (array_obj t) - | Non -> Object Sharable, [{name; typ = Non}] + | Non -> Object, [{name; typ = Non}] | _ -> invalid "as_obj_sub" let as_array_sub env t = match promote env t with | Array t -> t @@ -431,8 +431,9 @@ let rec rel_typ env rel eq t1 t2 = | Obj (s1, tfs1), Obj (s2, tfs2) -> s1 = s2 && rel_fields env rel eq tfs1 tfs2 - | Obj (s, _), Shared when rel != eq -> - s != Object Local + | Obj (s, tfs1), Shared when rel != eq -> + s = Actor || + rel_fields env rel eq tfs1 (List.map (fun f -> { f with typ = Shared }) tfs1) | Array t1', Array t2' -> rel_typ env rel eq t1' t2' | Array t1', Obj _ when rel != eq -> @@ -606,7 +607,7 @@ let rec string_of_typ_nullary vs = function sprintf "[var %s]" (string_of_typ_nullary vs t) | Array t -> sprintf "[%s]" (string_of_typ_nullary vs t) - | Obj (Object Local, fs) -> + | Obj (Object, fs) -> sprintf "{%s}" (String.concat "; " (List.map (string_of_field vs) fs)) | t -> sprintf "(%s)" (string_of_typ' vs t) @@ -644,10 +645,8 @@ and string_of_typ' vs t = sprintf "?%s" (string_of_typ_nullary vs t) | Async t -> sprintf "async %s" (string_of_typ_nullary vs t) - | Obj (Object Sharable, fs) -> - sprintf "shared %s" (string_of_typ_nullary vs (Obj (Object Local, fs))) | Obj (Actor, fs) -> - sprintf "actor %s" (string_of_typ_nullary vs (Obj (Object Local, fs))) + sprintf "actor %s" (string_of_typ_nullary vs (Obj (Object, fs))) | Mut t -> sprintf "var %s" (string_of_typ' vs t) | t -> string_of_typ_nullary vs t diff --git a/src/type.mli b/src/type.mli index d26ebb50719..6fbca464e7a 100644 --- a/src/type.mli +++ b/src/type.mli @@ -3,7 +3,7 @@ type con = Con.t type control = Returns | Promises (* returns a computed value or immediate promise *) type sharing = Local | Sharable -type obj_sort = Object of sharing | Actor +type obj_sort = Object | Actor type func_sort = Call of sharing | Construct type eff = Triv | Await diff --git a/src/typing.ml b/src/typing.ml index 663aa35a721..2352ff1f5f5 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -207,8 +207,8 @@ and check_typ_field env s typ_field : T.field = if s = T.Actor && not (T.is_func (T.promote env.cons t)) then error env typ.at "actor field %s has non-function type\n %s" id.it (T.string_of_typ_expand env.cons t); - if s <> T.Object T.Local && not (T.sub env.cons t T.Shared) then - error env typ.at "shared object or actor field %s has non-shared type\n %s" + if s = T.Actor && not (T.sub env.cons t T.Shared) then + error env typ.at "actor field %s has non-shared type\n %s" id.it (T.string_of_typ_expand env.cons t); {T.name = id.it; typ = t} @@ -934,8 +934,8 @@ and infer_exp_field env s (tfs, ve) field : T.field list * val_env = if not env.pre then begin if s = T.Actor && priv.it = Public && not (is_func_exp exp) then error env field.at "public actor field is not a function"; - if s <> T.Object T.Local && priv.it = Public && not (T.sub env.cons t T.Shared) then - error env field.at "public shared object or actor field %s has non-shared type\n %s" + if s = T.Actor && priv.it = Public && not (T.sub env.cons t T.Shared) then + error env field.at "public actor field %s has non-shared type\n %s" (string_of_name name.it) (T.string_of_typ_expand env.cons t) end; let ve' = T.Env.add id.it t ve in diff --git a/test/run/for.as b/test/run/for.as index dc8d83d7eed..5be13d5874a 100644 --- a/test/run/for.as +++ b/test/run/for.as @@ -10,16 +10,6 @@ async { assert(i == 11); }; -{ - var i = 0; - for (j in await async (range(0, 10))) { - printInt(j); - assert(j == i); - i += 1; - }; - assert(i == 11); -}; - { var i = 0; i := 0; @@ -31,16 +21,6 @@ async { assert(i == 11); }; -{ - var i = 0; - for (j in await async (range(0, 10))) { - printInt(j); - assert(j == i); - await (async (i += 1)); - }; - assert(i == 11); -}; - }; diff --git a/test/run/ok/for.run-ir.ok b/test/run/ok/for.run-ir.ok index ac6ac408923..0b36fe95ae6 100644 --- a/test/run/ok/for.run-ir.ok +++ b/test/run/ok/for.run-ir.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012345678910012345678910 diff --git a/test/run/ok/for.run-low.ok b/test/run/ok/for.run-low.ok index ac6ac408923..0b36fe95ae6 100644 --- a/test/run/ok/for.run-low.ok +++ b/test/run/ok/for.run-low.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012345678910012345678910 diff --git a/test/run/ok/for.run.ok b/test/run/ok/for.run.ok index ac6ac408923..0b36fe95ae6 100644 --- a/test/run/ok/for.run.ok +++ b/test/run/ok/for.run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012345678910012345678910 From 8317a92b2a66f7f3c59a74a1b891ae2696797cef Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 6 Feb 2019 10:29:56 +0100 Subject: [PATCH 3/5] Update test output for issue103, showing that it is fixed --- test/fail/ok/issue103.tc.ok | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index 1740e3ce0e3..d0f8ed19484 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -1,4 +1,8 @@ issue103.as:3.29-3.40: type error, shared function has non-shared parameter type () -> Nat +issue103.as:10.29-10.46: type error, shared function has non-shared parameter type + {foo : () -> Nat} issue103.as:17.29-17.40: type error, async type has non-shared parameter type () -> Nat +issue103.as:24.29-24.48: type error, async type has non-shared parameter type + {foo : () -> Nat} From efb7fdaf07acdc2ddcf43072860539eed4700765 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 6 Feb 2019 10:37:33 +0100 Subject: [PATCH 4/5] Update Syntax.md --- design/Syntax.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/Syntax.md b/design/Syntax.md index d60646ba5db..e3bd9a76101 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -7,7 +7,7 @@ Productions marked * probably deferred to later versions. ``` ::= type expressions ? constructor - (shared|actor)? { ;* } object + actor? { ;* } object [ var? ] array ? option (shared|class)? ? -> function @@ -109,7 +109,7 @@ Productions marked * probably deferred to later versions. expression let = immutable var (: )? = mutable - (new|object|actor|shared) ? =? { ;* } object + (new|object|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type actor? class ? (: )? =? class From 476ef56c39e97d348a15926a2d2f91afd2ccaa87 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 6 Feb 2019 14:47:10 +0100 Subject: [PATCH 5/5] Show that mutable fields make objects non-sharable --- test/fail/issue103.as | 28 ++++++++++++++++++++++++---- test/fail/ok/issue103.tc.ok | 14 ++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/test/fail/issue103.as b/test/fail/issue103.as index 2b60aa7d48c..e220fdc60d8 100644 --- a/test/fail/issue103.as +++ b/test/fail/issue103.as @@ -1,27 +1,47 @@ // A (non-shared) function is not sharable { - func invalid1 (f : shared (() -> Nat) -> ()) { + func invalid (f : shared (() -> Nat) -> ()) { f (func foo() : Nat = 1) }; }; // An object with function fields is not sharable { - func invalid2 (f : shared {foo : () -> Nat} -> ()) { + func invalid (f : shared {foo : () -> Nat} -> ()) { f (new { foo() : Nat = 1; }) }; }; +// An Object with a mutable field is not sharable +{ + func invalid (f : shared {var foo : Nat} -> ()) { + f { new { foo : Nat = 1; } } + }; +}; + // Cannot return a function in an async { - func invalid3 () : (async (() -> Nat)) { + func invalid () : (async (() -> Nat)) { async { func foo() : Nat = 1 } }; }; +// Cannot return an object with a mutable field in an async +{ + func invalid () : (async ({var foo : Nat})) { + async { new { foo : Nat = 1; } } + }; +}; // Cannot return an object with function fields in an async { - func invalid4 () : (async ({foo : () -> Nat})) { + func invalid () : (async ({foo : () -> Nat})) { async { new { foo() : Nat = 1; } } }; }; + +// Cannot return an object with a mutable field in an async +{ + func invalid () : (async ({var foo : Nat})) { + async { new { foo : Nat = 1; } } + }; +}; diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index d0f8ed19484..f1a19785956 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -1,8 +1,14 @@ -issue103.as:3.29-3.40: type error, shared function has non-shared parameter type +issue103.as:3.28-3.39: type error, shared function has non-shared parameter type () -> Nat -issue103.as:10.29-10.46: type error, shared function has non-shared parameter type +issue103.as:10.28-10.45: type error, shared function has non-shared parameter type {foo : () -> Nat} -issue103.as:17.29-17.40: type error, async type has non-shared parameter type +issue103.as:17.28-17.43: type error, shared function has non-shared parameter type + {foo : var Nat} +issue103.as:24.28-24.39: type error, async type has non-shared parameter type () -> Nat -issue103.as:24.29-24.48: type error, async type has non-shared parameter type +issue103.as:30.28-30.45: type error, async type has non-shared parameter type + {foo : var Nat} +issue103.as:37.28-37.47: type error, async type has non-shared parameter type {foo : () -> Nat} +issue103.as:44.28-44.45: type error, async type has non-shared parameter type + {foo : var Nat}