Skip to content

Commit

Permalink
Merge pull request #307 from savi-lang/allow/non-sendable-params-iso-…
Browse files Browse the repository at this point in the history
…constructor-empty-object

Allow non-sendable params to an elevated constructor when the type has no fields.
  • Loading branch information
jemc authored Apr 22, 2022
2 parents 4d81979 + 0fccffa commit a3472d5
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 21 deletions.
42 changes: 26 additions & 16 deletions spec/compiler/type_check.validation.savi.spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,32 @@
pass: type_check
---

It complains if some params of an asynchronous function are not sendable:

```savi
:actor BadActor
:be bad_behavior(a String'ref, b String'val, c String'box)
```
```error
An asynchronous function must only have sendable parameters:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~
- this parameter type (String'ref) is not sendable:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~~~~~~~~~~~
- this parameter type (String'box) is not sendable:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~~~~~~~~~~~
```

---

It complains if some params of an elevated constructor are not sendable:

```savi
:let field String'ref: String.new
:new iso iso_constructor(a String'ref, b String'val, c String'box)
:new val val_constructor(a String'ref, b String'val, c String'box)
:new box box_constructor(a String'ref, b String'val, c String'box)
Expand Down Expand Up @@ -38,24 +61,11 @@ A constructor with elevated capability must only have sendable parameters:

---

It complains if some params of an asynchronous function are not sendable:
It allows non-sendable params to an elevated constructor if there are no fields:

```savi
:actor BadActor
:be bad_behavior(a String'ref, b String'val, c String'box)
```
```error
An asynchronous function must only have sendable parameters:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~
- this parameter type (String'ref) is not sendable:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~~~~~~~~~~~
- this parameter type (String'box) is not sendable:
:be bad_behavior(a String'ref, b String'val, c String'box)
^~~~~~~~~~~~
// (no fields)
:new iso iso_constructor(a String'ref, b String'val, c String'box)
```

---
Expand Down
12 changes: 7 additions & 5 deletions src/savi/compiler/type_check.cr
Original file line number Diff line number Diff line change
Expand Up @@ -769,11 +769,13 @@ class Savi::Compiler::TypeCheck
require_sendable =
if @func.has_tag?(:async)
"An asynchronous function"
elsif @func.has_tag?(:constructor) \
&& !MetaType.cap(Cap::REF).subtype_of?(ctx,
resolve(ctx, @pre_infer[ret]).not_nil!.cap_only
)
"A constructor with elevated capability"
elsif @func.has_tag?(:constructor)
ret_mt = resolve(ctx, @pre_infer[ret]).not_nil!
ret_rt = ret_mt.single_rt?.not_nil!
if !MetaType.cap(Cap::REF).subtype_of?(ctx, ret_mt.cap_only) \
&& ret_rt.defn(ctx).has_any_fields?
"A constructor with elevated capability"
end
end
if require_sendable
@func.params.try do |params|
Expand Down
4 changes: 4 additions & 0 deletions src/savi/program.cr
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ class Savi::Program
io << "#<#{self.class} #{@ident.value}>"
end

def has_any_fields?
@functions.any?(&.has_tag?(:field))
end

def find_func?(func_name)
@functions
.find { |f| f.ident.value == func_name && !f.has_tag?(:hygienic) }
Expand Down

0 comments on commit a3472d5

Please sign in to comment.