-
Notifications
You must be signed in to change notification settings - Fork 121
Rule out messages with abstract types in the type checker #247
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -380,6 +380,32 @@ let avoid cons t = | |
| if cons = ConSet.empty then t else | ||
| avoid' cons t | ||
|
|
||
| let is_concrete t = | ||
| let good_cons = ref ConSet.empty in (* break the cycles *) | ||
| let rec go = function | ||
| | (Prim _ | Var _ | Any | Non | Shared | Pre) -> true | ||
| | Con (c, ts) -> | ||
| if ConSet.mem c !good_cons | ||
| then true | ||
| else begin | ||
| match Con.kind c with | ||
| | Abs _ -> false | ||
| | Def (_,t) -> | ||
| good_cons := ConSet.add c !good_cons; go t | ||
| end | ||
| && List.for_all go ts | ||
| | Array t -> go t | ||
| | Tup ts -> List.for_all go ts | ||
| | Func (s, c, tbs, ts1, ts2) -> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should you not check the bounds are concrete or at least empty too?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right … I do that on terms, so I should do it on types.. Initially I thought I only check for occurrences, i.e. allow a shared function to be polymorphic as long as the type was not used, which would be fine, but useless and possibly confusing. |
||
| List.for_all go ts1 && | ||
| List.for_all go ts2 | ||
| | Opt t -> go t | ||
| | Async t -> go t | ||
| | Obj (s, fs) -> List.for_all (fun f -> go f.typ) fs | ||
| | Mut t -> go t | ||
| | Serialized t -> go t | ||
| in go t | ||
|
|
||
|
|
||
| (* Equivalence & Subtyping *) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // check that types with non-concrete types in messages are rejected | ||
| { let x : ?(shared <A <: Shared>A -> ()) = null; }; | ||
| { let x : ?(shared <A <: Shared>() -> A) = null; }; | ||
| { let x : ?(<A <: Shared>(shared A -> ()) -> ()) = null; }; | ||
| { let x : ?(<A <: Shared>(shared () -> async A) -> ()) = null; }; | ||
|
|
||
| // Type aliases can have message arguments with type variables, | ||
| // as long as they are instantiated with concrete types | ||
| // So this whould be fine: | ||
| { type X<B> = shared B -> (); let x : ?(X<Int>) = null; }; | ||
|
|
||
| // But this not | ||
| { type X<B> = shared B -> (); let x : ?(<A <: Shared>X<A> -> ()) = null; }; | ||
|
|
||
| // check that functions with non-concrete types in messages are rejected | ||
| { shared func foo<A <: Shared>( x : A ) : () = (); }; | ||
| { shared func foo<A <: Shared>() : ?A = null; }; | ||
| { func foo<A <: Shared>() : () = { | ||
| { shared func bar( x : A ) : () = (); }; | ||
| { shared func bar() : ?A = null; }; | ||
| }}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| func call3<B <: Shared>(f : shared () -> async B) : async B { f(); }; | ||
| func call3(f : shared () -> async Int) : async Int { f(); }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| shared func call4<B <: Shared>(f : shared () -> async B) : async B = f(); | ||
| shared func call4(f : shared () -> async Int) : async Int = f(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| abstract-msgs.as:2.13-2.40: type error, shared functions cannot be polymorphic | ||
| abstract-msgs.as:3.13-3.40: type error, shared functions cannot be polymorphic | ||
| abstract-msgs.as:4.34-4.35: type error, shared function parameter contains abstract type | ||
| A/2 | ||
| abstract-msgs.as:5.40-5.47: type error, shared function result contains abstract type | ||
| A/3 | ||
| abstract-msgs.as:8.48-8.50: type error, shared functions cannot be polymorphic | ||
| abstract-msgs.as:9.41-9.45: type error, shared functions cannot be polymorphic | ||
| abstract-msgs.as:11.22-11.27: type error, shared function parameter contains abstract type | ||
| A/9 | ||
| abstract-msgs.as:12.25-12.27: type error, shared function has non-async result type | ||
| ?A/9 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| asyncret1.as:1.36-1.38: type error, shared function has non-async result type | ||
| asyncret1.as:1.42-1.43: type error, shared function has non-async result type | ||
| C |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| asyncret2.as:1.63-1.66: type error, expression of type | ||
| async B/1 | ||
| asyncret2.as:1.54-1.57: type error, expression of type | ||
| async Int | ||
| cannot produce expected type | ||
| B/1 | ||
| Int |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| asyncret3.as:1.70-1.73: type error, shared function with async type has non-async body | ||
| asyncret3.as:1.61-1.64: type error, shared function with async type has non-async body |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,4 @@ Top-level code done. | |
| 0_1 | ||
| 0_2 | ||
| 0_3 | ||
| !!<Int> | ||
| <()> | ||
| <(Int,Bool)> | ||
| !! | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,4 @@ | |
| 0_1 | ||
| 0_2 | ||
| 0_3 | ||
| !!<Int> | ||
| <()> | ||
| <(Int,Bool)> | ||
| !! | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,4 @@ | |
| 0_1 | ||
| 0_2 | ||
| 0_3 | ||
| !!<Int> | ||
| <()> | ||
| <(Int,Bool)> | ||
| !! | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,4 @@ | |
| 0_1 | ||
| 0_2 | ||
| 0_3 | ||
| !!<Int> | ||
| <()> | ||
| <(Int,Bool)> | ||
| !! | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless you only use this on opened types, you may want to return false in the Var _ case, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, that part of probably not right yet. I thought I can work on types without opening, but that would allow hiding a non-concrete type somewhere inside. Will have to come up with a test case and revise.
I fact, why does it even complain about
then?
Well, tomorrow…