Repository: go
Issue: proposal: spec: immutable type qualifier
Labels: LanguageChange,Proposal,LanguageChangeReview

This issue describes a language feature proposal to **Immutable Types**. It targets the current [Go 1.x (> 1.11) language specification](https://golang.org/ref/spec) and doesn't violate [the Go 1 compatibility promise](https://golang.org/doc/go1compat). It also describes [an even better approach to immutability](https://github.com/romshark/Go-1-2-Proposal---Immutability#3-immutability-by-default-go--2x) for a hypothetical, backward-incompatible [Go 2 language specification](https://blog.golang.org/toward-go2).

The linked [Design Document](https://github.com/romshark/Go-1-2-Proposal---Immutability) describes the entire proposal in full detail, including the [current problems](https://github.com/romshark/Go-1-2-Proposal---Immutability#11-current-problems), the [benefits](https://github.com/romshark/Go-1-2-Proposal---Immutability#12-benefits), the [proposed changes](https://github.com/romshark/Go-1-2-Proposal---Immutability#2-proposed-language-changes), code examples and the [FAQ](https://github.com/romshark/Go-1-2-Proposal---Immutability#4-faq).

## Updates
- October 7th: This proposal is approaching its [second revision](https://github.com/romshark/Go-1-2-Proposal---Immutability/milestone/2) addressing major flaws such as [`const`-poisoning](https://github.com/golang/go/issues/27975#issuecomment-426458235), verbosity, `const`-keyword overloading and others.

## Introduction
Immutability is a technique used to prevent mutable shared state, which is a very common source of bugs, especially in concurrent environments, and can be achieved through the concept of **immutable types**.

Bugs caused by mutable shared state are not only hard to find and fix, but they're also hard to even identify. Such kind of problems can be avoided by systematically limiting the mutability of certain objects in the code. But a Go 1.x developer's current approach to immutability is manual copying, which lowers runtime performance, code readability, and safety. Copying-based immutability makes code verbose, [imprecise and ambiguous](https://github.com/romshark/Go-1-2-Proposal---Immutability#111-ambiguous-code-and-dangerous-bugs) because the intentions of the code author are never clear. Documentation can be rather [misleading](https://github.com/romshark/Go-1-2-Proposal---Immutability#112-vague-and-bloated-documentation) and doesn't solve the problems either.

## Immutable Types in Go 1.x
**Immutable types can help achieve this goal more elegantly** improving the safety, readability, and expressiveness of the code. They're based on 5 fundamental rules:

- **I.** Each and every type has an immutable counterpart.
- **II.** Assignments to objects of an immutable type are illegal.
- **III.** Calls to mutating methods (methods with a mutable receiver type) on objects of an immutable type are illegal.
- **IV.** Mutable types can be cast to their immutable counterparts, but not the other way around.
- **V.** Immutable interface methods must be implemented by a method with an immutable receiver type.

These rules can be enforced by making the compiler scan all objects of immutable types for illegal modification attempts, such as assignments and calls to mutating methods and fail the compilation. The compiler would also need to check, whether types correctly implement immutable interface methods.

To prevent breaking Go 1.x compatibility this document describes a **backward-compatible** approach to adding support for immutable types by overloading the `const` keyword ([see here for more details](https://github.com/romshark/Go-1-2-Proposal---Immutability#44-why-overload-the-const-keyword-instead-of-introducing-a-new-keyword-like-immutable-etc)) to act as an *immutable type qualifier*.

Immutable types can be used for:
- [immutable fields](https://github.com/romshark/Go-1-2-Proposal---Immutability#21-immutable-fields)
- [immutable methods](https://github.com/romshark/Go-1-2-Proposal---Immutability#22-immutable-methods)
- [immutable arguments](https://github.com/romshark/Go-1-2-Proposal---Immutability#23-immutable-arguments)
- [immutable return values](https://github.com/romshark/Go-1-2-Proposal---Immutability#24-immutable-return-values)
- [immutable variables](https://github.com/romshark/Go-1-2-Proposal---Immutability#25-immutable-variables)
- [immutable interfaces](https://github.com/romshark/Go-1-2-Proposal---Immutability#26-immutable-interface-methods)
- [immutable reference types and containers](https://github.com/romshark/Go-1-2-Proposal---Immutability#29-immutable-reference-types)
- [immutable package-scope variables](https://github.com/romshark/Go-1-2-Proposal---Immutability#210-immutable-package-scope-variables)

## Immutable Types in Go 2.x
Ideally, a safe programming language should enforce [immutability by default](https://github.com/romshark/Go-1-2-Proposal---Immutability#3-immutability-by-default-go--2x) where all types are immutable unless they're explicitly qualified as mutable because forgetting to make an object immutable is easier, than accidentally making it mutable. But this concept would require significant,
backward-incompatible language changes breaking existing Go 1.x code. Thus such an approach to immutability would only be possible in a new backward-incompatible Go 2.x language specification.

## Related Proposals
This proposal is somewhat related to:
- #20443
- #22876
- #22048

Detailed comparisons to other proposals are described in the [design document, section 5.](https://github.com/romshark/Go-1-2-Proposal---Immutability#5-other-proposals).

---

Please feel free to file [issues](https://github.com/romshark/Go-1-2-Proposal---Immutability/issues) and [pull requests](https://github.com/romshark/Go-1-2-Proposal---Immutability/pulls), become a [stargazer](https://github.com/romshark/Go-1-2-Proposal---Immutability/stargazers),
contact me directly at roman.scharkov@gmail.com and join the conversation on [Slack Gophers](https://gophers.slack.com) (@romshark), the [international](https://t.me/joinchat/BkBvqUQTWYNc170pxYOQJQ) and the [russian](https://t.me/gogolang) Telegram groups, as well as the original [golangbridge](https://forum.golangbridge.org/t/go-1-2-immutability-proposal/10613), [reddit](https://www.reddit.com/r/golang/comments/9kv2cc/proposal_go_12_immutable_types/) and [hackernews](https://news.ycombinator.com/item?id=18126176) posts! Thank you!