<SeanTAllen>
im glad you are explaining jemc. i am very tired and was about to do a crappy job of it
<jemc>
you can think of a recover block as being an "isolated region" - it lets you construct a result as if it were isolated, but you can only use references with sendable (iso, val, or tag) caps to do it
<vassilvk>
right
<jemc>
in this case, your `x` reference has a type of `String ref` outside the isolated region - it will need to be converted to one of the sendable caps to be used in the isolated region
<vassilvk>
ah!
<vassilvk>
got it
<jemc>
you can't "lift" a `ref` to an `iso` or `val` (except by using already having used recover in the first place!), so it gets implicitly "dropped" to a `String tag` when you try to use it
<slfritchie>
Yeah ... a complaint that something has `tag` when you "know" damn well it doesn't ... probably means that it isn't sendable and you're trying to use it in a `recover` block.
<jemc>
so the trick is that anything non-sendable that you need to use within your `recover` block has to also originate in that block
<vassilvk>
Thanks, this makes sense (I don't recall seeing anything about the auto-drop-to-tag, maybe I mnissed it).
<jemc>
worth noting: there's some chatter about an upcoming RFC to make isolated regions themselves a first-class language feature, which would allow for some more advanced usage of the isolated regions concept than the simplified / heavy-handed behaviour that `recover` currently enforces
<vassilvk>
I see - thanks
_andre has quit [Quit: leaving]
<vassilvk>
Another (possibly even more noob question):
<vassilvk>
let x: String = String
<vassilvk>
Issues an error indicating that x is not with the same refcaps as String
<vassilvk>
Seems counterintuitive
<vassilvk>
I think I understand the reason - the constructor of String returns String ref, while String itself is defined with refcap of val...
<vassilvk>
...but still, looking at the code, it is not immediately clear what (if anything) is wrong with the expression
<vassilvk>
So, my question is, if a class type is defined with refcaps val, wouldn't that class constructor get a default refcap of val? If not, how do I know what is the default refcap of a class constructor? Is it always ref?
<jemc>
> how do I know what is the default refcap of a class constructor? Is it always ref?
<jemc>
(I was trying to find the link from the tutorial, but this particular point seems to be poorly documented there)
<jemc>
So, there are three kinds of "methods" - `fun` (synchronous), `be` (asynchronous), and `new` (constructor)
<jemc>
each has an implicit "receiver capability" if you don't specify one
<jemc>
they are `fun box`, `be ref`, and `new ref`, respectively
<jemc>
one exception is primitives, where the constructor must always be `new val`
<jemc>
(but primitive constructors are rarely needed in practice)
<jemc>
so, if you set up a class constructor (for example `new create`), it will be understood as `new ref create`
<vassilvk>
Yes, I've been messing around with primitives - I noticed that they had constructors which I found strange as I could not figure out what use case a primitive constructor might cover...I guess that's another topic
<vassilvk>
Got it
<jemc>
in the case of `String`, the *type* has a default capability of `val` because it's assumed that dealing with immutable strings is the most common case
<vassilvk>
Right
<jemc>
but the `new create` constructor makes a `ref`, because creating an empty immutable string isn't usually what you want
<vassilvk>
Makes sense
<jemc>
(and if you did want that, you can just use `""`)
<jemc>
so yeah, you end up with the case where `let x: String = String` doesn't compile, which is indeed a bit surprising until you dig into it
<jemc>
> I could not figure out what use case a primitive constructor might cover
<jemc>
the only place I've seen them used is for when you're using a primitive for object-capability-security
<jemc>
as you know, a primitive has no fields, is not heap allocated, and thus there's no need to actually construct anything at runtime
<jemc>
but these constructors are there to enforce a constraint purely at *compile time*
<jemc>
that is, the constraint that you must already hold an `AmbientAuth` to get your hands on a `NetAuth`
<jemc>
or similarly, you need to hold an `AmbientAuth` or a `NetAuth` to get your hand on a `TCPAuth`
<jemc>
(with the purpose being that someone can't create a library for you to use that secretly opens a socket when you never gave it the "permission" to do so in the form of one of these auth primitives)
<vassilvk>
Yep, I looked at examples where primitive constructors which take parameters are used (primarily looked at builtins like Boolean). However, when I played around with user-defined primitives it did seem excessive that the default primitive constructor was called on each assignment. Made no sense to me as I knew that there is no state to be modified or anything to be constructed to begin with.
<jemc>
so, even though these primitives are all still singletons, the compiler won't let you get a reference to that singleton "out of nothing" - you have to be explicitly handed the authority to do so
<jemc>
> it did seem excessive that the default primitive constructor was called on each assignment
<jemc>
excessive in what way?
<vassilvk>
Let me put together an example
<jemc>
(note that the builtin "machine word" primitives (numeric and boolean) are a bit of a special case, in that they map to machine words rather than singletons - by contrast the `net` package's auth primitives are very much like user-defined ones that you could use in a similar pattern)
<vassilvk>
Here I have a default constructor for a "singleton" entity which can have no state.
<jemc>
yeah, so I find that to be expected behaviour, in that the singleton nature of primitives is more of an optimization than a language-level concept.
<vassilvk>
The constructor is called on each assignment to the "singleton" although there is nothing to be constructed really.
<jemc>
That is, for consistency's sake a primitive acts the same way as a class with no fields at the language level
<jemc>
the only difference beeing that at the runtime detail level, it requires no heap allocation at all
<jemc>
remember that when you name a type `MyType` where an expression is expected, that's syntax sugar for calling `MyType.create()`
<jemc>
so I'd be more surprised to find that `create` wasn't actually getting called
<jemc>
if you're worried about runtime overhead for calling an empty constructor millions of times, you don't really need to worry about it because it will get optimized out during codegen
<vassilvk>
That was exactly my point - thanks. If optimization will take care of that, then I'm not worried anymore :)
<vassilvk>
(I was really thinking about all the assignments to None, etc.)
<jemc>
Yeah, so because the Pony compiler has access to all source code for your whole program at once (as opposed to something like linking object files together in a C project), it can aggressively inline functions where advantageous
<vassilvk>
Sounds good.
<jemc>
(or rather, LLVM does most of that heavy lifting for us, as long as the Pony compiler sets things up nicely in the LLVM IR)
<vassilvk>
Speaking of LLVM, I've heard that there are some issues with ponyc + LLVM 4 and above. What is the nature of those issues?
<vassilvk>
I'm asking because, as you know, I am able to use LLVM 6 to compile and link ponyc-generated IR on a number of platforms. I am wondering if there is anything to watch out for.
<vassilvk>
Thanks!
<jemc>
basically, we're missing out on some optimizations until we find that cause of that and fix it
gokr has quit [Ping timeout: 265 seconds]
acarrico has quit [Ping timeout: 260 seconds]
<jemc>
there aren't known actual stability issues for LLVM >= 4, but I think we chose to have the Makefile say `decreased performance or crashes` because the reason we added the performance decrease workaround was because of an unexpected crash
<jemc>
that is, as a way of avoiding the crash
<vassilvk>
Got it
<vassilvk>
jemc: thanks for all the info!
<jemc>
glad to help
<jemc>
especially given all the work you've done on the cross compile tooling - it's really valuable to the community and much appreciated