What is the explanation that instances of Data1 and Data2 have different capabilities?
The line where an object of Data1 class is instantiated compiles without a problem, but the line with Data2 get's the error saying that "right side must be a subtype of left side".
class Data1
let _x: U8 = 0
class Data2
let _x: U8
new create() => _x = 0
actor Main
new create(env: Env) =>
let d1: Data1 iso = Data1
let d2: Data2 iso = Data2
In Pony, there are many places where you can omit basic elements of syntax or structure, and expect them to be filled in with implicit defaults. The answer to your question here about the difference between
Data1
andData2
has to do with two examples of implicit defaults, which happen to not have the same capability.The
Data2
class has a single constructor,new create() => _x = 0
, which has a implicit default receiver capability ofref
. That is, it implicitly expands tonew ref create() => _x = 0
.The
Data1
class has no constructor, so Pony creates an implicit default constructor for you, which isnew iso create()
. The_x = 0
from your field declaration also gets implicitly transferred to the body of the constructor, but that's somewhat outside the scope of your question.So, in this case, assigning
let d1: Data1 iso = Data1
, since the created object will be of typeData1 iso^
, which can be assigned toData1 iso
. Assigninglet d2: Data2 iso = Data2
doesn't work, since the created object will be of typeData2 ref^
, which can't be assigned toData2 iso
without breaking the isolation guarantees.Changing your
Data2
constructor tonew iso create()
is the best solution for making your example code work. We don't useiso
as the implicit default capability for constructors because it would put additional constraints on the parameters to the constructor (they would all have to be sendable).For completeness, note that there is another way around your problem, on the caller side. If you place the constructor call in a
recover
block, you can "lift" to a capability that has stronger guarantees (for example, fromref
toiso
). This works because therecover
block enforces other constraints on object references used within it (for example, any references passing into the recover block must be sendable), that will uphold the guarantees you are lifting to. This assignment would look like: