I'm designing a language and was wondering how to incorporate C++-like references with regards to their place in the type system. I think they're useful for operations like indexing and dereferencing (
v[i] returns a reference that can be assigned to,
*pointer_type<a> returns a reference to an
a that behaves like an
Nominally in C++, a reference type like
int& and its original type
int are two distinct types. However, I believe that this is inconsistent with the rest of the type system: an
int& can be substituted for
int and they sometimes behave as they were the same type, and sometimes they don't, without explicit conversions (which is one of the reasons why references are used in the first place).
My solution would be for bindings and function arguments to essentially have a "secondary type", or rather another qualification with special rules, determining whether they are references or not. There would be two types in this secondary type system:
ref and non-
ref (default), and these labels would be written in places where other similar labels like
mut) would be -- mainly when introducing new bindings or in function types.
Thus, along with classical type mismatch errors, the compiler would report something like mismatched binding mechanism as well. For example this would happen if the programmer attempted to place a function which accepts a single integer by-reference into a list of functions which accept it by-copy (
ref a -> b vs.
a -> b). Although the functions would have the same type:
a -> b, the binding mechanisms are incompatible (because if passed lvalues that are later assigned to, unexpected incompatible behaviour could occur).
Does this solution make sense or is it better to just wrap it in the type system and suffer inconsistencies? Are there some negative side-effects that I'm not anticipating?
To clarify: the touching points between these two type systems would have special rules. For example, there would be implicit conversions from
ref to non-
ref while keeping the type invariant.