Go: Type Construction and Cycle Detection

The type checker constructs an internal representation
for each type it encounters while traversing the AST:
a process informally called type construction.
Type construction is naturally a depth-first process,
since completing a type requires its dependencies
to be completed first.
type T []U
type U *T
Recall that type completeness is a prerequisite
for deconstructing a type. In this case,
type construction never deconstructs a type,
it merely refers to types. In other words,
type completeness does not block type construction here.

Because type construction isn't blocked, the type checker
can simply delay such checks until the end of type checking,
when all types are complete (note that the checks
themselves also do not block type construction).
If a type were to reveal a type error,
it makes no difference when that error is reported
during type checking, only that it is reported eventually.
Instead of returning an incomplete value,
we return a special invalid operand, which signals
that the call expression could not be evaluated.
The rest of the type checker has special
handling for invalid operands.

IBM completed its acquisition of Confluent

2026 年 3 月, 官宣

Go: Allocating on the Stack

We generally double the size of the allocation
each time it fills up, so we can eventually append
most new tasks to the slice without allocation.
But there is a fair amount of overhead in the
"startup" phase when the slice is small.
During this startup phase we spend a lot of time
in the allocator, and produce a bunch of garbage,
which seems pretty wasteful.
func process4(c chan task, lengthGuess int) {
    var tasks []task
    if lengthGuess <= 10 {
        tasks = make([]task, 0, 10)
    } else {
        tasks = make([]task, 0, lengthGuess)
    }
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
func process(c chan task) {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
func extract3(c chan task) []task {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    tasks = runtime.move2heap(tasks)
    return tasks
}