Mutabiity inference is probably the most complex thing we attempted in
BitC, and we got it wrong. I think the *issues* aren't hard to summarize:

1. When a constituent field of an object is "immutable", but the entire
object is not, what does that mean? The choices are: (a) it prevents any
assignment that would cause the corresponding *location* to change, or (b)
the property holds only for the lifetime of the containing object.  In the
presence of unboxed types and concurrency, these two definitions are very,
very different.
2. Is mutation a property of a location, or a type, or is the thing we
really care about more a statement about behavior?

In hindsight, I now think that the property I was really trying to grapple
with might be described more accurately as "invariance". We have some
object that is evolving, and at some point it becomes desirable to say two
kinds of things:

1. Certain parts of the object will not change for the remainder of the
object's lifetime. The cases that seem *useful* seem to be closely related
to notions of typestate.
2. Certain parts of a (passed) object will not *be* changed by a given
procedure.

As a naive example, it can be useful if the *value* in a list element is
mutable but the next pointer is not. This guarantees that if you hold a
pointer to a list, the length of that list does not change.

This notion of invariant seems to me to have much the same
"metaconstructor" feel that the current const/mutable notions have in BitC,
except that it seems to me that we want to be able to use explicit labels
here to support unification. In particular, *some* lists want to have
unchanging length, but not all of them. Should this be two distinct types,
or should the list type be designed in such a way that we can specify at
construction time whether the value field is invariant?

I'm very much at a loss about how to think about this. I would appreciate
input. The cases that are compile-time invariant [shallowly or deeply] seem
pretty straightforward. The cases that involve mixed invariance seem more
complicated. So some questions:

1. Is this worth it? It seems to be driven by the desire to mix imperative
and pure programming without an explosion of type definition variations
(due to case analysis getting embedded at the type level).
2. How do we think about object sharing across concurrency *without* some
ability to talk about this?
3. Any pointers on things I might read?


Jonathan
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to