Closed kevinbarabash closed 1 year ago
Instead of adding a .binding
to struct Type {}
, we should do the following:
TypeKind::Mutable()
with TypeKind::Binding { mutable: boolean, t: Index }
This will allow us to differentiate between unbound types, mutable bound types, and immutable bound types. This provides us enough information to unify correctly and allow the results of a function call to be assigned to either a mutable or immutable variable.
This has been addressed by #634 and #635.
Instead of a Type being mutable or immutable, it's the binding that's mutable or immutable, including params in function definitions.
Functions return a type... it's only when that type gets assigned to a binding do we know whether that binding is mutable or not.
There is still a place for mutability in the type system it's just that the only way to introduce mutability is through is through a binding. Thus when inferring the type of something from a variable, we need to look at the mutability of the binding first.
Type
should have a.binding
field of typeOption<Binding>
. Types inferred from literals will have.binding
set toNone
. When unifying types, types without a binding can unify those with a binding. Those with a binding must check whether that binding is mutable or not and unify using the correct method or return an error when trying to use an immutable binding where a mutable binding is required.TODO:
mut
in eachmut
living outside the type is that it means we can still use type inference when usingmut
Some actual implementation steps:
mut
from type annotationsmut
to param bindings in function type annotations e.g. declare fn foo(mut xs: Array